TheAlgorithms/C-Sharp · error · ArgumentException

The length of key should be divisible by 16

Error message

The length of key should be divisible by 16

What it means

FeistelCipher.Decode requires the input text length to be a multiple of the 16-byte block size, since the ciphertext is split into fixed 16-byte blocks. If text.Length % 16 != 0, an ArgumentException is thrown noting the length must be divisible by 16 (the message text mentions `key` due to a nameof bug, but it is the text length that is wrong).

Solutions

  1. Ensure Decode receives exactly the string produced by Encode — do not trim, truncate, or append characters.
  2. Verify text.Length % 16 == 0 before calling Decode and fix the data source if not.
  3. Strip transport-added whitespace/newlines from the encoded text before decoding.
  4. Re-encode the plaintext with FeistelCipher.Encode to get properly padded ciphertext, then decode that.

Example fix

// before
cipher.Decode(corruptedCipherText, key); // length not multiple of 16
// after
if (corruptedCipherText.Length % 16 != 0)
    throw new InvalidOperationException("Ciphertext was truncated; re-encode the original text.");
var plain = cipher.Decode(corruptedCipherText, key);
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrEmpty(text) || text.Length % 16 != 0)
    throw new ArgumentException("Ciphertext must be non-empty and its length a multiple of 16.");

Type guard

static bool IsBlockAligned(string text) => text != null && text.Length % 16 == 0;

Try / catch

try
{
    var plain = feistel.Decode(cipherText, key);
}
catch (ArgumentException ex)
{
    // ciphertext corrupted/truncated: re-obtain or re-encode the data
    throw new InvalidOperationException("Ciphertext is not 16-byte block aligned; re-encode the source data.", ex);
}

Prevention

When it happens

Trigger: Calling FeistelCipher.Decode with a string whose length is not a multiple of 16, e.g. Decode("short", key) — 5 % 16 != 0 — throws. Also happens when encoded text was truncated or extra characters (whitespace, line breaks) were added in transport, as exercised by TestEncodedMessageSize/decoded.

Common situations: Copy-pasting ciphertext through systems that trimmed or wrapped it (email, logs, JSON), dropping characters; manually editing encoded output; decoding data encrypted by a different version or padding mode; confusing hex/encoded length with raw block size.

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 TheAlgorithms/C-Sharp@96e2905cab (2026-09-13). Data as JSON: /api/errors/27af3c4726bb8680. Report an issue: GitHub.

Appendix: source

Thrown at Algorithms/Encoders/FeistelCipher.cs:72

        }

        return encodedText.ToString();
    }

    /// <summary>
    ///     Decodes text that was encoded using specified key.
    /// </summary>
    /// <param name="text">Text to be decoded.</param>
    /// <param name="key">Key that was used to encode the text.</param>
    /// <exception cref="ArgumentException">Error: key should be more than 0x00001111 for better encoding, key=0 will throw DivideByZero exception.</exception>
    /// <exception cref="ArgumentException">Error: The length of text should be divisible by 16 as it the block lenght is 16 bytes.</exception>
    /// <returns>Decoded text.</returns>
    public string Decode(string text, uint key)
    {
        // The plain text will be padded to fill the size of block (16 bytes)
        if (text.Length % 16 != 0)
        {
            throw new ArgumentException($"The length of {nameof(key)} should be divisible by 16");
        }

        List<ulong> blocksListEncoded = GetBlocksFromEncodedText(text);
        StringBuilder decodedTextHex = new();

        foreach (ulong block in blocksListEncoded)
        {
            uint temp = 0;

            // decompose a block to two subblocks 0x0123456789ABCDEF => 0x01234567 & 0x89ABCDEF
            uint rightSubblock = (uint)(block & 0x00000000FFFFFFFF);
            uint leftSubblock = (uint)(block >> 32);

            // Feistel "network" - decoding, the order of rounds and operations on the blocks is reverted
            uint roundKey;
            for (int round = Rounds - 1; round >= 0; round--)
            {
                roundKey = GetRoundKey(key, round);

View on GitHub (pinned to 96e2905cab)