OpenNHP/opennhp · error

failed to create AES cipher for CBC

Error message

failed to create AES cipher for CBC: %w

What it means

CBCEncryption(GCM_AES256, key, ...) wraps aes.NewCipher(key[:]) failure as this message. As with the AEAD path, Go's aes.NewCipher only fails for key lengths other than 16/24/32 bytes; with the fixed 32-byte SymmetricKeySize array this is practically unreachable and points to nil/misformed key material or dependency issues. It occurs while setting up the AES-CBC block cipher (AES-256, IV taken from key[8:24]).

Solutions

  1. Populate the key array completely via a successful key-exchange/KDF before calling CBCEncryption
  2. Check the wrapped error for the underlying key-length complaint
  3. Keep SymmetricKeySize at 32 (or another AES-legal 16/24/32) and re-verify all call sites after any resize
  4. Remember ChaCha20-Poly1305 returns ErrNotApplicable for CBC — route those callers to an AEAD function instead

Example fix

// before
var key [core.SymmetricKeySize]byte // never filled
ciphertext, _ := core.CBCEncryption(core.GCM_AES256, &key, plaintext, false)
// after
shared := ecdh.SharedSecret(peerPub)
var key [core.SymmetricKeySize]byte
utils.Memcpy(key[:], kdf(shared))
ciphertext, err := core.CBCEncryption(core.GCM_AES256, &key, plaintext, false)
if err != nil {
    return fmt.Errorf("cbc encrypt: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if key == nil {
    return errors.New("CBC key not initialized")
}
if core.SymmetricKeySize != 16 && core.SymmetricKeySize != 24 && core.SymmetricKeySize != 32 {
    return fmt.Errorf("SymmetricKeySize %d invalid for AES-CBC", core.SymmetricKeySize)
}

Try / catch

ciphertext, err := core.CBCEncryption(core.GCM_AES256, &key, plaintext, false)
if err != nil {
    if errors.Is(err, core.ErrNotApplicable) {
        return errors.New("CBC not available for this cipher - use AEAD")
    }
    return fmt.Errorf("AES-CBC encrypt failed: %w", err)
}

Prevention

When it happens

Trigger: Calling CBCEncryption with a nil *[SymmetricKeySize]byte, an under-filled key array, or after changing SymmetricKeySize to a value that is not 16/24/32; also via dependency corruption.

Common situations: Custom bulk-encryption code paths (e.g. DHP payload encryption) that receive a key before the ECDH/KDF step completed; refactors resizing SymmetricKeySize; forks altering the crypto stack.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at nhp/core/crypto.go:195

		if err != nil {
			return nil, fmt.Errorf("failed to create ChaCha20-Poly1305: %w", err)
		}
		return aead, nil

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

func CBCEncryption(t GcmTypeEnum, key *[SymmetricKeySize]byte, plaintext []byte, inPlace bool) ([]byte, error) {
	var block cipher.Block
	var iv []byte
	var err error
	switch t {
	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

View on GitHub (pinned to 6e04ca5ff0)