RC4加密java [英] RC4 encryption java
问题描述
public class RC4 {
private int [] S = new int [256];
private int [] T = new int [256];
private int keylen;
public RC4(byte [] key)throws异常{
if(key.length< 1 || key.length> 256){
throw new Exception(密钥必须在1到256字节之间);
} else {
keylen = key.length; (int i = 0; i <256; i ++){
S [i] = i;
T [i] = key [i%keylen];
}
int j = 0; (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; (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;
}
返回密文;
}
public int [] decrypt(int [] ciphertext){
return encrypt(ciphertext);
}
}
我有几个问题:
-
为什么上述代码中的纯文本是
int
数组? -
当我测试这个代码时,我得到了奇怪的结果,有人可以向我解释吗?这里我的代码测试:
public class RC4_Main {
public static void main(String args [ ])throws Exception {
String keyword =hello;
byte [] keytest = keyword.getBytes(); //将关键字转换为字节
int [] text = {1,2,3,4,5}; // text as 12345
RC4 rc4 = new RC4(keytest);
System.out.print(\\\
original text:); (int i = 0; i< text.length; i ++){
System.out.print(text [i]);
}
int [] cipher = rc4.encrypt(text); // encryption
System.out.print(\\\
cipher:); (int i = 0; i< cipher.length; i ++){
System.out.print(cipher [i]);
}
int [] backtext = rc4.decrypt(cipher); // decrypt
System.out.print(\\\
back to text:); (int i = 0; i< backtext.length; i ++){
System.out.print(backtext [i]);
}
System.out.println();
}
}
这是结果:(原始和回到文本不是SAME)为什么???
原文:12345
密码:1483188254174
返回文本:391501310217
有一些事情需要注意:
- 当您需要无符号字节(例如索引)时,Java不是很容易使用;
- 如果您在
S
和T
中创建状态,您应该真的注意到这些值改变,当你使用相同的实例解密 时,你采用加密的状态; - 上面的代码不是非常有效的内存明智,您可以轻松地重写它来采取字节数组;
- 使用一个String,在将参数重构为
byte []
之后首先需要使用字符编码,首先,例如使用String.getBytes(Charset charset)
;
更容易,并且有一些有趣的深夜黑客攻击,我改进了您的代码,并针对 rfc6229 使用零字节数组。
更新:由于micahk指出以下,使用的恶性C XOR交换阻止了此代码加密最终Java中的输入字节。使用常规的旧交换修复它。
警告:以下代码应被视为编码练习。请使用一个经过验证的库,而不是下面的代码片段在您的应用程序中执行RC4(或Ron的代码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(
键必须在1到256字节之间);
} else {
keylen = key.length; (int i = 0; i <256; i ++){
S [i] =(byte)i;
T [i] = key [i%keylen];
}
int j = 0;
byte tmp; (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 。长度];
int i = 0,j = 0,k,t;
byte tmp; (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);
}
返回密文;
}
public byte [] decrypt(final byte [] ciphertext){
return encrypt(ciphertext);
}
}
快乐编码
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 {
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);
}
}
I have few question:
Why is the plain-text an
int
array in the above code?When I test this code I get strange result, can somebody explain to me? Here my code to test:
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(); } }
Here is the result: (original and back to text are not SAME) why???
original text: 12345
cipher: 1483188254174
back to text: 391501310217
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
andT
, 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. usingString.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.
这篇关于RC4加密java的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!