AES 加密,用于十六进制密钥、IV 和 Java 中的数据



我必须用密钥加密十六进制字符串,IV也作为十六进制数据。请在下面找到我使用的代码。问题是我需要加密的字符串是明文格式。我需要将明文转换为十六进制,但我不知道该怎么做。任何人都可以帮我吗?

我一直在使用网络工具进行确认,

http://aes.online-domain-tools.com/

static byte[] IV = {  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
static String plaintext = "00010101010102020202020303030303"; 
static byte[] encryptionKey = {0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
    0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41  };
public static void main(String[] args) {
    try {
        System.out.println("==Java==");
        System.out.println("plain:   " + plaintext);
        byte[] cipher = encrypt(plaintext, encryptionKey);
        System.out.print("cipher:  ");
        for (int i = 0; i < cipher.length; i++) {
            // System.out.print(new Integer(cipher[i]) + " ");
            byte b = cipher[i];
            System.out.print(String.format("%02x", b & 0xFF) + " ");
        }
        String decrypted = decrypt(cipher, encryptionKey);
        System.out.println("decrypt: " + decrypted);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public static byte[] encrypt(String plainText, byte[] encryptionKey)
        throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    SecretKeySpec key = new SecretKeySpec(encryptionKey, "AES");
    cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));
    return cipher.doFinal(plainText.getBytes("UTF-8"));
}
public static String decrypt(byte[] cipherText, byte[] encryptionKey)
        throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    SecretKeySpec key = new SecretKeySpec(encryptionKey, "AES");
    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(IV));
    return new String(cipher.doFinal(cipherText), "UTF-8");
}

对于上述数据,我应该得到,

B6

06 DA B9 CD DC 2D 89 4B 49 0A AB 4E E7 DC 58

但相反,我得到了,

E3 62 34 3F AD 8b 89 37 57 81 91 31 EE 79 49 52 26 BF 40 CB D0 CE 36 BD 8A 04 6B AF 34 D9 F3 D7

提前谢谢。

从中学到的最好的东西可能是,CBC(以及底层分组密码)等现代操作模式对二进制数据进行操作,通常作为一组字节提供。

从这个意义上说,最好尽可能坚持使用二进制数据。不要使用超过绝对必要的转换,并且仅在供人类使用时才使用十六进制编码。如果需要使用基于文本的表示形式传输二进制文件,则可以使用 Base 64 编码。

编码/解码最好使用Apache Commons Codec,Guava,Bouncy Castle等库来执行,Java 8仍然没有十六进制编码/解码字节数组(叹息)。


我创建了一个小代码示例,它输出十六进制格式,就好像它是 Java 字节数组文字一样。我会留给你创建不同的版本。

static byte[] IV = {  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
static byte[] plaintext = { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03 }; 
static byte[] encryptionKey = {0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
    0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41  };
public static void main(String[] args) {
    try {
        System.out.println("==Java==");
        System.out.println("plain:   " + toJavaHex(plaintext));
        byte[] cipher = encrypt(plaintext, encryptionKey);
        System.out.println("cipher:  " + toJavaHex(cipher));
        String decrypted = toJavaHex(decrypt(cipher, encryptionKey));
        System.out.println("decrypt: " + decrypted);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public static String toJavaHex(byte[] data) {
    StringBuilder sb = new StringBuilder(13 * data.length);
    for (int i = 0; i < data.length; i++) {
        if (i != 0) {
            sb.append(", ");
        }
        sb.append(String.format("(byte) 0x%02x", data[i]));
    }
    return sb.toString();
}
public static byte[] encrypt(byte[] plainText, byte[] encryptionKey)
        throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    SecretKeySpec key = new SecretKeySpec(encryptionKey, "AES");
    cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));
    return cipher.doFinal(plainText);
}
public static byte[] decrypt(byte[] cipherText, byte[] encryptionKey)
        throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    SecretKeySpec key = new SecretKeySpec(encryptionKey, "AES");
    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(IV));
    return cipher.doFinal(cipherText);
}

最新更新