{"record":{"id":"7e1b55701a151359","repo":"slackhq/nebula","slug":"invalid-passphrase-or-corrupt-private-key","errorCode":null,"errorMessage":"invalid passphrase or corrupt private key","messagePattern":"invalid passphrase or corrupt private key","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cert/crypto.go","lineNumber":105,"sourceCode":"\n\tblock, err := aes.NewCipher(key)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tgcm, err := cipher.NewGCM(block)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tnonce, ciphertext, err := splitNonceCiphertext(data, gcm.NonceSize())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tplaintext, err := gcm.Open(nil, nonce, ciphertext, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid passphrase or corrupt private key\")\n\t}\n\n\treturn plaintext, nil\n}\n\nfunc aes256DeriveKey(passphrase []byte, params *Argon2Parameters) ([]byte, error) {\n\tif params.salt == nil {\n\t\tparams.salt = make([]byte, 32)\n\t\tif _, err := rand.Read(params.salt); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// keySize of 32 bytes will result in AES-256 encryption\n\tkey, err := deriveKey(passphrase, 32, params)\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/crypto.go#L87-L123","documentation":"aes256Decrypt derives the key from the passphrase with Argon2id and opens the AES-256-GCM ciphertext; gcm.Open fails when authentication fails. The library collapses any authentication failure into this message, meaning the passphrase is wrong or the ciphertext/metadata was altered or truncated. It deliberately does not distinguish wrong passphrase from corruption.","triggerScenarios":"Calling DecryptAndUnmarshalSigningPrivateKey with a passphrase that differs from the one used at encryption, or with ciphertext bytes that were modified/truncated (splitNonceCiphertext passed but GCM tag mismatched).","commonSituations":"Typo or changed passphrase in config (key.password / encrypted_host_key), encrypted key file edited or copied incorrectly, different Argon2 parameters than used at encryption time, environment variable interpolation altering the passphrase.","solutions":["Re-enter the exact passphrase used when the key was encrypted ( EncryptAndMarshalSigningPrivateKey ).","Re-encrypt the private key with the new passphrase if the original is lost — the old ciphertext cannot be recovered.","Verify the encrypted key file is byte-identical to the original (no edits, CRLF conversion, or truncation).","Ensure the Argon2 parameters stored in the file metadata were not altered."],"exampleFix":"// before\nkey, _, err := cert.DecryptAndUnmarshalSigningPrivateKey([]byte(os.Getenv(\"NEBULA_PASS\")), pemBytes) // wrong env var value\n// after\npass := []byte(os.Getenv(\"NEBULA_KEY_PASSWORD\"))\nif len(pass) == 0 {\n    return fmt.Errorf(\"NEBULA_KEY_PASSWORD not set\")\n}\nkey, _, err := cert.DecryptAndUnmarshalSigningPrivateKey(pass, pemBytes)","handlingStrategy":"try-catch","validationCode":"// cannot be validated beforehand; verify passphrase is present and non-empty\npass := []byte(os.Getenv(\"NEBULA_KEY_PASSWORD\"))\nif len(pass) == 0 {\n    return fmt.Errorf(\"passphrase must be provided to decrypt host key\")\n}","typeGuard":null,"tryCatchPattern":"key, groups, err := cert.DecryptAndUnmarshalSigningPrivateKey(pass, pemBytes)\nif err != nil {\n    if err.Error() == \"invalid passphrase or corrupt private key\" {\n        return fmt.Errorf(\"wrong passphrase for encrypted host key (or file corrupted); re-check NEBULA_KEY_PASSWORD\")\n    }\n    return err\n}","preventionTips":["Store the passphrase in a secret manager, not hand-typed config.","Compare checksums of encrypted key files after transfer to rule out corruption.","Keep a tested backup of the passphrase before rotating.","Re-encrypt the key with EncryptAndMarshalSigningPrivateKey after passphrase changes."],"tags":["encryption","passphrase","aes-gcm","decryption"],"backgroundTag":"wrong-passphrase-decryption-failed","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}