{"record":{"id":"e57d7f555a1b42e4","repo":"nilaoda/N_m3u8DL-RE","slug":"key-must-be-12-or-8-bytes","errorCode":null,"errorMessage":"Key must be 12 or 8 bytes!","messagePattern":"Key must be 12 or 8 bytes!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/N_m3u8DL-RE/Crypto/ChaCha20Util.cs","lineNumber":12,"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                }\n                else\n                {","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/nilaoda/N_m3u8DL-RE/blob/e113dee70c924ee08dae5460624909b04d84cb76/src/N_m3u8DL-RE/Crypto/ChaCha20Util.cs#L1-L30","documentation":"DecryptPer1024Bytes decrypts a buffer with ChaCha20 in 1024-byte blocks and validates key/nonce sizes up front. It throws when the nonce is neither 12 bytes (RFC 7539) nor 8 bytes (original DJB variant). Note the message misleadingly says 'Key' but the check is on the nonce.","triggerScenarios":"Passing a nonce of any length other than 12 or 8 (e.g. a 16-byte IV, a hex string decoded to an odd length, or a truncated/empty byte array) to DecryptPer1024Bytes while decrypting AES-128 SAMPLE-AES-free ChaCha20-encrypted HLS segments.","commonSituations":"Hardcoding a nonce parsed incorrectly from an EXT-X-KEY attribute; base64-decoding a nonce that was actually hex; passing a UTF-8-encoded nonce string instead of raw bytes.","solutions":["Ensure the nonce bytes are exactly 12 bytes for IETF ChaCha20 or 8 bytes for the original variant; pad an 8-byte nonce yourself or let the method prepend {0,0,0,0}","Verify how you decoded the nonce: hex 'DecodeData' vs base64 'Convert.FromBase64String' — decoding with the wrong scheme changes the length","Log nonceBytes.Length before the call to confirm the actual size","If the key (not nonce) is the wrong size, fix it to exactly 32 bytes to avoid the sibling 'Key must be 32 bytes!' exception"],"exampleFix":"// before\nvar nonce = Encoding.UTF8.GetBytes(keyInfo.IV); // wrong: variable length\nvar dec = ChaCha20Util.DecryptPer1024Bytes(seg, key, nonce);\n// after\nvar nonce = GetBytesFromHex(keyInfo.IV.TrimStart(\"0x\"));\nif (nonce.Length != 12 && nonce.Length != 8) nonce = nonce.Take(12).ToArray();\nvar dec = ChaCha20Util.DecryptPer1024Bytes(seg, key, nonce);","handlingStrategy":"validation","validationCode":"if (keyBytes.Length != 32) throw new ArgumentException(\"key must be 32 bytes\");\nif (nonceBytes.Length != 12 && nonceBytes.Length != 8) throw new ArgumentException($\"nonce must be 12 or 8 bytes, got {nonceBytes.Length}\");","typeGuard":"static bool IsValidChaCha20Params(byte[] key, byte[] nonce) => key.Length == 32 && (nonce.Length == 12 || nonce.Length == 8);","tryCatchPattern":null,"preventionTips":["Decode IV/nonce attributes with the correct scheme (hex for HLS IVs, not base64 or UTF-8)","Assert key/nonce lengths in tests with representative playlist data","Remember the misleading message text: this specific throw is about the nonce length"],"tags":["csharp","crypto","chacha20","invalid-nonce-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"}