OpenNHP/opennhp · error
extractInitiatorStaticPubKey: aead
Error message
extractInitiatorStaticPubKey: aead: %w
What it means
After deriving the AEAD key (KeyGen2 from the Noise chain key and ephemeral shared secret), extractInitiatorStaticPubKey builds an AEAD instance via AeadFromKey using ciphers.GcmType (AES-256-GCM or SM4-GCM). This error means the AEAD construction itself failed — the key material was fine size-wise but the GcmType is not a recognized AEAD algorithm, or the AEAD backend could not accept the key.
Solutions
- Ensure the CipherSuite originates from NewCipherSuite(common.CIPHER_SCHEME_CURVE|GMSM) so HashType/GcmType are consistent with what AeadFromKey supports.
- Confirm both AES-GCM and SM4-GCM backends are compiled in for your build tags if using the GMSM scheme.
- Log ciphers.GcmType alongside the wrapped error to see which unsupported value reached AeadFromKey.
- If adding a new cipher scheme, register its AEAD constructor in AeadFromKey before deploying senders that use it.
Example fix
// before
suite := &core.CipherSuite{HashType: ht, GcmType: 99} // unsupported
peerPk, err := extractInitiatorStaticPubKey(dev, suite, hdr)
// after
suite := core.NewCipherSuite(common.CIPHER_SCHEME_GMSM)
peerPk, err := extractInitiatorStaticPubKey(dev, suite, hdr) Defensive patterns
Strategy: validation
Validate before calling
switch suite.GcmType {
case common.CIPHER_SCHEME_CURVE, common.CIPHER_SCHEME_GMSM:
// ok
default:
return fmt.Errorf("unsupported gcm type %d", suite.GcmType)
} Type guard
func hasKnownAead(c *core.CipherSuite) bool {
return c != nil && c.GcmType == common.CIPHER_SCHEME_CURVE || (c != nil && c.GcmType == common.CIPHER_SCHEME_GMSM)
} Try / catch
aead, err := AeadFromKey(ciphers.GcmType, &key)
if err != nil {
log.Error("aead init failed gcmType=%d: %v", ciphers.GcmType, err)
return nil, err // abort packet, do not fall through to cookie verification
} Prevention
- Construct cipher suites only through NewCipherSuite.
- Keep AES-GCM and SM4-GCM backends compiled into your build.
- Test AeadFromKey for all schemes at daemon startup.
- Log GcmType on failure to speed diagnosis.
When it happens
Trigger: checkHMAC on an overload-path RKN packet where the CipherSuite's GcmType is not one of the registered GCM implementations (e.g. CipherSuite built manually with an unsupported GcmType constant), or an SM4/AES backend initialization failure in the crypto package.
Common situations: Mixing cipher scheme constants between builds (scheme table changed between versions so old persisted config maps to a GcmType that no longer exists); a custom crypto plugin returning an unsupported GcmType; corrupted in-memory CipherSuite.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- extractInitiatorStaticPubKey: open
- invalid input key
- failed to create AES-GCM
- missing remote peer public key
- extractInitiatorStaticPubKey: init hash
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/48211cec52c5bcb4.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/responder.go:169
defer SetZero(chainKey[:])
// ChainKey0
initHash, err := NewHash(ciphers.HashType)
if err != nil {
return nil, fmt.Errorf("extractInitiatorStaticPubKey: init hash: %w", err)
}
initHash.Write([]byte(InitialHashString))
noise.MixKey(&chainKey, initHash.Sum(nil), []byte(InitialChainKeyString))
// ChainKey0 → ChainKey1
noise.MixKey(&chainKey, chainKey[:], header.EphermeralBytes())
// Derive AEAD key for static-field decryption.
var key [SymmetricKeySize]byte
defer SetZero(key[:])
noise.KeyGen2(&chainKey, &key, chainKey[:], ess[:])
aead, err := AeadFromKey(ciphers.GcmType, &key)
if err != nil {
return nil, fmt.Errorf("extractInitiatorStaticPubKey: aead: %w", err)
}
// Trust the AEAD's returned plaintext length over a static
// scheme→size mapping. The previous version allocated a
// PublicKeySizeEx-sized buffer and sliced it back down based on
// header.CipherScheme(); that worked because the only two ciphers
// today happen to match the scheme→size table exactly, but a
// future cipher whose plaintext length doesn't fit either fixed
// size would silently mis-key the cookie HMAC (Open writes
// however many bytes the AEAD decrypted, then the caller would
// either truncate them or hash trailing zero-padding).
//
// Validate the length explicitly before returning so future
// breakage manifests as an error here, not as cookie failures
// further down. Pass nil for the dst so Open allocates exactly
// the right size.
peerPk, err := aead.Open(nil, header.NonceBytes(), header.StaticBytes(), chainHash.Sum(nil))
if err != nil {
return nil, fmt.Errorf("extractInitiatorStaticPubKey: open: %w", err)View on GitHub (pinned to 6e04ca5ff0)