{"record":{"id":"56c58fa22baf7ed1","repo":"kataras/iris","slug":"err-56c58f","errorCode":null,"errorMessage":"err","messagePattern":"err","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"middleware/jwt/signer.go","lineNumber":61,"sourceCode":"\n\ts := &Signer{\n\t\tAlg:    signatureAlg,\n\t\tKey:    signatureKey,\n\t\tMaxAge: maxAge,\n\t}\n\n\tif maxAge > 0 {\n\t\ts.Options = []SignOption{MaxAge(maxAge)}\n\t}\n\n\treturn s\n}\n\n// WithEncryption enables AES-GCM payload-only decryption.\nfunc (s *Signer) WithEncryption(key, additionalData []byte) *Signer {\n\tencrypt, _, err := jwt.GCM(key, additionalData)\n\tif err != nil {\n\t\tpanic(err) // important error before serve, stop everything.\n\t}\n\n\ts.Encrypt = encrypt\n\treturn s\n}\n\n// Sign generates a new token based on the given \"claims\" which is valid up to \"s.MaxAge\".\nfunc (s *Signer) Sign(claims any, opts ...SignOption) ([]byte, error) {\n\tif len(opts) > 0 {\n\t\topts = append(opts, s.Options...)\n\t} else {\n\t\topts = s.Options\n\t}\n\n\treturn SignEncrypted(s.Alg, s.Key, s.Encrypt, claims, opts...)\n}\n\n// NewTokenPair accepts the access and refresh claims plus the life time duration for the refresh token","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/middleware/jwt/signer.go#L43-L79","documentation":"Signer.WithEncryption enables AES-GCM payload encryption using golang-jwt's GCM constructor. If the key is not a valid AES key size (16, 24, or 32 bytes) the constructor returns an error and the Signer panics immediately, since encryption misconfiguration must be caught before serving.","triggerScenarios":"Calling signer.WithEncryption(key, additionalData) with a key whose length is not 16, 24, or 32 bytes — e.g. a short passphrase, an empty slice, or a 33-byte key.","commonSituations":"Reading the key from an env var that is unset or a raw passphrase instead of a decoded base64/hex key; truncating a hex string; key generated with a non-standard length.","solutions":["Make the key exactly 32 bytes (AES-256): sha256.Sum256([]byte(passphrase)) or a 32-byte random key.","If loading from env, decode it: base64.StdEncoding.DecodeString or hex.DecodeString, then verify len(key) is 16/24/32 before calling WithEncryption.","Generate a proper key with crypto/rand: make([]byte, 32); rand.Read(key)."],"exampleFix":"// before\nsigner.WithEncryption([]byte(os.Getenv(\"JWT_KEY\")), nil) // wrong length\n// after\nkey, _ := hex.DecodeString(os.Getenv(\"JWT_KEY\"))\nif n := len(key); n != 16 && n != 24 && n != 32 {\n    log.Fatalf(\"jwt gcm key must be 16/24/32 bytes, got %d\", n)\n}\nsigner.WithEncryption(key, nil)","handlingStrategy":"validation","validationCode":"func validateGCMKey(key []byte) error {\n    switch len(key) {\n    case 16, 24, 32:\n        return nil\n    }\n    return fmt.Errorf(\"AES-GCM key must be 16, 24, or 32 bytes, got %d\", len(key))\n}","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Fatalf(\"jwt encryption setup failed: %v\", r)\n    }\n}()\ns.WithEncryption(key, aad)","preventionTips":["Generate keys with crypto/rand at exactly 32 bytes and store them encoded (base64/hex).","Decode keys before use and assert length at config-load time.","Never pass passphrase strings directly as AES keys."],"tags":["go","panic","jwt","aes-gcm","invalid-key","startup"],"backgroundTag":"invalid-encryption-key","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}