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

  1. Use a predefined CipherSuites constant instead of hand-assembling the struct
  2. Verify the HashType value is supported (BLAKE2s for CURVE, SM3 for GMSM)
  3. Keep chain-hash and HMAC hash creation consistent by setting HashType once from the scheme
  4. 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

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


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 = initTime

View on GitHub (pinned to 6e04ca5ff0)