slackhq/nebula · error

invalid AES-256 key length (%d) - cowardly refusing to encry

Error message

invalid AES-256 key length (%d) - cowardly refusing to encrypt

What it means

aes256Encrypt derives a 32-byte key via Argon2id and sanity-checks the length before AES-256-GCM encryption. A length other than 32 would silently degrade AES behavior, so the library refuses. With the fixed keySize of 32 in aes256DeriveKey this should never happen; it guards internal regressions.

Source

Thrown at cert/crypto.go:56

	return &Argon2Parameters{
		version:     argon2.Version,
		Memory:      memory, // KiB
		Parallelism: parallelism,
		Iterations:  iterations,
	}
}

// Encrypts data using AES-256-GCM and the Argon2id key derivation function
func aes256Encrypt(passphrase []byte, kdfParams *Argon2Parameters, data []byte) ([]byte, error) {
	key, err := aes256DeriveKey(passphrase, kdfParams)
	if err != nil {
		return nil, err
	}

	// this should never happen, but since this dictates how our calls into the
	// aes package behave and could be catastraphic, let's sanity check this
	if len(key) != 32 {
		return nil, fmt.Errorf("invalid AES-256 key length (%d) - cowardly refusing to encrypt", len(key))
	}

	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	gcm, err := cipher.NewGCM(block)
	if err != nil {
		return nil, err
	}

	nonce := make([]byte, gcm.NonceSize())
	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
		return nil, err
	}

	ciphertext := gcm.Seal(nil, nonce, data, nil)

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Use the stock library; do not modify aes256DeriveKey/deriveKey keySize.
  2. If forking, ensure deriveKey is called with keySize=32 and Argon2 parameters produce a 32-byte output.
  3. Report a bug if this occurs on unmodified code.
Defensive patterns

Strategy: validation

Validate before calling

// ensure you use the stock API; the KDF key size is fixed at 32 bytes internally
_, err := cert.EncryptAndMarshalSigningPrivateKey(key, cert.NewArgon2Parameters(9*1024, 1, 4))

Try / catch

blob, err := cert.EncryptAndMarshalSigningPrivateKey(key, params)
if err != nil && strings.Contains(err.Error(), "invalid AES-256 key length") {
    return fmt.Errorf("internal KDF regression; do not modify keySize wiring: %w", err)
}

Prevention

When it happens

Trigger: EncryptAndMarshalSigningPrivateKey reaching aes256Encrypt with a derived key whose length != 32 — only possible if internal KDF wiring changes or the function is invoked with modified code paths.

Common situations: Custom forks that changed deriveKey keySize, or patched crypto code; practically unreachable with the stock library.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/3419bd68497718e7. Report an issue: GitHub.