{"record":{"id":"3b7e3b2820b74d9d","repo":"elsa-workflows/elsa-core","slug":"elsa-secrets-encryption-key-must-be-exactly-16-24-or-32","errorCode":null,"errorMessage":"Elsa Secrets encryption key must be exactly 16, 24, or 32 bytes.","messagePattern":"Elsa Secrets encryption key must be exactly 16, 24, or 32 bytes\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/modules/Elsa.Secrets/Services/DefaultSecretValueProtector.cs","lineNumber":48,"sourceCode":"        var nonce = Convert.FromBase64String(parts[1]);\n        var tag = Convert.FromBase64String(parts[2]);\n        var ciphertext = Convert.FromBase64String(parts[3]);\n        var plaintext = new byte[ciphertext.Length];\n\n        using var aes = new AesGcm(GetKey(), TagSize);\n        aes.Decrypt(nonce, ciphertext, tag, plaintext);\n\n        return System.Text.Encoding.UTF8.GetString(plaintext);\n    }\n\n    private byte[] GetKey()\n    {\n        var key = options.Value.EncryptionKey;\n        if (key == null || key.Length == 0)\n            throw new InvalidOperationException(\"Elsa Secrets encryption key is not configured. Configure SecretsOptions.EncryptionKey before using the encrypted secrets store.\");\n\n        if (key.Length is not (16 or 24 or 32))\n            throw new InvalidOperationException(\"Elsa Secrets encryption key must be exactly 16, 24, or 32 bytes.\");\n\n        return key;\n    }\n}\n","sourceCodeStart":30,"sourceCodeEnd":53,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Secrets/Services/DefaultSecretValueProtector.cs#L30-L53","documentation":"GetKey validates that SecretsOptions.EncryptionKey is exactly 16, 24, or 32 bytes (AES-128/192/256 key sizes) and throws InvalidOperationException otherwise. A key of any other length cannot be used with the AES-GCM cipher used by the protector.","triggerScenarios":"Setting SecretsOptions.EncryptionKey to a byte array whose length is not 16, 24, or 32 — commonly a raw UTF-8 password of arbitrary length, or a base64 string that was not decoded / decoded incorrectly.","commonSituations":"Passing a passphrase string directly instead of a properly sized key; double-encoding base64; truncating a key during copy/paste; generating a 40-byte key from a wrong hash output.","solutions":["Derive a properly sized key: use a KDF (e.g. Rfc2898DeriveBytes/argon2) or SHA-256 hash to get exactly 32 bytes.","Ensure base64-encoded keys are decoded to bytes before assignment (Encoding/Convert.FromBase64String).","Generate a fresh key of exactly 32 bytes (RandomNumberGenerator.GetBytes(32)) if no prior encrypted data exists.","Caution: changing the key makes previously encrypted payloads undecryptable — re-encrypt secrets after changing keys."],"exampleFix":"// before\noptions.EncryptionKey = Encoding.UTF8.GetBytes(\"my-secret-passphrase\"); // 20 bytes -> throws\n// after\nusing var kdf = new Rfc2898DeriveBytes(\"my-secret-passphrase\", salt, 100_000, HashAlgorithmName.SHA256);\noptions.EncryptionKey = kdf.GetBytes(32); // exactly 32 bytes","handlingStrategy":"validation","validationCode":"var key = options.EncryptionKey;\nif (key is not { Length: 16 or 24 or 32 })\n    throw new InvalidOperationException($\"EncryptionKey must be 16/24/32 bytes; got {key?.Length ?? 0}.\");","typeGuard":"bool IsValidKey(byte[]? key) => key is { Length: 16 or 24 or 32 };","tryCatchPattern":"try { var value = protector.Protect(plaintext); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"16, 24, or 32 bytes\"))\n{ logger.LogCritical(\"Secrets encryption key has invalid length: {Msg}\", ex.Message); throw; }","preventionTips":["Generate keys with RandomNumberGenerator.GetBytes(32)","Always base64-decode encoded keys before assigning to byte[]","Use a KDF for passphrase-derived keys","Never assign raw passphrase bytes directly","Re-encrypt secrets after any key change"],"tags":["secrets","encryption","key-size"],"backgroundTag":"invalid-config-value","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}