RC4加密java

Ron*_*ing 5 java encryption rc4-cipher

您好我在尝试用Java实现RC4算法.我发现这段代码是一个帮助我理解这个想法的例子:

public class RC4 {
  private int[] S = new int[256];
  private int[] T = new int[256];
  private int keylen;

  public RC4(byte[] key) throws Exception {
    if (key.length < 1 || key.length > 256) {
      throw new Exception("key must be between 1 and 256 bytes");
    } else {
      keylen = key.length;
      for (int i = 0; i < 256; i++) {
        S[i] = i;
        T[i] = key[i % keylen];
      }
      int j = 0;
      for (int i = 0; i < 256; i++) {
        j = (j + S[i] + T[i]) % 256;
        S[i] ^= S[j];
        S[j] ^= S[i];
        S[i] ^= S[j];
      }
    }
  }

  public int[] encrypt(int[] plaintext) {
    int[] ciphertext = new int[plaintext.length];
    int i = 0, j = 0, k, t;
    for (int counter = 0; counter < plaintext.length; counter++) {
      i = (i + 1) % 256;
      j = (j + S[i]) % 256;
      S[i] ^= S[j];
      S[j] ^= S[i];
      S[i] ^= S[j];
      t = (S[i] + S[j]) % 256;
      k = S[t];
      ciphertext[counter] = plaintext[counter] ^ k;
    }
    return ciphertext;
  }

  public int[] decrypt(int[] ciphertext) {
    return encrypt(ciphertext);
  }
}
Run Code Online (Sandbox Code Playgroud)

我有几个问题:

  1. 为什么纯文本int在上面的代码中是一个数组?

  2. 当我测试这段代码时,我得到了奇怪的结果,有人可以向我解释一下吗?这里我的代码测试:

    public class RC4_Main {
    
        public static void main(String args[]) throws Exception {
            String keyword = "hello";
            byte[] keytest = keyword.getBytes(); //convert keyword to byte
    
            int[] text = {1, 2, 3, 4, 5}; // text as 12345
    
            RC4 rc4 = new RC4(keytest);
    
            System.out.print("\noriginal text: ");
            for (int i = 0; i < text.length; i++) {          
                System.out.print(text[i]);          
            }    
    
            int[] cipher = rc4.encrypt(text); //encryption      
            System.out.print("\ncipher: ");
            for (int i = 0; i < cipher.length; i++) {          
                System.out.print(cipher[i]);          
            }    
    
            int[] backtext = rc4.decrypt(cipher); //decryption
            System.out.print("\nback to text: ");
            for (int i = 0; i < backtext.length; i++) {          
                System.out.print(backtext[i]);            
            } 
            System.out.println();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

结果如下:(原文和回文不是SAME)为什么???

original text: 12345
cipher: 1483188254174
back to text: 391501310217
Run Code Online (Sandbox Code Playgroud)

Maa*_*wes 9

有几点需要注意:

  • 当你需要无符号字节时(例如索引),Java不是很容易使用;
  • 如果你在S和中创建一个状态T,你应该注意到这些值会发生变化,当你使用相同的实例进行解密时,你会采用加密状态;
  • 上面的代码在内存方面效率不高,你可以轻松地重写它来取字节数组;
  • 要使用String,在重构参数后byte[],首先需要先使用,例如使用String.getBytes(Charset charset);

为了让生活更轻松,并有一些有趣的深夜黑客,我改进了你的代码,并使用零输出字节数组对rfc6229中的单个向量进行了测试.

更新:正如micahk指出的那样,使用的邪恶C XOR交换阻止了此代码加密Java中输入的最后一个字节.使用常规旧交换修复它.

警告:以下代码应视为编码练习.请使用经过严格审查的库而不是下面的代码片段在您的应用程序中执行RC4(或Ron的Code 4,ARC4等).这意味着Cipher.getInstance("RC4");在Bouncy Castle中使用或使用ARC4课程.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

快乐的编码.

  • 或者尝试http://stackoverflow.com/questions/2817752/java-code-to-convert-byte-to-hexadecimal (2认同)