当前位置: 首页 > 知识库问答 >
问题:

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

曹涵润
2023-03-14
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")));
    }
}

谢谢

共有1个答案

法浩壤
2023-03-14

“Key1”是您的密钥。在这段代码中,字节数组是通过对密码调用String.getBytes()获得的。请参阅下面的答案,了解为什么这是不可取的,以及一些建议的替代方案。

“key2”命名错误;它实际上是一个初始化向量(或简称'IV')。这是一个随机的字节序列,防止相同的明文总是被转换成相同的密文。

应该使用Securerandom.getBytes()为每个加密消息生成一个随机IV。对于AES,IV应该是16字节(128位)。IV不是秘密;它应该与密文一起发送,这样接收者就可以使用它(连同密钥)来解密消息。

在加密之后,我建议将IV字节预置到密文字节中,然后对得到的字节数组进行base64编码。

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

一般说来,仅仅加密并不能确保消息没有被篡改。如果您想检测攻击者何时篡改您的加密消息,您可以将类似于HMAC的消息身份验证代码应用于iv+CypherText。

 类似资料:
  • 我正在从https://docs.AWS.amazon.com/cli/latest/reference/kms/encrypt.html和https://docs.AWS.amazon.com/cli/latest/reference/kms/decrypt.html读取AWS加密cli文档。我发现我可以在不创建数据密钥的情况下加密/解密。当我阅读https://docs.aws.amazon.

  • 我正在尝试将我的应用程序从128位AES密钥升级为256位AES。然而,当我将第54行从128更改为256时,我会得到以下密钥大小错误。 java.security.无效密钥异常: 非法的密钥大小 我已正确安装了JCE文件,我的应用程序生成较长的密钥这一事实证明了这一点。 我在其他文章中看到过“AES / CBC / PKCS7Padding”加密方法,但这只会让我遇到这个例外:

  • 在《计算机系统程序员的观点》(2.3.5)一书中,计算二的补码乘法的方法描述如下: C中的有符号乘法通常是通过将2w位乘积截断为w位来执行的。将二补码数截断为w位相当于首先计算其取模2w的值,然后从无符号转换为二补码。 因此,对于相似的位级操作数,为什么无符号乘法不同于二的补乘法?为什么两个补乘法需要进行符号扩展? 为了计算无符号和二补加法的相同位级表示,我们可以转换二补的参数,然后执行无符号加法

  • 问题内容: 我正在尝试快速实施AES加密。Android和C#的加密解密工作正常。我需要迅速实施它。这是android 的当前代码,其后是C#。 我尝试使用 CryptoSwift 跨平台AES加密 但是,这些都不起作用。当我在服务器上发送加密的字符串时,它没有被解密。 任何帮助将不胜感激 问题答案: 确保使用相同的参数,这些参数似乎是带有iv (实际上是PKCS#7)填充和16字节(128位)密

  • 问题内容: 我正在编写一个用于传输文件的小型应用程序,或多或少地将其作为一种学习更多编程加密基础的方法。这个想法是生成一个RSA密钥对,交换公共密钥,并发送AES iv和密钥以进一步解密。我想用接收者的RSA公钥加密AES密钥,如下所示: 然后,我将密钥值写给接收器,并按如下方式解密: 在控制台的另一端,我将其作为输出: 此外,如果我创建一个大小为16的字节数组,并将cipher.doFinal(

  • 我正在使用AES加密实现一个加密字符串的程序,并希望将我的“密钥”保存在一个文件中,而不是在源代码中硬编码。 但是,这给我带来了一个问题,我如何保护这个秘密密钥不被他人看到? 如果我要再次加密这个“密钥文件”,我将不得不再次处理同样的问题。 我该如何处理这些问题? 参考:https://wiki.sei.cmu.edu/confluence/display/java/MSC61-J.不要使用不安全