首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RC4加密java

RC4加密java
EN

Stack Overflow用户
提问于 2012-09-05 21:01:29
回答 6查看 47.8K关注 0票数 6

嗨,我正在努力用Java实现RC4算法。我发现这个代码是帮助我理解这个想法的一个例子:

代码语言:javascript
复制
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);
  }
}

我没有什么问题:

  1. 为什么纯文本在上面的代码中是一个int数组?
  2. 当我测试这段代码时,我得到了奇怪的结果,有人能给我解释一下吗?下面是我要测试的代码: 公共类RC4_Main { public静态void ( String args[])抛出异常{String关键字= "hello";byte[] keytest = keyword.getBytes();// int[]关键字为字节int[] text = {1、2、3、4、5};// text as 12345 RC4 rc4 =新RC4(keytest);System.out.print(“\n原始文本:");for (int i= 0;i< text.length;i++) { System.out.print(texti);} int[]密码=rc4.Encrypt(文本);//加密System.out.print(“\n密码:");for (int i= 0;i< cipher.length;i++) {System.out.print(密码);} int[] backtext =rc4.Declt(密码);//解密System.out.print(“\n回文本:");for (int i= 0;i< backtext.length;i++) { System.out.print(backtexti);} System.out.println();}

结果是:(原文和回文本不一样)为什么?

代码语言:javascript
复制
original text: 12345
cipher: 1483188254174
back to text: 391501310217
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-09-05 22:53:48

有几件事需要注意:

  • 当需要无符号字节(例如索引)时,Java并不容易使用;
  • 如果您在ST中创建了一个状态,那么当您使用相同的实例解密时,您应该注意到这些值发生了变化;
  • 上面的代码不是很有效率的内存,您可以轻松地重写它来获取字节数组;
  • 要使用字符串,在将参数重构为byte[]之后,首先需要使用字符编码,例如使用String.getBytes(Charset charset)(http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#getBytes(java.nio.charset.Charset%29)

为了让生活更简单,并在深夜进行一些有趣的黑客攻击,我改进了您的代码,并使用零d输出字节数组对rfc6229中的单个向量进行了测试。

更新:正如micahk在下面指出的那样,使用的邪恶的C XOR交换阻止了该代码加密Java中输入的最后字节。使用常规的旧掉期来修复它。

警告:下面的代码应该被视为编码练习。请使用经过良好审核的库来执行RC4 (或Ron的代码4、ARC4等),而不是下面的代码片段。在你的申请中。这意味着使用Cipher.getInstance("RC4");或ARC4类。

代码语言:javascript
复制
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);
    }
}

编码愉快。

票数 10
EN

Stack Overflow用户

发布于 2013-11-27 02:29:44

由于使用xor-交换技术,Java代码有一个错误:

代码语言:javascript
复制
        S[i] ^= S[j];
        S[j] ^= S[i];
        S[i] ^= S[j];

而不是这样,您需要使用一个临时变量,如下所示。我还没有深入探究为什么xor交换的结果不像预期的那样,但是我有解密错误,这些错误都是通过简单的直接交换解决的。我怀疑这是为了执行xor操作而从字节到int的隐式转换的一个微妙的副作用。

代码语言:javascript
复制
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;
            for (int i = 0; i < 256; i++) {
                j = (j + S[i] + T[i]) & 0xFF;
                byte temp = S[i];
                S[i] = S[j];
                S[j] = temp;
            }
        }
    }

    public byte[] encrypt(final byte[] plaintext) {
        final byte[] ciphertext = new byte[plaintext.length];
        int i = 0, j = 0, k, t;
        for (int counter = 0; counter < plaintext.length; counter++) {
            i = (i + 1) & 0xFF;
            j = (j + S[i]) & 0xFF;
            byte temp = S[i];
            S[i] = S[j];
            S[j] = temp;
            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);
    }
}
票数 4
EN

Stack Overflow用户

发布于 2012-09-05 21:14:12

您的整数数组ST尚未构造。因此,一旦尝试使用NullPointerException,就会得到它们。

看看其余的代码,我猜它们应该是256项数组:

代码语言:javascript
复制
private int[] S = new int[256];
private int[] T = new int[256];
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12289717

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档