didi/DoKit · error · IllegalArgumentException

key must be between 1 and 256 bytes

Error message

key must be between 1 and 256 bytes

What it means

EncryptUtils.rc4 implements the RC4 stream cipher, whose key scheduling algorithm builds two 256-entry tables by repeating the key (iK[i] = key[i % keyLen]). The algorithm requires a 1..256 byte key; an empty key would divide by zero in the modulo and a >256 key is outside the spec, so both are rejected.

Source

Thrown at Android/dokit-util/src/main/java/com/didichuxing/doraemonkit/util/EncryptUtils.java:1145

            } else {
                return cipher.doFinal(data);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Return the bytes of RC4 encryption/decryption.
     *
     * @param data The data.
     * @param key  The key.
     */
    public static byte[] rc4(byte[] data, byte[] key) {
        if (data == null || data.length == 0 || key == null) return null;
        if (key.length < 1 || key.length > 256) {
            throw new IllegalArgumentException("key must be between 1 and 256 bytes");
        }
        final byte[] iS = new byte[256];
        final byte[] iK = new byte[256];
        int keyLen = key.length;
        for (int i = 0; i < 256; i++) {
            iS[i] = (byte) i;
            iK[i] = key[i % keyLen];
        }
        int j = 0;
        byte tmp;
        for (int i = 0; i < 256; i++) {
            j = (j + iS[i] + iK[i]) & 0xFF;
            tmp = iS[j];
            iS[j] = iS[i];
            iS[i] = tmp;
        }

        final byte[] ret = new byte[data.length];

View on GitHub (pinned to 626827cddb)

Solutions

  1. Verify 1 <= key.length <= 256 before calling; log the actual length when it fails.
  2. If the key comes from encoded text, decode first (e.g. Base64.decode) rather than using getBytes() of the encoded form.
  3. For empty keys, fail at configuration/load time with a clear error instead of reaching the cipher.

Example fix

// before
byte[] key = readFileOrEmpty("rc4.key"); // may be byte[0]
byte[] out = EncryptUtils.rc4(data, key); // throws

// after
byte[] key = readFile("rc4.key");
if (key == null || key.length < 1 || key.length > 256) throw new IllegalStateException("bad RC4 key");
byte[] out = EncryptUtils.rc4(data, key);
Defensive patterns

Strategy: validation

Validate before calling

boolean okKey = key != null && key.length >= 1 && key.length <= 256;
byte[] out = okKey ? EncryptUtils.rc4(data, key) : null;

Try / catch

try { out = EncryptUtils.rc4(data, key); } catch (IllegalArgumentException e) { throw new SecurityException("Invalid RC4 key length", e); }

Prevention

When it happens

Trigger: Passing an empty byte[] key (data non-empty, key length 0); passing a key longer than 256 bytes such as a raw RSA/EC public key or an X.509 certificate blob instead of a symmetric secret; null keys return null earlier and do not throw.

Common situations: Loading keys from misconfigured files/assets that resolve to empty arrays; using a hex/base64 string as key without decoding so its byte length balloons past 256; key-generation code that failed and returned an empty array.

Related errors


AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14). Data as JSON: /api/errors/2fa01761156ee569. Report an issue: GitHub.