nilaoda/N_m3u8DL-RE · error · ArgumentException
Key length must be . Actual
Error message
Key length must be {allowedKeyLength}. Actual: {key.Length} What it means
CSChaCha20 only accepts a 256-bit key. KeySetup compares key.Length against allowedKeyLength (32) and throws ArgumentException("Key length must be 32. Actual: N") on any other size, because the state initialization reads exactly 32 bytes in 8 little-endian words.
Solutions
- Ensure the key is exactly 32 bytes (64 hex chars) before constructing the cipher.
- Trim whitespace/newlines from decoded key material.
- If the source key is 16 bytes, confirm the encryption actually uses ChaCha20-256; otherwise use the matching cipher.
- Add an upfront length assertion where keys are parsed.
Example fix
// before var key = Convert.FromHexString(hexKey); // may be 16 bytes // after if (key.Length != 32) Array.Resize(ref key, 32); // better: validate & reject var cipher = new CSChaCha20(key, nonce, 0);
Defensive patterns
Strategy: validation
Validate before calling
if (keyBytes == null || keyBytes.Length != 32) throw new InvalidOperationException($"ChaCha20 key must be 32 bytes, got {keyBytes?.Length ?? 0}"); Type guard
bool IsChaCha20Key(byte[] k) => k is { Length: 32 }; Try / catch
try { cipher = new CSChaCha20(key, nonce, 0); }
catch (ArgumentException ex) { Console.Error.WriteLine($"Bad key: {ex.Message}"); } Prevention
- Decode keys to byte[] and assert Length == 32 before use.
- Trim whitespace/newlines from decoded key material.
- Route 16-byte AES keys to the AES path, not ChaCha20.
When it happens
Trigger: Passing a 16-byte (AES-128) key, a hex string decoded to the wrong byte count, or a key buffer with a length prefix/BOM included to the ChaCha20 constructor.
Common situations: Users supply 16-byte SAMPLE-AES keys meant for AES-CTR; Base64/hex decode helpers produce padded or truncated buffers; key material read from a file includes trailing newline 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/45d7934a87c13321.
Report an issue: GitHub.
Appendix: source
Thrown at src/N_m3u8DL-RE/Crypto/CSChaCha20.cs:130
private static readonly byte[] sigma = Encoding.ASCII.GetBytes("expand 32-byte k");
private static readonly byte[] tau = Encoding.ASCII.GetBytes("expand 16-byte k");
/// <summary>
/// Set up the ChaCha state with the given key. A 32-byte key is required and enforced.
/// </summary>
/// <param name="key">
/// A 32-byte (256-bit) key, treated as a concatenation of eight 32-bit little-endian integers
/// </param>
private void KeySetup(byte[] key)
{
if (key == null)
{
throw new ArgumentNullException("Key is null");
}
if (key.Length != allowedKeyLength)
{
throw new ArgumentException($"Key length must be {allowedKeyLength}. Actual: {key.Length}");
}
state[4] = Util.U8To32Little(key, 0);
state[5] = Util.U8To32Little(key, 4);
state[6] = Util.U8To32Little(key, 8);
state[7] = Util.U8To32Little(key, 12);
byte[] constants = (key.Length == allowedKeyLength) ? sigma : tau;
int keyIndex = key.Length - 16;
state[8] = Util.U8To32Little(key, keyIndex + 0);
state[9] = Util.U8To32Little(key, keyIndex + 4);
state[10] = Util.U8To32Little(key, keyIndex + 8);
state[11] = Util.U8To32Little(key, keyIndex + 12);
state[0] = Util.U8To32Little(constants, 0);
state[1] = Util.U8To32Little(constants, 4);
state[2] = Util.U8To32Little(constants, 8);View on GitHub (pinned to e113dee70c)