OpenNHP/opennhp · error

failed to create AES cipher

Error message

failed to create AES cipher: %w

What it means

AeadFromKey(GCM_AES256, key) wraps the error from aes.NewCipher(key[:]) when the key material cannot form an AES block cipher. Go's crypto/aes only fails when the key length is not 16, 24, or 32 bytes; since key is a *[SymmetricKeySize]byte (32 bytes), this error indicates the caller supplied a nil pointer, mis-sized buffer, or corrupted key derivation. It is a programming/key-derivation bug signal, not a runtime network condition.

Solutions

  1. Ensure the key array is fully populated by a successful ECDH/SharedSecret + KDF before calling AeadFromKey
  2. Check the wrapped error — with a fixed-size array it points to dependency-level or pointer-level problems
  3. Verify SymmetricKeySize is 32 (AES-256) and unchanged in your build
  4. Add a caller-side assert that the key is non-zero before use
  5. Run the cipher-suite tests (go test ./nhp/core/...) to reproduce with known-good keys

Example fix

// before
key := &[core.SymmetricKeySize]byte{}
aead, err := core.AeadFromKey(core.GCM_AES256, key)
// after
shared := ecdh.SharedSecret(peerPub)
if len(shared) == 0 {
    return errors.New("key exchange produced empty shared secret")
}
var key [core.SymmetricKeySize]byte
utils.Memcpy(key[:], kdf(shared))
aead, err := core.AeadFromKey(core.GCM_AES256, &key)
if err != nil {
    return fmt.Errorf("aead init: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if key == nil {
    return errors.New("symmetric key not initialized")
}
if core.SymmetricKeySize != 16 && core.SymmetricKeySize != 24 && core.SymmetricKeySize != 32 {
    return fmt.Errorf("SymmetricKeySize %d is not a valid AES key length", core.SymmetricKeySize)
}

Try / catch

aead, err := core.AeadFromKey(core.GCM_AES256, &key)
if err != nil {
    return fmt.Errorf("AES-GCM setup failed: %w", err)
}
// use aead.Seal / aead.Open only after this succeeds

Prevention

When it happens

Trigger: Calling AeadFromKey with a *[SymmetricKeySize]byte that was never filled (all code paths normally pass exactly 32 bytes), or future refactors that change SymmetricKeySize to a non-AES-legal length, or passing a key derived from an ECDH shared-secret routine that returned garbage/empty data.

Common situations: A key-exchange step silently failed earlier and left the symmetric key zero-length or mis-sized; custom code constructs the array via unsafe casting of a shorter byte slice; tests exercising GCM with a stubbed key.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07). Data as JSON: /api/errors/b54fd115401c348c. Report an issue: GitHub.

Appendix: source

Thrown at nhp/core/crypto.go:156

func NewECDH(t EccTypeEnum) (e Ecdh) {
	switch t {
	case ECC_CURVE25519:
		e = curve.NewECDH()

	case ECC_SM2:
		e = gmsm.NewECDH()
	}

	return e
}

func AeadFromKey(t GcmTypeEnum, key *[SymmetricKeySize]byte) (cipher.AEAD, error) {
	switch t {
	case GCM_AES256:
		aesBlock, err := aes.NewCipher(key[:])
		if err != nil {
			return nil, fmt.Errorf("failed to create AES cipher: %w", err)
		}
		aead, err := cipher.NewGCM(aesBlock)
		if err != nil {
			return nil, fmt.Errorf("failed to create AES-GCM: %w", err)
		}
		return aead, nil

	case GCM_SM4:
		sm4Block, err := sm4.NewCipher(key[:16])
		if err != nil {
			return nil, fmt.Errorf("failed to create SM4 cipher: %w", err)
		}
		aead, err := cipher.NewGCM(sm4Block)
		if err != nil {
			return nil, fmt.Errorf("failed to create SM4-GCM: %w", err)
		}
		return aead, nil

View on GitHub (pinned to 6e04ca5ff0)