RC4 encryption java

后端 未结 6 1015
没有蜡笔的小新
没有蜡笔的小新 2020-12-14 05:12

Hi there I am trying to implement the RC4 algorithm in Java. I found this code as an example that help me to understand the idea:

public class RC4 {
  privat         


        
6条回答
  •  误落风尘
    2020-12-14 05:35

    There are a few things to notice:

    • Java is not very easy to use when you require unsigned bytes (e.g. for indexing);
    • if you create a state in S and T, you should really notice that these values change, when you decrypt with the same instance you take the state used for encryption;
    • the above code is not very efficient memory wise, and you can easily rewrite it to take byte arrays;
    • to use a String, after refactoring the arguments to byte[], you first need to use character-encoding first, e.g. using String.getBytes(Charset charset);

    To make life easier, and to have some fun late night hacking, I improved your code and tested it against a single vector in rfc6229 using a zero'd out byte array.

    UPDATE: As micahk points out below, the evil C XOR swap that was used prevented this code from encrypting the final byte of input in Java. Using regular old swaps fixes it.

    Warning: the code below should be considered a coding exercise. Please use a well vetted library instead of the code snippet below to perform RC4 (or Ron's Code 4, ARC4 etc.) in your application. That means using Cipher.getInstance("RC4"); or the ARC4 classes in Bouncy Castle.

    public class RC4 {
        private final byte[] S = new byte[256];
        private final byte[] T = new byte[256];
        private final int keylen;
    
        public RC4(final byte[] key) {
            if (key.length < 1 || key.length > 256) {
                throw new IllegalArgumentException(
                        "key must be between 1 and 256 bytes");
            } else {
                keylen = key.length;
                for (int i = 0; i < 256; i++) {
                    S[i] = (byte) i;
                    T[i] = key[i % keylen];
                }
                int j = 0;
                byte tmp;
                for (int i = 0; i < 256; i++) {
                    j = (j + S[i] + T[i]) & 0xFF;
                    tmp = S[j];
                    S[j] = S[i];
                    S[i] = tmp;
                }
            }
        }
    
        public byte[] encrypt(final byte[] plaintext) {
            final byte[] ciphertext = new byte[plaintext.length];
            int i = 0, j = 0, k, t;
            byte tmp;
            for (int counter = 0; counter < plaintext.length; counter++) {
                i = (i + 1) & 0xFF;
                j = (j + S[i]) & 0xFF;
                tmp = S[j];
                S[j] = S[i];
                S[i] = tmp;
                t = (S[i] + S[j]) & 0xFF;
                k = S[t];
                ciphertext[counter] = (byte) (plaintext[counter] ^ k);
            }
            return ciphertext;
        }
    
        public byte[] decrypt(final byte[] ciphertext) {
            return encrypt(ciphertext);
        }
    }
    

    Happy coding.

提交回复
热议问题