crowdsecurity/crowdsec · critical
failed to create cipher: %w
Error message
failed to create cipher: %w
What it means
After HKDF key derivation, sealCookieV0 creates the AES block cipher via aes.NewCipher. This error means Go's AES implementation rejected the key. With a correct 32-byte HKDF output this is effectively impossible; it indicates the derived key has an invalid length, i.e. a broken keyring or a corrupted deriveKey path.
Source
Thrown at pkg/appsec/challenge/crypto.go:124
//
// Returns ErrAllowlistReasonSize if reason exceeds MaxAllowlistReasonLen.
func sealCookieV0(envelope *pb.ChallengeCookie, masterCookieKey []byte, notAfter int64, flags byte, reason string, aad []byte, maxCookieLen int) (string, error) {
if maxCookieLen <= 0 {
maxCookieLen = MaxCookieLen
}
if len(reason) > MaxAllowlistReasonLen {
return "", fmt.Errorf("%w: %d > %d", ErrAllowlistReasonSize, len(reason), MaxAllowlistReasonLen)
}
key, err := deriveKey(masterCookieKey)
if err != nil {
return "", err
}
block, err := aes.NewCipher(key)
if err != nil {
return "", fmt.Errorf("failed to create cipher: %w", err)
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", fmt.Errorf("failed to create GCM: %w", err)
}
// Reject an over-limit envelope before marshaling it.
maxPlaintext := maxCookieLen/4*3 - 1 - gcm.NonceSize() - gcm.Overhead()
if plaintextLen := cookiePlaintextFixedHeaderLen + len(reason) + proto.Size(envelope); plaintextLen > maxPlaintext {
return "", fmt.Errorf("%w: plaintext=%d > %d", ErrCookieTooLarge, plaintextLen, maxPlaintext)
}
envelopeBytes, err := proto.Marshal(envelope)
if err != nil {
return "", fmt.Errorf("failed to marshal challenge cookie proto: %w", err)
}
View on GitHub (pinned to 909b515798)
Solutions
- Inspect the wrapped error; if it mentions illegal key size, audit how masterCookieKey reaches sealCookieV0.
- Rebuild the ChallengeRuntime through its standard constructor so the keyring produces a proper 32-byte key.
- Verify the hkdf.Read call in deriveKey returns no error and fills all 32 bytes.
Defensive patterns
Strategy: try-catch
Try / catch
if err != nil {
return fmt.Errorf("cookie sealing failed (cipher): %w", err)
} Prevention
- Do not bypass the standard runtime constructor.
- Keep crypto packages stock (no vendored forks).
- Treat any occurrence as a bug report-worthy internal invariant failure.
When it happens
Trigger: Calling sealCookieV0 when deriveKey returned a key whose length is not 16/24/32 bytes — only possible with a corrupted or improperly initialized master cookie key, or an hkdf stream truncated by an error path.
Common situations: Programmatic misuse of the challenge package bypassing normal runtime construction; in practice developers rarely see this — it is a defensive check on an internal invariant.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- failed to create GCM: %w
- cookie expired
- unknown cookie version
- empty master secret
- generate PoW salt: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/85035a0b4158dde4.
Report an issue: GitHub.