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

  1. Left-pad 8-byte nonces with four zero bytes to make 12 bytes (as ChaCha20Util.DecryptPer1024Bytes does).
  2. Trim decoded IV buffers to exactly 12 bytes.
  3. Use ChaCha20Util.DecryptPer1024Bytes, which handles the 8-byte padding automatically.
  4. 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

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)