{"record":{"id":"716522da723907cc","repo":"OpenNHP/opennhp","slug":"extractinitiatorstaticpubkey-init-hash-w","errorCode":null,"errorMessage":"extractInitiatorStaticPubKey: init hash: %w","messagePattern":"extractInitiatorStaticPubKey: init hash: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nhp/core/responder.go","lineNumber":155,"sourceCode":"\t// in a throwaway hash that never leaks back to ppd).\n\tchainHash, err := NewHash(ciphers.HashType)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"extractInitiatorStaticPubKey: chain hash: %w\", err)\n\t}\n\tchainHash.Write([]byte(InitialHashString))\n\tchainHash.Write(deviceEcdh.PublicKey())\n\tchainHash.Write(header.EphermeralBytes())\n\n\t// Local chain key: ChainKey0 = MixKey(InitialHash, InitialChainKey)\n\t// then ChainKey0 → ChainKey1 via ess.\n\tvar noise NoiseFactory\n\tnoise.HashType = ciphers.HashType\n\tvar chainKey [SymmetricKeySize]byte\n\tdefer SetZero(chainKey[:])\n\t// ChainKey0\n\tinitHash, err := NewHash(ciphers.HashType)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"extractInitiatorStaticPubKey: init hash: %w\", err)\n\t}\n\tinitHash.Write([]byte(InitialHashString))\n\tnoise.MixKey(&chainKey, initHash.Sum(nil), []byte(InitialChainKeyString))\n\t// ChainKey0 → ChainKey1\n\tnoise.MixKey(&chainKey, chainKey[:], header.EphermeralBytes())\n\n\t// Derive AEAD key for static-field decryption.\n\tvar key [SymmetricKeySize]byte\n\tdefer SetZero(key[:])\n\tnoise.KeyGen2(&chainKey, &key, chainKey[:], ess[:])\n\n\taead, err := AeadFromKey(ciphers.GcmType, &key)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"extractInitiatorStaticPubKey: aead: %w\", err)\n\t}\n\t// Trust the AEAD's returned plaintext length over a static\n\t// scheme→size mapping. The previous version allocated a\n\t// PublicKeySizeEx-sized buffer and sliced it back down based on","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/nhp/core/responder.go#L137-L173","documentation":"extractInitiatorStaticPubKey is the responder-side helper that re-derives the Noise IK key chain to decrypt the initiator's static public key from the packet header. This error wraps a failure from NewHash, i.e. the configured hash algorithm (BLAKE2s for CURVE, SM3 for GMSM) could not be instantiated. In practice this only happens if the CipherSuite's HashType is invalid or the crypto backend failed to initialize, since both supported hash types are always compiled in.","triggerScenarios":"Calling checkHMAC on an RKN packet under server overload when ciphers.HashType holds an unsupported value — e.g. a CipherSuite constructed with a scheme value outside CIPHER_SCHEME_CURVE/CIPHER_SCHEME_GMSM, or a crypto provider regression that makes hash instantiation fail.","commonSituations":"A hand-built CipherSuite passed into device code with a zero/garbage HashType; a build with a modified crypto backend where the SM3 or BLAKE2s implementation fails to register; effectively never hit with the stock two supported cipher schemes.","solutions":["Verify the CipherSuite passed in comes from NewCipherSuite with a valid common.CIPHER_SCHEME_* constant (0=CURVE, 1=GMSM), not a hand-populated struct.","Check the version of the crypto/hash package backing NewHash for regressions; rebuild from a known-good tag.","Log the full CipherSuite (HashType, GcmType) at the call site of checkHMAC to confirm the scheme matches the packet header's CipherScheme field.","If a custom cipher scheme was added, implement its HashType in NewHash/NewCipherSuite before routing packets with that scheme."],"exampleFix":"// before\nsuite := &core.CipherSuite{HashType: unknownHash, GcmType: unknownGcm}\nppd.checkHMAC(sumCookie) // extractInitiatorStaticPubKey: init hash: ...\n// after\nsuite := core.NewCipherSuite(common.CIPHER_SCHEME_CURVE) // valid scheme\nppd.checkHMAC(sumCookie)","handlingStrategy":"validation","validationCode":"if suite.HashType == 0 || (suite.HashType != hashCurve && suite.HashType != hashGmsm) {\n\treturn fmt.Errorf(\"unsupported hash type %d for cipher suite\", suite.HashType)\n}","typeGuard":"func isValidCipherSuite(c *core.CipherSuite) bool {\n\treturn c != nil && (c.GcmType == common.CIPHER_SCHEME_CURVE || c.GcmType == common.CIPHER_SCHEME_GMSM)\n}","tryCatchPattern":"peerPk, err := extractInitiatorStaticPubKey(dev, suite, hdr)\nif err != nil {\n\tlog.Error(\"static key extraction failed: %v\", err)\n\treturn ErrServerHMACCheckFailed // fail closed, never bypass the cookie path\n}","preventionTips":["Always build CipherSuites via NewCipherSuite with a documented CIPHER_SCHEME_* constant.","Add a unit test instantiating NewHash for every supported scheme.","Never persist or hand-edit HashType/GcmType values in config.","Fail closed: treat hash-init errors as fatal startup issues, not per-packet retries."],"tags":["go","cryptography","noise-protocol","hash-init"],"backgroundTag":"invalid-enum-value","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}