{"record":{"id":"29baf77a0ab3f8e9","repo":"ory/hydra","slug":"key-must-be-exactly-32-long-bytes-got-d-bytes","errorCode":null,"errorMessage":"key must be exactly 32 long bytes, got %d bytes","messagePattern":"key must be exactly 32 long bytes, got (.+?) bytes","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"aead/aesgcm.go","lineNumber":67,"sourceCode":"\t}\n\n\tkeys, err := allKeys(ctx, c.c)\n\tif err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\n\tfor _, key := range keys {\n\t\tif plaintext, err = c.decrypt(msg, key, aad); err == nil {\n\t\t\treturn plaintext, nil\n\t\t}\n\t}\n\n\treturn nil, err\n}\n\nfunc (*AESGCM) decrypt(ciphertext, key, additionalData []byte) ([]byte, error) {\n\tif len(key) != 32 {\n\t\treturn nil, errors.Errorf(\"key must be exactly 32 long bytes, got %d bytes\", len(key))\n\t}\n\n\tplaintext, err := aesGCMDecrypt(ciphertext, aeadKey(key), additionalData)\n\tif err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\n\treturn plaintext, nil\n}\n\n// aesGCMEncrypt encrypts data using 256-bit AES-GCM.  This both hides the content of\n// the data and provides a check that it hasn't been altered. Output takes the\n// form nonce|ciphertext|tag where '|' indicates concatenation.\nfunc aesGCMEncrypt(plaintext []byte, key *[32]byte, additionalData []byte) (ciphertext []byte, err error) {\n\tblock, err := aes.NewCipher(key[:])\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/aead/aesgcm.go#L49-L85","documentation":"AESGCM.decrypt requires the encryption key to be exactly 32 bytes (AES-256) before it derives the AEAD subkey and runs GCM decryption. The library throws this when a caller supplies a key of any other length, because Go's crypto/aes only accepts 16/24/32-byte keys and this implementation standardizes on 256-bit keys.","triggerScenarios":"Calling Decrypt (or decrypt directly) with a key that is not 32 bytes long — e.g. a raw 16-byte or 24-byte AES key, a hex-decoded key that was truncated, or a base64 string passed in without decoding.","commonSituations":"Storing the key in config as a string and passing its byte length instead of the decoded value; generating a key with a different cipher setting (AES-128); reading a key from an env var that was padded, truncated, or not base64/hex decoded; migrating from an older cipher that used 16-byte keys.","solutions":["Check len(key) at the call site and regenerate/derive a 32-byte key (crypto/rand.Read(make([]byte, 32)) or sha256 of a passphrase).","If the key comes from base64/hex config, decode it (base64.StdEncoding.DecodeString / hex.DecodeString) instead of using the literal string bytes.","If you have a shorter key, derive a 32-byte one deterministically (e.g. HKDF/SHA-256) — but note this changes ciphertexts only if the original encryption also derived keys the same way."],"exampleFix":"// before\nkey := []byte(os.Getenv(\"COOKIE_SECRET\")) // may be < 32 bytes\nplaintext, err := cipher.Decrypt(ctx, ciphertext, key, ad)\n\n// after\nraw, err := base64.StdEncoding.DecodeString(os.Getenv(\"COOKIE_SECRET\"))\nif err != nil || len(raw) != 32 {\n    return fmt.Errorf(\"COOKIE_SECRET must decode to exactly 32 bytes\")\n}\nplaintext, err := cipher.Decrypt(ctx, ciphertext, raw, ad)","handlingStrategy":"validation","validationCode":"if len(key) != 32 {\n    return fmt.Errorf(\"encryption key must be 32 bytes, got %d\", len(key))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate keys with crypto/rand.Read(make([]byte, 32)) and store them base64-encoded.","Always decode base64/hex key material from config before passing byte slices.","Add a startup assertion on key length so misconfiguration fails fast.","Never pass the raw config string bytes as a key."],"tags":["crypto","aead","aes-gcm","key-length"],"backgroundTag":"invalid-encryption-key-length","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}