OpenNHP/opennhp · error

unsupported cipher type for CBC

Error message

unsupported cipher type for CBC: %d

What it means

CBCEncryption only supports block ciphers (AES-256 and SM4) for CBC mode. When the GcmTypeEnum passed is not GCM_AES256 or GCM_SM4 — e.g. GCM_CHACHA20POLY1305 handled earlier via ErrNotApplicable, or any unknown numeric value — the default branch rejects it because CBC mode cannot be applied to a stream cipher or an unregistered type.

Solutions

  1. Pass only GCM_AES256 or GCM_SM4 to CBCEncryption; verify the enum value at the call site.
  2. If the caller wants ChaCha20Poly1305, use AeadFromKey/AEAD encryption instead — CBC is ErrNotApplicable for stream ciphers.
  3. Validate the cipher-type config field (e.g. in config.toml) maps to a supported GcmTypeEnum before calling.
  4. Add the missing case to CBCEncryption if a new block cipher was introduced to the enum.

Example fix

// before
data, err := core.CBCEncryption(core.GCM_CHACHA20POLY1305, key, plaintext, false)
// after
data, err := core.CBCEncryption(core.GCM_AES256, key, plaintext, false)
// or for ChaCha20Poly1305 use AEAD:
aead, err := core.AeadFromKey(core.GCM_CHACHA20POLY1305, key)
Defensive patterns

Strategy: validation

Validate before calling

func cbcSupported(t core.GcmTypeEnum) bool { return t == core.GCM_AES256 || t == core.GCM_SM4 }
if !cbcSupported(scheme) { return fmt.Errorf("scheme %v cannot use CBC", scheme) }

Type guard

func isBlockCipherCBC(t core.GcmTypeEnum) bool { return t == core.GCM_AES256 || t == core.GCM_SM4 }

Try / catch

data, err := core.CBCEncryption(t, key, pt, false)
if errors.Is(err, core.ErrNotApplicable) {
    // stream cipher: fall back to AEAD path
} else if err != nil {
    return fmt.Errorf("CBC encrypt: %w", err)
}

Prevention

When it happens

Trigger: Calling CBCEncryption(t, key, plaintext, inPlace) with a GcmTypeEnum value other than GCM_AES256 or GCM_SM4, such as GCM_CHACHA20POLY1305 misuse reaching the default branch, a zero-value enum, or a cipher type loaded from config that doesn't match any case.

Common situations: Cipher scheme read from TOML config or wire data as an arbitrary integer; code refactors that map a Noise cipher suite (e.g. ChaCha20Poly1305) to CBC helpers; new enum added to GcmTypeEnum without updating CBCEncryption.

Related errors


AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07). Data as JSON: /api/errors/95f12ed7cf299616. Report an issue: GitHub.

Appendix: source

Thrown at nhp/core/crypto.go:210

	case GCM_AES256:
		block, err = aes.NewCipher(key[:])
		if err != nil {
			return nil, fmt.Errorf("failed to create AES cipher for CBC: %w", err)
		}
		iv = key[8:24]

	case GCM_SM4:
		block, err = sm4.NewCipher(key[:16])
		if err != nil {
			return nil, fmt.Errorf("failed to create SM4 cipher for CBC: %w", err)
		}
		iv = key[16:]

	case GCM_CHACHA20POLY1305:
		return nil, ErrNotApplicable

	default:
		return nil, fmt.Errorf("unsupported cipher type for CBC: %d", t)
	}

	var paddedPlainText []byte
	if len(plaintext)%block.BlockSize() == 0 {
		// skip padding
		paddedPlainText = plaintext
	} else {
		pkcs7 := padding.NewPKCS7Padding(uint(block.BlockSize()))
		paddedPlainText = pkcs7.Pad(plaintext)
	}

	var ciphertext []byte
	if inPlace {
		ciphertext = paddedPlainText
	} else {
		ciphertext = make([]byte, 0, len(plaintext))
	}

View on GitHub (pinned to 6e04ca5ff0)