{"record":{"id":"fe7a252e28a039af","repo":"nilaoda/N_m3u8DL-RE","slug":"key-must-be-32-bytes","errorCode":null,"errorMessage":"Key must be 32 bytes!","messagePattern":"Key must be 32 bytes!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/N_m3u8DL-RE/Crypto/ChaCha20Util.cs","lineNumber":10,"sourceCode":"﻿using CSChaCha20;\n\nnamespace N_m3u8DL_RE.Crypto;\n\ninternal static class ChaCha20Util\n{\n    public static byte[] DecryptPer1024Bytes(byte[] encryptedBuff, byte[] keyBytes, byte[] nonceBytes)\n    {\n        if (keyBytes.Length != 32)\n            throw new Exception(\"Key must be 32 bytes!\");\n        if (nonceBytes.Length != 12 && nonceBytes.Length != 8)\n            throw new Exception(\"Key must be 12 or 8 bytes!\");\n        if (nonceBytes.Length == 8)\n            nonceBytes = (new byte[4] { 0, 0, 0, 0 }).Concat(nonceBytes).ToArray();\n\n        var decStream = new MemoryStream();\n        using BinaryReader reader = new BinaryReader(new MemoryStream(encryptedBuff));\n        using (BinaryWriter writer = new BinaryWriter(decStream))\n            while (true)\n            {\n                var buffer = reader.ReadBytes(1024);\n                byte[] dec = new byte[buffer.Length];\n                if (buffer.Length > 0)\n                {\n                    ChaCha20 forDecrypting = new ChaCha20(keyBytes, nonceBytes, 0);\n                    forDecrypting.DecryptBytes(dec, buffer);\n                    writer.Write(dec, 0, dec.Length);\n                }","sourceCodeStart":1,"sourceCodeEnd":28,"githubUrl":"https://github.com/nilaoda/N_m3u8DL-RE/blob/e113dee70c924ee08dae5460624909b04d84cb76/src/N_m3u8DL-RE/Crypto/ChaCha20Util.cs#L1-L28","documentation":"ChaCha20Util.DecryptPer1024Bytes is the segment-decryption helper. It requires a 32-byte key and throws Exception(\"Key must be 32 bytes!\") otherwise (note the nonce check message is likewise mislabeled 'Key must be 12 or 8 bytes!'). This is a plain Exception, so catch blocks targeting ArgumentException will not catch it.","triggerScenarios":"Calling DecryptPer1024Bytes with keyBytes.Length != 32 — e.g. a 16-byte AES key from --key parsing, a truncated/extended key buffer, or a key decoded with wrong encoding.","commonSituations":"SAMPLE-AES (16-byte key) streams routed into the ChaCha20 path; key hex strings with whitespace causing decode size mismatch; mixing up KID and KEY buffers.","solutions":["Ensure keyBytes is exactly 32 bytes (64 hex chars) before calling the helper.","Use the correct decryption routine for 16-byte AES keys instead of ChaCha20.","Fix key decoding (strip whitespace, use correct hex/base64) so the decoded buffer is 32 bytes.","Catch base Exception, not just ArgumentException, when wrapping this helper's failures."],"exampleFix":"// before\nChaCha20Util.DecryptPer1024Bytes(buf, key16, nonce); // 16-byte key\n// after\nif (key.Length != 32) throw new InvalidOperationException(\"need 32-byte key\");\nChaCha20Util.DecryptPer1024Bytes(buf, key32, nonce);","handlingStrategy":"validation","validationCode":"if (keyBytes?.Length != 32) throw new InvalidOperationException(\"ChaCha20 requires a 32-byte key\");\nif (nonceBytes?.Length is not (8 or 12)) throw new InvalidOperationException(\"nonce must be 8 or 12 bytes\");","typeGuard":"bool CanChaChaDecrypt(byte[] k, byte[] n) => k is { Length: 32 } && n is { Length: 8 or 12 };","tryCatchPattern":"try { dec = ChaCha20Util.DecryptPer1024Bytes(buf, key, nonce); }\ncatch (Exception ex) { Console.Error.WriteLine($\"decrypt failed: {ex.Message}\"); } // plain Exception, not ArgumentException","preventionTips":["Assert key length == 32 at the call site.","Send 16-byte AES keys to the AES decryption path instead.","Catch generic Exception here — the helper throws plain Exception with a mislabeled nonce message."],"tags":["crypto","chacha20","key-length"],"backgroundTag":"invalid-argument-value","analyzedSha":"e113dee70c924ee08dae5460624909b04d84cb76","analyzedAt":"2026-09-13T02:43:21.078Z","contentChangedAt":"2026-09-13T02:43:21.078Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}