nilaoda/N_m3u8DL-RE · error · ArgumentException
Nonce length must be
Error message
Nonce length must be {allowedNonceLength}. Actual: {nonce.Length} What it means
ChaCha20 in this implementation requires a nonce of exactly allowedNonceLength bytes (12). IvSetup checks nonce.Length and, on mismatch, disposes the partially-initialized state and throws ArgumentException("Nonce length must be 12. Actual: N").
Solutions
- Left-pad 8-byte nonces with four zero bytes to make 12 bytes (as ChaCha20Util.DecryptPer1024Bytes does).
- Trim decoded IV buffers to exactly 12 bytes.
- Use ChaCha20Util.DecryptPer1024Bytes, which handles the 8-byte padding automatically.
- Validate nonce length at the point where IVs are extracted from the manifest.
Example fix
// before var cipher = new CSChaCha20(key, nonce8, 0); // 8-byte nonce // after var nonce12 = new byte[4].Concat(nonce8).ToArray(); var cipher = new CSChaCha20(key, nonce12, 0);
Defensive patterns
Strategy: validation
Validate before calling
if (nonceBytes.Length == 8) nonceBytes = new byte[4].Concat(nonceBytes).ToArray();
if (nonceBytes.Length != 12) throw new InvalidOperationException($"nonce must be 12 bytes, got {nonceBytes.Length}"); Type guard
bool IsChaCha20Nonce(byte[] n) => n is { Length: 12 }; Try / catch
try { cipher = new CSChaCha20(key, nonce, 0); }
catch (ArgumentException ex) { Console.Error.WriteLine($"Bad nonce: {ex.Message}"); } Prevention
- Pad 8-byte nonces to 12 bytes with four leading zero bytes.
- Trim decoded IVs to exactly 12 bytes.
- Prefer ChaCha20Util.DecryptPer1024Bytes which handles 8-byte nonces automatically.
When it happens
Trigger: Passing an 8-byte nonce directly to CSChaCha20 without padding to 12 bytes, a 16-byte IETF 96-bit variant mismatch, or a decoded IV with padding bytes included.
Common situations: Older 8-byte-nonce ChaCha20 streams fed into this 12-byte-nonce implementation; IV attributes parsed with an extra 4 bytes; hex-decoded IV of odd length padded incorrectly.
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/5074295a7c8205ca.
Report an issue: GitHub.
Appendix: source
Thrown at src/N_m3u8DL-RE/Crypto/CSChaCha20.cs:173
/// <param name="nonce">
/// A 12-byte (96-bit) nonce, treated as a concatenation of three 32-bit little-endian integers
/// </param>
/// <param name="counter">
/// A 4-byte (32-bit) block counter, treated as a 32-bit little-endian integer
/// </param>
private void IvSetup(byte[] nonce, uint counter)
{
if (nonce == null)
{
// There has already been some state set up. Clear it before exiting.
Dispose();
throw new ArgumentNullException("Nonce is null");
}
if (nonce.Length != allowedNonceLength)
{
// There has already been some state set up. Clear it before exiting.
Dispose();
throw new ArgumentException($"Nonce length must be {allowedNonceLength}. Actual: {nonce.Length}");
}
state[12] = counter;
state[13] = Util.U8To32Little(nonce, 0);
state[14] = Util.U8To32Little(nonce, 4);
state[15] = Util.U8To32Little(nonce, 8);
}
#region Encryption methods
/// <summary>
/// Encrypt arbitrary-length byte array (input), writing the resulting byte array to preallocated output buffer.
/// </summary>
/// <remarks>Since this is symmetric operation, it doesn't really matter if you use Encrypt or Decrypt method</remarks>
/// <param name="output">Output byte array, must have enough bytes</param>
/// <param name="input">Input byte array</param>View on GitHub (pinned to e113dee70c)