{"record":{"id":"e2ef6761f2b20f39","repo":"micro/go-micro","slug":"decryption-failed-is-the-key-set-correctly","errorCode":null,"errorMessage":"decryption failed (is the key set correctly?)","messagePattern":"decryption failed \\(is the key set correctly\\?\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/secrets/secretbox/secretbox.go","lineNumber":70,"sourceCode":"func (s *secretBox) Encrypt(in []byte, opts ...secrets.EncryptOption) ([]byte, error) {\n\t// no opts are expected, so they are ignored\n\n\t// there must be a unique nonce for each message\n\tvar nonce [24]byte\n\tif _, err := rand.Reader.Read(nonce[:]); err != nil {\n\t\treturn []byte{}, errors.Wrap(err, \"couldn't obtain a random nonce from crypto/rand\")\n\t}\n\treturn secretbox.Seal(nonce[:], in, &nonce, &s.secretKey), nil\n}\n\nfunc (s *secretBox) Decrypt(in []byte, opts ...secrets.DecryptOption) ([]byte, error) {\n\t// no options are expected, so they are ignored\n\n\tvar decryptNonce [24]byte\n\tcopy(decryptNonce[:], in[:24])\n\tdecrypted, ok := secretbox.Open(nil, in[24:], &decryptNonce, &s.secretKey)\n\tif !ok {\n\t\treturn []byte{}, errors.New(\"decryption failed (is the key set correctly?)\")\n\t}\n\treturn decrypted, nil\n}\n","sourceCodeStart":52,"sourceCodeEnd":74,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/config/secrets/secretbox/secretbox.go#L52-L74","documentation":"NaCl secretbox.Open failed to authenticate the ciphertext with the configured symmetric key. Secretbox verifies a MAC before decrypting, so this error means the data was not encrypted with the same 32-byte key that Init loaded, or the data is corrupted.","triggerScenarios":"Calling secretBox.Decrypt on data encrypted with a different key; the ciphertext's first 24 bytes (nonce) were stripped or altered; the payload was truncated or double-decoded before Decrypt.","commonSituations":"Two environments (staging vs production) with different SECRETBOX keys but shared stored ciphertext; key rotation where old records still use the previous key; storing ciphertext through a lossy transformation (e.g. writing bytes as a string with encoding changes).","solutions":["Ensure the same 32-byte key used by Init at encryption time is configured at decryption time; compare keys byte-for-byte across environments.","Keep the payload intact: the first 24 bytes are the nonce and must be included; decode/encode with a stable, lossless encoding (base64) end-to-end.","If keys rotated, keep the old key available to decrypt legacy records and migrate them to the new key.","Verify Init succeeded with no error and that the key length check (32 bytes) passed."],"exampleFix":"// before\ndecrypted, err := sb.Decrypt(storedString) // may have lost bytes\n// after\nraw, err := base64.StdEncoding.DecodeString(storedString)\nif err != nil { return err }\ndecrypted, err := sb.Decrypt(raw) // same key as used to encrypt","handlingStrategy":"try-catch","validationCode":"if len(ciphertext) <= 24 {\n    return errors.New(\"payload too short: missing nonce\")\n}","typeGuard":null,"tryCatchPattern":"decrypted, err := sb.Decrypt(payload)\nif err != nil {\n    if strings.Contains(err.Error(), \"is the key set correctly\") {\n        return fmt.Errorf(\"secretbox key mismatch or corrupt payload: %w\", err)\n    }\n    return err\n}","preventionTips":["Keep secretbox keys synchronized across all services sharing encrypted data","Record a key version alongside ciphertext to support rotation","Always store ciphertext as base64/hex, never raw bytes in string columns","Verify the same key on both encrypt and decrypt paths with a startup self-test"],"tags":["crypto","secretbox","decryption","wrong-key"],"backgroundTag":"decryption-authentication-failed","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}