OpenNHP/opennhp · error
unsupported mode
Error message
unsupported mode: %v
What it means
newCipherBlock's default branch catches any SymmetricCipherMode value outside the known AES and SM4 tags and returns this error. It guards against constructing the mode directly from a raw integer instead of via NewSymmetricCipherMode.
Solutions
- Initialize the mode via NewSymmetricCipherMode with a valid name instead of raw values
- Ensure the struct/field holding the mode is not left at its zero value
- Validate mode tags received from peers against supported suites before use
Example fix
// before
var mode SymmetricCipherMode // zero value -> unsupported mode
// after
mode, err := NewSymmetricCipherMode("AES-256-GCM-128") Defensive patterns
Strategy: type-guard
Validate before calling
func isKnownMode(m SymmetricCipherMode) bool {
switch m {
case AES256GCM64Tag, AES256GCM96Tag, AES256GCM104Tag, AES256GCM112Tag, AES256GCM120Tag, AES256GCM128Tag, SM4GCM64Tag, SM4GCM128Tag:
return true
}
return false
} Type guard
func validSymmetricMode(m SymmetricCipherMode) bool { return isKnownMode(m) } Try / catch
if !validSymmetricMode(mode) {
mode, err = NewSymmetricCipherMode("AES-256-GCM-128")
} Prevention
- Never cast raw ints to SymmetricCipherMode
- Construct modes only via NewSymmetricCipherMode
- Avoid leaving mode fields at their zero value
When it happens
Trigger: Encrypt/Decrypt called on a SymmetricCipherMode value that is neither an AES256GCM* tag nor SM4GCM* tag (e.g. 0, or a value cast from an int) (nhp/core/ztdo/noise.go:122).
Common situations: Zero-value SymmetricCipherMode structs from uninitialized variables; deserialized mode tags from peers using newer suites; casting arbitrary integers to the mode type.
Related errors
- unknown symmetric mode name
- unsupported cipher type for CBC decryption
- unknown mode
- unknown mode
- failed to create device
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/721327b9094d5cd3.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/ztdo/noise.go:122
}
}
func (mode SymmetricCipherMode) newCipherBlock(key []byte) (cipher.Block, error) {
switch mode {
case AES256GCM64Tag, AES256GCM96Tag, AES256GCM104Tag,
AES256GCM112Tag, AES256GCM120Tag, AES256GCM128Tag:
if len(key) != 32 {
return nil, fmt.Errorf("invalid key length for AES-256-GCM")
}
return aes.NewCipher(key)
case SM4GCM64Tag, SM4GCM128Tag:
if len(key) < 16 {
return nil, fmt.Errorf("invalid key length for SM4-GCM")
} else {
key = key[:16]
}
return sm4.NewCipher(key)
default:
return nil, fmt.Errorf("unsupported mode: %v", mode)
}
}
func (mode SymmetricCipherMode) Encrypt(key, nonce, plaintext, ad []byte) ([]byte, error) {
tagSize := mode.TagSize()
cipherBlock, err := mode.newCipherBlock(key)
if err != nil {
return nil, err
}
aead, err := cipher.NewGCMWithTagSize(cipherBlock, tagSize)
if err != nil {
return nil, err
}
ciphertext := aead.Seal(plaintext[:0], nonce, plaintext, ad)
View on GitHub (pinned to 6e04ca5ff0)