golang/go · error

crypto/rsa: use of PKCS#1 v1.5 encryption is not allowed in

Error message

crypto/rsa: use of PKCS#1 v1.5 encryption is not allowed in FIPS 140-only mode

What it means

Returned by EncryptPKCS1v15 the moment FIPS 140-only mode is enforced. PKCS#1 v1.5 encryption is deterministic-ish and vulnerable to Bleichenbacher-style padding-oracle attacks, so FIPS 140-3 drops it from the approved-algorithm set; the Go library makes the function a hard failure rather than silently operating. The function is also marked Deprecated for non-FIPS reasons (see draft-irtf-cfrg-rsa-guidance).

Source

Thrown at src/crypto/rsa/pkcs1v15.go:52

// EncryptPKCS1v15 encrypts the given message with RSA and the padding
// scheme from PKCS #1 v1.5.  The message must be no longer than the
// length of the public modulus minus 11 bytes.
//
// The random parameter is used as a source of entropy to ensure that encrypting
// the same message twice doesn't result in the same ciphertext. Since Go 1.26,
// a secure source of random bytes is always used, and the Reader is ignored
// unless GODEBUG=cryptocustomrand=1 is set. This setting will be removed in a
// future Go release. Instead, use [testing/cryptotest.SetGlobalRandom].
//
// Deprecated: PKCS #1 v1.5 encryption is dangerous and should not be used.
// See [draft-irtf-cfrg-rsa-guidance-05] for more information. Use
// [EncryptOAEP] and [DecryptOAEP] instead.
//
// [draft-irtf-cfrg-rsa-guidance-05]: https://www.ietf.org/archive/id/draft-irtf-cfrg-rsa-guidance-05.html#name-rationale
func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
	if fips140only.Enforced() {
		return nil, errors.New("crypto/rsa: use of PKCS#1 v1.5 encryption is not allowed in FIPS 140-only mode")
	}

	if err := checkPublicKeySize(pub); err != nil {
		return nil, err
	}

	k := pub.Size()
	if len(msg) > k-11 {
		return nil, ErrMessageTooLong
	}

	if boring.Enabled && rand.IsDefaultReader(random) {
		bkey, err := boringPublicKey(pub)
		if err != nil {
			return nil, err
		}
		return boring.EncryptRSAPKCS1(bkey, msg)
	}

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Switch to rsa.EncryptOAEP(sha256.New(), rand.Reader, pub, msg, nil) — the FIPS-approved replacement.
  2. If the peer only supports PKCS#1 v1.5, renegotiate the protocol (JWE alg from RSA1_5 to RSA-OAEP-256, legacy SAML/XML-Enc profiles, etc.).
  3. As a last resort, drop GODEBUG=fips140=only — but only after a risk review, since it disables FIPS compliance globally.

Example fix

// before
ct, err := rsa.EncryptPKCS1v15(rand.Reader, pub, msg)

// after
ct, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, pub, msg, nil)
Defensive patterns

Strategy: fallback

Validate before calling

func encryptFIPS(pub *rsa.PublicKey, msg []byte) ([]byte, error) {
    // Always OAEP — never PKCS1v15.
    return rsa.EncryptOAEP(sha256.New(), rand.Reader, pub, msg, nil)
}

Try / catch

ct, err := rsa.EncryptPKCS1v15(rand.Reader, pub, msg)
if err != nil {
    if errors.Is(err, errors.New("crypto/rsa: use of PKCS#1 v1.5 encryption is not allowed in FIPS 140-only mode")) {
        // fall back to OAEP only if the peer can handle it
        ct, err = rsa.EncryptOAEP(sha256.New(), rand.Reader, pub, msg, nil)
    }
}

Prevention

When it happens

Trigger: Call rsa.EncryptPKCS1v15(rand.Reader, pub, msg) in a binary running with GODEBUG=fips140=only; transitively reach it through legacy code that wraps RSA key transport with v1.5 padding; using a third-party library (e.g. older JWT or JWE libs) that internally calls EncryptPKCS1v15.

Common situations: A service that previously ran in non-FIPS Go gets rebuilt or redeployed with FIPS-only enabled (compliance mandate) and now fails on existing RSA-encrypted payloads; integration with a peer system that only supports RSAES-PKCS1-v1_5.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/e95b93908bd04abd. Report an issue: GitHub.