使用RC4加密和解密

时间:2017-04-15 00:44:34

标签: java

我正在尝试用Java中的RC4编写加密和解密输入文本的代码。有谁知道如何解决它?

我的代码:

import java.util.Arrays;

public class RC4 {

    private static final int SBOX_LEN = 256;
    private static final int MIN_KEY_LEN = 5;

    private byte[] key = new byte[SBOX_LEN - 1];

    private int[] sbox = new int[SBOX_LEN];

    public RC4() {
        initialize();
    }

    public RC4(String key) {

        this();
        setKey(key);
    }

    public static void main(String[] args) {

        RC4 rc4 = new RC4();

        byte[] cipherText = rc4.encryptMessage(args[0], args[1]);
        System.out.println(Arrays.toString(cipherText));

        String plainText = rc4.decryptMessage(cipherText, args[1]);
        System.out.println(plainText);
    }

    private void initialize() {

        Arrays.fill(key, (byte) 0);
        Arrays.fill(sbox, 0);
    }

    public byte[] encryptMessage(String message, String key) {

        initialize();
        setKey(key);

        byte[] crypt = crypt(message.getBytes());
        initialize();

        return crypt;
    }

    public String decryptMessage(byte[] message, String key) {

        initialize();
        setKey(key);

        byte[] msg = crypt(message);
        initialize();

        return new String(msg);
    }

    public byte[] crypt(final byte[] msg) {

        sbox = initializeSBox(key);

        byte[] code = new byte[msg.length];
        int i = 0;
        int j = 0;

        for (int n = 0; n < msg.length; n++) {

            i = (i + 1) % SBOX_LEN;
            j = (j + sbox[i]) % SBOX_LEN;
            swap(i, j, sbox);

            int rand = sbox[(sbox[i] + sbox[j]) % SBOX_LEN];
            code[n] = (byte) (rand ^ msg[n]);
        }

        return code;
    }

    private int[] initializeSBox(byte[] key) {

        int[] sbox = new int[SBOX_LEN];
        int j = 0;

        for (int i = 0; i < SBOX_LEN; i++) {
            sbox[i] = i;
        }

        for (int i = 0; i < SBOX_LEN; i++) {
            j = ((j + sbox[i] + (key[i % key.length])) & 0xFF) % SBOX_LEN;
            swap(i, j, sbox);
        }

        return sbox;
    }

    private void swap(int i, int j, int[] sbox) {

        int temp = sbox[i];

        sbox[i] = sbox[j];
        sbox[j] = temp;
    }

    public void setKey(String key) {

        if (!((key.length() >= MIN_KEY_LEN) && (key.length() < SBOX_LEN))) {

            throw new RuntimeException(String.format("Key length must be between %d and %d", MIN_KEY_LEN, SBOX_LEN - 1));
        }

        this.key = key.getBytes();
    }
}

1 个答案:

答案 0 :(得分:1)

RC4是一个坏算法,如果要高度保护数据,建议不要再使用它。

如果仍然需要有效的实现,则无需在代码中重新创建算法。 Java API javax.crypto可以为您完成此任务。只需生成一个密钥,然后将init方法设置为加密/解密模式即可。

static String decryptRC4() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException{

    byte[] testDataBytes = "testString".getBytes();

    KeyGenerator rc4KeyGenerator = KeyGenerator.getInstance("RC4");
    SecretKey key = rc4KeyGenerator.generateKey();

    // Create Cipher instance and initialize it to encrytion mode
    Cipher cipher = Cipher.getInstance("RC4");  // Transformation of the algorithm
    cipher.init(Cipher.ENCRYPT_MODE, key);
    byte[] cipherBytes = cipher.doFinal(testDataBytes);

    // Reinitialize the Cipher to decryption mode
    cipher.init(Cipher.DECRYPT_MODE,key, cipher.getParameters());
    byte[] testDataBytesDecrypted = cipher.doFinal(cipherBytes);

    System.out.println("Decrypted Data : "+new String(testDataBytesDecrypted));
    return new String(testDataBytesDecrypted);
}

输出: enter image description here

如果您需要将加密的数据作为url的一部分发送,请使用Base64Encoding然后发送。

例如

    static String decryptRC4() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException{

    byte[] plainBytes = "testString".getBytes();

    KeyGenerator rc4KeyGenerator = KeyGenerator.getInstance("RC4");
    SecretKey key = rc4KeyGenerator.generateKey();

    // Create Cipher instance and initialize it to encrytion mode
    Cipher cipher = Cipher.getInstance("RC4");  // Transformation of the algorithm
    cipher.init(Cipher.ENCRYPT_MODE, key);
    byte[] cipherBytes = cipher.doFinal(plainBytes);

    String encoded = encodeBase64(cipherBytes);

    String decoded = decodeBase64(encoded);

    // Reinitialize the Cipher to decryption mode
    cipher.init(Cipher.DECRYPT_MODE,key, cipher.getParameters());
    byte[] plainBytesDecrypted = cipher.doFinal(Hex.decode(decoded));

    System.out.println("Decrypted Data : "+new String(plainBytesDecrypted));
    return new String(plainBytesDecrypted);
}

static String decodeBase64(String encodedData){
    byte[] b = Base64.getDecoder().decode(encodedData);
    String decodedData = DatatypeConverter.printHexBinary(b);
    return decodedData;
}

static String encodeBase64(byte[] data){
    byte[] b = Base64.getEncoder().encode(data);
    String encodedData = new String(b);
    /*String encodedData = DatatypeConverter.printHexBinary(b);*/
    return encodedData;
}

**提示:**如上所示,使用Hex.decode从base64解码的字符串中获取字节,否则会出现编码问题。尽可能使用十六进制进行转换,并使用Bouncycastle方法转换为字节数组。

需要进口:

import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.xml.bind.DatatypeConverter;

import org.apache.commons.codec.DecoderException;
import org.bouncycastle.util.encoders.Hex;

此外,如果您是根据自己的字符串生成密钥的,则可以使用MD5Hashing进行加密。