【问题标题】:AES - Storing IV with Ciphertext in JavaAES - 在 Java 中使用密文存储 IV
【发布时间】:2023-03-19 16:22:01
【问题描述】:

我已经实现了 CBC 模式 AES 加密和解密机制,在该机制中,我为每次推荐的加密尝试生成随机 IV 和随机密钥。

现在,我将密钥保存在单独的文件中,IV 保存在另一个文件中,但是在浏览了不同的论坛后,我发现 IV 不应该保持安全,并且应该在加密时附加密文并在解密时我们可以从该密码字节数组中提取出 16 个字节..

现在,我尝试了一段 sn-p 代码来达到同样的效果,但结果并不好,因为第一个块没有正确加密;但是该块的其余部分可以。

谁能告诉我我的方法有什么问题?

任何帮助将不胜感激谢谢:)。

public static byte[] encrypt (byte[] plaintext,SecretKey key,byte[] IV ) throws Exception {

        //Get Cipher Instance
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        //Create SecretKeySpec
        SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "AES");

        //Create IvParameterSpec
        IvParameterSpec ivSpec = new IvParameterSpec(IV);

        System.out.println( "IV encrypt= " + ivSpec );

        //Initialize Cipher for ENCRYPT_MODE
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);

        //Perform Encryption
        byte[] cipherText = cipher.doFinal(plaintext);

        ByteArrayOutputStream b = new ByteArrayOutputStream();

        b.write(IV);
        b.write( cipherText );

        return b.toByteArray();
    }

--------------------------------------------------------------------------
public static String decrypt (byte[] cipherText, SecretKey key ) throws Exception
    {
        //Get Cipher Instance
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        //Create SecretKeySpec
        SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "AES");

        byte[] iv = Arrays.copyOfRange( cipherText , 0, 16);

        //Create IvParameterSpec
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        //Initialize Cipher for DECRYPT_MODE
        cipher.init(Cipher.DECRYPT_MODE, keySpec,ivSpec);

        //Perform Decryption
        byte[] decryptedText = cipher.doFinal(cipherText);

        return new String(decryptedText);
    }

----------------------------------------------------------------------------

KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128);

        // Generate Key
        SecretKey key = keyGenerator.generateKey();

        // Generating IV.
        byte[] IV = new byte[16];
        SecureRandom random = new SecureRandom();
        random.nextBytes(IV);

        System.out.println("Original Text  : " + plainText);

        byte[] cipherText = encrypt(plainText.getBytes("UTF-8") ,key, IV);



        String decryptedText = decrypt(cipherText,key, IV);
        System.out.println("DeCrypted Text : "+decryptedText);

结果

Original Text  : This is a plain text which need to be encrypted by AES Algorithm with CBC Mode
DeCrypted Text : ûª¯Î¥pAï2EÞi+¼‹Ý$8ŶÄDDNâOæàtext which need to be encrypted by AES Algorithm with CBC Mode

【问题讨论】:

  • 您实际上并没有对 IV 做任何事情。密码对象不会仅仅因为变量的名称是“IV”而将其发送出去。它已在 init() 调用中提供。

标签: java encryption


【解决方案1】:

只是因为你在这里复制了 IV:

byte[] iv = Arrays.copyOfRange( cipherText , 0, 16);

并不意味着当您尝试解密它时它仍然不存在:

byte[] decryptedText = cipher.doFinal(cipherText);

您应该解密 ciphertext 除了 中前 16 个字节的所有内容。目前,您还在 IV 上执行 AES 解密 - 这就是您收到垃圾的原因。

【讨论】:

  • 那我应该如何将它从我的密文中分离出来呢?
  • 另外,在加密中,我使用没有 IV 的 cipher.init 并将其添加到最终字节数组中。那么 cbc 在这里满足吗?在我的情况下,它是使用 IV 与第一个块进行异或还是使用 0 IV?
  • 你肯定需要用 iv 初始化密码进行加密——否则它怎么知道使用它?
  • 您不需要分离它,只需使用 Arrays.copyOfRange 提取密文,就像您对 iv 所做的那样。
  • 问题已解决代码:IvParameterSpec ivSpec = new IvParameterSpec(IV); System.out.println( "IV encrypt= " + ivSpec ); //Initialize Cipher for ENCRYPT_MODE cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); 解密:IvParameterSpec ivSpec = new IvParameterSpec( cipherText, 0, 16 ); cipherText = Arrays.copyOfRange ( cipherText, 16, cipherText.length); //Initialize Cipher for DECRYPT_MODE cipher.init(Cipher.DECRYPT_MODE, keySpec,ivSpec);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-28
  • 1970-01-01
  • 2012-02-21
  • 1970-01-01
相关资源
最近更新 更多