golang/go · critical

invalid ASN.1 from SignASN1

Error message

invalid ASN.1 from SignASN1

What it means

Thrown by the r,s-from-sig re-parser in ecdsa_legacy.go:83 when the signature bytes returned by the FIPS SignASN1 do not reparse as a clean SEQUENCE { INTEGER r, INTEGER s }. This is effectively an internal consistency failure: the library just produced bytes that fail cryptobyte ASN.1 validation. It should not be reachable in normal operation.

Source

Thrown at src/crypto/ecdsa/ecdsa_legacy.go:83

// The signature is randomized. 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].
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
	sig, err := SignASN1(rand, priv, hash)
	if err != nil {
		return nil, nil, err
	}

	r, s = new(big.Int), new(big.Int)
	var inner cryptobyte.String
	input := cryptobyte.String(sig)
	if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
		!input.Empty() ||
		!inner.ReadASN1Integer(r) ||
		!inner.ReadASN1Integer(s) ||
		!inner.Empty() {
		return nil, nil, errors.New("invalid ASN.1 from SignASN1")
	}
	return r, s, nil
}

func signLegacy(priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err error) {
	if fips140only.Enforced() {
		return nil, errors.New("crypto/ecdsa: use of custom curves is not allowed in FIPS 140-only mode")
	}

	c := priv.Curve

	// A cheap version of hedged signatures, for the deprecated path.
	var seed [32]byte
	if _, err := io.ReadFull(csprng, seed[:]); err != nil {
		return nil, err
	}
	for i, b := range priv.D.Bytes() {
		seed[i%32] ^= b

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Rebuild with a clean, consistent toolchain (go clean -cache; go build) to rule out stale/partially-compiled crypto packages.
  2. Report as a bug to the Go/crypto maintainers with a reproducer if it persists with valid inputs — this path is an invariant check, not an input error.
  3. Ensure GOEXPERIMENT=fips140 toolchain matches the stdlib version (no mixing of versions).
Defensive patterns

Strategy: try-catch

Try / catch

r, s, err := ecdsa.SignLegacyToRS(...) // or equivalent ASN.1 reparse
if err != nil {
    if strings.Contains(err.Error(), "invalid ASN.1 from SignASN1") {
        // internal invariant failure: clean rebuild, report upstream
        _ = goCleanCache()
    }
    return err
}

Prevention

When it happens

Trigger: Reaching this requires the FIPS SignASN1 path to return bytes that are not a well-formed ECDSA-Sig-Value ASN.1 structure. In practice only seen with a corrupted build, a buggy nistec/fips shim, or memory corruption — never with correct inputs.

Common situations: Reproduce only under a broken FIPS backend, mismatched internal package versions after a partial upgrade, or fuzzing that hit an unexpected nistec state.

Related errors


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