OpenNHP/opennhp · error
failed to create HMAC hash
Error message
failed to create HMAC hash: %w
What it means
createMsgAssemblerData initializes the HMAC hash (HmacHash0) used for message-chain MACs. This error means NewHash failed for the negotiated HashType at the HMAC stage — same class as the chain-hash failure but occurring after it. It points to an invalid or unsupported hash type in the cipher suite.
Solutions
- Use a predefined CipherSuites constant instead of hand-assembling the struct
- Verify the HashType value is supported (BLAKE2s for CURVE, SM3 for GMSM)
- Keep chain-hash and HMAC hash creation consistent by setting HashType once from the scheme
- Add a unit test calling createMsgAssemblerData with your configured suite
Example fix
// before
ciphers := &nhpcore.CipherSuites{EccType: nhpcore.ECC_CURVE25519} // HashType unset
// after
ciphers := &nhpcore.CipherSuites{EccType: nhpcore.ECC_CURVE25519, HashType: nhpcore.HASH_TYPE_BLAKE2S} Defensive patterns
Strategy: validation
Validate before calling
if md.Ciphers.HashType == 0 {
return errors.New("HashType unset")
} Type guard
func hasHashType(c *nhpcore.CipherSuites) bool { return c.HashType != 0 } Try / catch
if _, err := dev.MsgToPacket(md); err != nil && strings.Contains(err.Error(), "failed to create HMAC hash") {
return fmt.Errorf("invalid cipher suite: %w", err)
} Prevention
- Set HashType once from the scheme constant and share it across all hash uses
- Keep suite construction centralized in one constructor function
- Add a round-trip unit test through createMsgAssemblerData
When it happens
Trigger: Same as the chain-hash error but reached when chain hash creation succeeded: createMsgAssemblerData called with a ciphers.HashType that the crypto layer cannot instantiate for HMAC.
Common situations: Partially configured CipherSuites struct (some fields set, HashType invalid); algorithm registry changed between library versions; custom cipher suite definitions.
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
- failed to create device
- failed to create device from new key
- keystore: generate otp
- failed to create blake2s hash
- failed to create AES-GCM
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/a4da07c7a62652a2.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/initiator.go:153
if err != nil {
return nil, fmt.Errorf("failed to create chain hash: %w", err)
}
mad.chainHash.Write([]byte(InitialHashString))
// init chain key -> ChainKey0
mad.noise.HashType = mad.ciphers.HashType
mad.noise.MixKey(&mad.chainKey, mad.chainHash.Sum(nil), []byte(InitialChainKeyString))
// init timestamp
mad.LocalInitTime = time.Now().UnixNano()
// assign channel
mad.ResponseMsgCh = md.ResponseMsgCh
// init hmac hash -> HmacHash0
mad.hmacHash, err = NewHash(mad.ciphers.HashType)
if err != nil {
return nil, fmt.Errorf("failed to create HMAC hash: %w", err)
}
mad.hmacHash.Write([]byte(InitialHashString))
// create ephermeral key
ephermalEccType := mad.ciphers.EccType
mad.ephermeralEcdh = NewECDH(ephermalEccType)
copy(mad.header.EphermeralBytes(), mad.ephermeralEcdh.PublicKey())
return mad, nil
}
func (mad *MsgAssemblerData) derivePacketParserData(pkt *Packet, initTime int64) (ppd *PacketParserData) {
ppd = &PacketParserData{}
ppd.device = mad.device
ppd.basePacket = pkt
ppd.CipherScheme = mad.CipherScheme
ppd.ConnData = mad.connData
ppd.LocalInitTime = initTimeView on GitHub (pinned to 6e04ca5ff0)