OpenNHP/opennhp · error
failed to create chain hash
Error message
failed to create chain hash: %w
What it means
createMsgAssemblerData initializes the per-message chain hash (ChainHash0) with NewHash for the negotiated cipher suite's hash type. If the hash algorithm cannot be instantiated, the wrapped error is returned. This indicates the configured ciphers.HashType is unsupported or crypto backend initialization failed.
Solutions
- Set md.Ciphers to a valid CipherSuites value (e.g. from the negotiated ConnData) before assembly
- Ensure the cipher scheme constant is one of the supported values (CURVE or GMSM)
- Test NewHash(hashType) directly to confirm the hash type is registered
- Rebuild with full crypto backends if using a trimmed build
Example fix
// before
md := &MsgData{Msg: msg} // Ciphers zero-valued
// after
md := &MsgData{Msg: msg, Ciphers: connData.Ciphers} // negotiated suite Defensive patterns
Strategy: validation
Validate before calling
if _, err := nhpcore.NewHash(md.Ciphers.HashType); err != nil {
return fmt.Errorf("unsupported hash type %v", md.Ciphers.HashType)
} Type guard
func supportedSuite(c *nhpcore.CipherSuites) bool {
_, err := nhpcore.NewHash(c.HashType)
return err == nil
} Try / catch
mad, err := dev.MsgToPacket(md)
if err != nil && strings.Contains(err.Error(), "failed to create chain hash") {
return fmt.Errorf("bad cipher config: %w", err)
} Prevention
- Use predefined cipher-suite constants, not hand-built structs
- Verify crypto backends are compiled in (SM3 for GMSM)
- Test crypto init at process startup
When it happens
Trigger: MsgToPacket or packet assembly calls createMsgAssemblerData with a MsgData whose ciphers.HashType is unknown/zero, or the underlying hash constructor fails (e.g. unregistered algorithm).
Common situations: Cipher-scheme mismatch after switching between CIPHER_SCHEME_CURVE and CIPHER_SCHEME_GMSM; manually built MsgData with an uninitialized Ciphers struct; missing SM3 support in a custom crypto build.
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 blake2s hash
- failed to write HRK data to SM3
- failed to create device
- failed to create device from new key
- keystore: generate otp
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/8fa0bca4d75dee7f.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/initiator.go:136
}
// create header and init device ecdh
log.Info("start encryption using CIPHER_SCHEME_%d(0: CURVE; 1: GMSM.)", mad.CipherScheme)
mad.header = mad.BasePacket.HeaderWithCipherScheme(mad.CipherScheme)
mad.ciphers = NewCipherSuite(mad.CipherScheme)
mad.deviceEcdh = d.GetEcdhByCipherScheme(mad.CipherScheme)
// init version
mad.header.SetVersion(ProtocolVersionMajor, ProtocolVersionMinor)
// init header counter
mad.header.SetCounter(mad.TransactionId)
}
// init chain hash -> ChainHash0
mad.chainHash, err = NewHash(mad.ciphers.HashType)
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)
}View on GitHub (pinned to 6e04ca5ff0)