CRITICAL bleichenbacher attackchigo

Bleichenbacher Attack in Chi (Go)

Bleichenbacher Attack in Chi with Go — how this specific combination creates or exposes the vulnerability

The Bleichenbacher attack (CVE-1998-0609) exploits padding oracle vulnerabilities in RSA PKCS#1 v1.5 decryption, allowing attackers to decrypt ciphertexts or forge signatures by observing server responses to malformed inputs. In Go applications using the Chi router, this vulnerability can surface when handling RSA-decrypted values (e.g., JWTs, encrypted cookies, or API tokens) without proper constant-time validation. Chi’s middleware chain does not automatically protect against timing side-channels; if a handler uses Go’s crypto/rsa package to decrypt user-controlled input and leaks timing differences via HTTP status codes or response times, an attacker can iteratively refine ciphertexts to recover plaintext.

For example, a Chi route that decrypts an RSA-encrypted token from a header and returns 400 Bad Request on padding errors but 200 OK on valid padding creates a padding oracle. Attackers can send crafted ciphertexts and measure response timing or status to distinguish valid from invalid padding, eventually decrypting sensitive data. This is exacerbated in Go because crypto/rsa.DecryptPKCS1v15 is not constant-time by default, and Chi does not wrap handlers in timing-safe decorators. The combination of Chi’s flexible handler pattern and Go’s RSA usage creates an exploitable surface when developers assume routing frameworks implicitly secure cryptographic operations.

Go-Specific Remediation in Chi — concrete code fixes

To mitigate Bleichenbacher attacks in Chi-based Go applications, replace crypto/rsa.DecryptPKCS1v15 with constant-time alternatives and avoid exposing decryption outcomes via side-channels. Use crypto/rsa.DecryptOAEP with SHA-256, which is resistant to padding oracles, or implement constant-time validation for PKCS#1 v1.5 if legacy support is required. The following example shows a secure Chi middleware that validates RSA-OAEP decryption without leaking timing information:

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"net/http"

	"github.com/go-chi/chi/v5"
)

func RSAOAEPDecryptMiddleware(privateKey *rsa.PrivateKey) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			encToken := r.Header.Get("X-Encrypted-Token")
			if encToken == "" {
				http.Error(w, "missing token", http.StatusBadRequest)
				return
			}

			ciphertext, err := decodeBase64URL(encToken)
			if err != nil {
				http.Error(w, "invalid token encoding", http.StatusBadRequest)
				return
			}

			// Constant-time decryption using OAEP
			plaintext, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, ciphertext, nil)
			if err != nil {
				// Do not leak error details; return generic error
				http.Error(w, "invalid token", http.StatusBadRequest)
				return
			}

			// Attach decrypted token to context for handlers
			ctx := r.Context()
			ctx = context.WithValue(ctx, "decryptedToken", plaintext)
			next.ServeHTTP(w, r.WithContext(ctx))
		})
	}
}

func decodeBase64URL(s string) ([]byte, error) {
	// Add padding if needed
	switch len(s) % 4 {
	case 2:
		s += "=="
	case 3:
		s += "="
	}
	return base64.URLEncoding.DecodeString(s)
}

func main() {
	privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)

	r := chi.NewRouter()
	tr.Use(RSAOAEPDecryptMiddleware(privateKey))
	tr.Get("/secure", func(w http.ResponseWriter, r *http.Request) {
		token := r.Context().Value("decryptedToken").([]byte)
		w.Write(token)
	})

	http.ListenAndServe(":8080", r)
}

Key mitigations: 1) OAEP padding prevents adaptive chosen-ciphertext attacks; 2) Error messages are generic (invalid token) to avoid oracle leakage; 3) No timing differences between error paths. For legacy PKCS#1 v1.5 use, implement constant-time validation via bitwise comparison (not shown here due to complexity; prefer OAEP). Chi’s middleware pattern enables centralized, consistent application of these controls across routes.

Frequently Asked Questions

Does Chi automatically protect against Bleichenbacher attacks?
No. Chi is a routing and middleware framework that does not include cryptographic safeguards. Developers must explicitly use constant-time decryption (e.g., RSA-OAEP) and avoid leaking decryption errors via HTTP responses or timing side-channels.
Can I still use RSA PKCS#1 v1.5 in Go if I switch to constant-time validation?
Technically yes, but it is error-prone and not recommended. RSA-OAEP with SHA-256 is the preferred, simpler, and more secure alternative. If PKCS#1 v1.5 is required for compatibility, use a vetted constant-time library (e.g., crypto/subtle) for padding validation, but prefer migrating to OAEP where possible.