为什么我需要两个密钥才能进行AES加密?

时间:2014-10-08 21:54:56

标签: java encryption aes

我正在尝试为某些文本实施AES加密,而我正在寻找最终归结为一个加密和解密密码的解决方案。我在这个网站上找到了一个可行的解决方案:Simple Java AES encrypt/decrypt example

import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class Encryptor {
    public static String encrypt(String key1, String key2, String value) {
        try {
            IvParameterSpec iv = new IvParameterSpec(key2.getBytes("UTF-8"));

            SecretKeySpec skeySpec = new SecretKeySpec(key1.getBytes("UTF-8"),
                    "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(value.getBytes());
            System.out.println("encrypted string:"
                    + Base64.encodeBase64String(encrypted));
            return Base64.encodeBase64String(encrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public static String decrypt(String key1, String key2, String encrypted) {
        try {
            IvParameterSpec iv = new IvParameterSpec(key2.getBytes("UTF-8"));

            SecretKeySpec skeySpec = new SecretKeySpec(key1.getBytes("UTF-8"),
                    "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));

            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {

        String key1 = "Bar12345Bar12345"; // 128 bit key
        String key2 = "ThisIsASecretKet";
        System.out.println(decrypt(key1, key2,
                encrypt(key1, key2, "Hello World")));
    }
}

此算法使用key1和key2,并且不理解为什么他们需要这两个。每个密钥的用途是什么,将key1保留为所有时间并将密钥2替换为个人密码是否安全?

由于

1 个答案:

答案 0 :(得分:7)

'key1'是你的密钥。在此代码中,通过在密码上调用String.getBytes()来获取字节数组。请参阅this answer,了解为何不适用,以及一些建议的备选方案。

'key2'被错误命名;它实际上是Initialization Vector(或简称“IV”)。这是一个随机的字节序列,可以防止同一个明文始终被转换为相同的密文。

应使用SecureRandom.getBytes()为每个加密邮件生成随机IV。对于AES,IV应为16字节(128位)。 IV是not a secret;它应该与密文一起发送,以便收件人可以使用它(以及密钥)来解密消息。

加密后,我建议将IV字节前置到密文字节,然后对结果字节数组进行Base64编码。

至于代码的结构,不需要将IV传递给加密方法;加密方法可以在内部生成IV。同样,如果密文以IV为前缀,那么您不需要将IV传递给decrypt方法;相反,decrypt方法可以假设消息的前16个字节是IV。

一般来说,仅加密并不能确保消息没有被篡改。如果您想检测攻击者何时篡改您的加密邮件,您可以apply a Message Authentication Code像HMAC一样使用iv + cyphertext。