nilaoda/N_m3u8DL-RE · error · Exception
Key must be 12 or 8 bytes!
Error message
Key must be 12 or 8 bytes!
What it means
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.
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
Example fix
// before
var nonce = Encoding.UTF8.GetBytes(keyInfo.IV); // wrong: variable length
var dec = ChaCha20Util.DecryptPer1024Bytes(seg, key, nonce);
// after
var nonce = GetBytesFromHex(keyInfo.IV.TrimStart("0x"));
if (nonce.Length != 12 && nonce.Length != 8) nonce = nonce.Take(12).ToArray();
var dec = ChaCha20Util.DecryptPer1024Bytes(seg, key, nonce); Defensive patterns
Strategy: validation
Validate before calling
if (keyBytes.Length != 32) throw new ArgumentException("key must be 32 bytes");
if (nonceBytes.Length != 12 && nonceBytes.Length != 8) throw new ArgumentException($"nonce must be 12 or 8 bytes, got {nonceBytes.Length}"); Type guard
static bool IsValidChaCha20Params(byte[] key, byte[] nonce) => key.Length == 32 && (nonce.Length == 12 || nonce.Length == 8);
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of nilaoda/N_m3u8DL-RE@e113dee70c (2026-09-13).
Data as JSON: /api/errors/e57d7f555a1b42e4.
Report an issue: GitHub.
Appendix: source
Thrown at src/N_m3u8DL-RE/Crypto/ChaCha20Util.cs:12
using CSChaCha20;
namespace N_m3u8DL_RE.Crypto;
internal static class ChaCha20Util
{
public static byte[] DecryptPer1024Bytes(byte[] encryptedBuff, byte[] keyBytes, byte[] nonceBytes)
{
if (keyBytes.Length != 32)
throw new Exception("Key must be 32 bytes!");
if (nonceBytes.Length != 12 && nonceBytes.Length != 8)
throw new Exception("Key must be 12 or 8 bytes!");
if (nonceBytes.Length == 8)
nonceBytes = (new byte[4] { 0, 0, 0, 0 }).Concat(nonceBytes).ToArray();
var decStream = new MemoryStream();
using BinaryReader reader = new BinaryReader(new MemoryStream(encryptedBuff));
using (BinaryWriter writer = new BinaryWriter(decStream))
while (true)
{
var buffer = reader.ReadBytes(1024);
byte[] dec = new byte[buffer.Length];
if (buffer.Length > 0)
{
ChaCha20 forDecrypting = new ChaCha20(keyBytes, nonceBytes, 0);
forDecrypting.DecryptBytes(dec, buffer);
writer.Write(dec, 0, dec.Length);
}
else
{View on GitHub (pinned to e113dee70c)