【问题标题】:(AES Encryption) Code flaws, what should I be carefull with? [Code Provided][Java](AES加密)代码缺陷,我应该注意什么? [提供代码][Java]
【发布时间】:2017-01-17 14:26:17
【问题描述】:

感谢您抽出宝贵时间来帮助我!

此帖子已被编辑以减少信息,请参阅编辑部分

好吧,我已经在这件事上花费了我们的研究,最后我得到了一段工作代码..

但是加密不是犯错的地方,我想问一下我的代码是否真的安全!这对我来说真的很重要,因为我想将它实现到一个程序中,所以我的代码是......

import java.nio.file.Files;
import java.nio.file.Paths;

import java.util.Base64;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;


public class EncryptFile{
    private static final String FILE_IN = "./EncryptFile.java";
    private static final String FILE_ENCR = "./EncryptFile_encr.java";
    private static final String FILE_DECR = "./EncryptFile_decr.java";
     public static void main(String []args){
        try
        {
            Encryption("passwordisnottheactual", Files.readAllBytes(Paths.get(FILE_IN)));
            Decryption("passwordisnottheactual");

        }catch(Exception e){
            System.out.println(e.getMessage());
        }
     }
     private static void Encryption(String Key, byte[] byteArray) throws Exception
     {
        // Decode the base64 encoded Key
        byte[] decodedKey = Base64.getDecoder().decode(Key);
        // Rebuild the key using SecretKeySpec
        SecretKey secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); 

        // Cipher gets AES Algorithm instance
        Cipher AesCipher = Cipher.getInstance("AES");

        //Initialize AesCipher with Encryption Mode, Our Key and A ?SecureRandom?
        AesCipher.init(Cipher.ENCRYPT_MODE, secretKey, new SecureRandom());
        byte[] byteCipherText = AesCipher.doFinal(byteArray);

        //Write Bytes To File
        Files.write(Paths.get(FILE_ENCR), byteCipherText);


     }
     private static void Decryption(String Key) throws Exception
     {
        //Ddecode the base64 encoded string
        byte[] decodedKey = Base64.getDecoder().decode(Key);
        //Rebuild key using SecretKeySpec
        SecretKey secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); 

        //Read All The Bytes From The File
        byte[] cipherText = Files.readAllBytes(Paths.get(FILE_ENCR));

        //Cipher gets AES Algorithm Instance
        Cipher AesCipher = Cipher.getInstance("AES");

        //Initialize it in Decrypt mode, with our Key, and a ?SecureRandom?
        AesCipher.init(Cipher.DECRYPT_MODE, secretKey, new SecureRandom());

        byte[] bytePlainText = AesCipher.doFinal(cipherText);
        Files.write(Paths.get(FILE_DECR), bytePlainText);
     }
}

编辑

简单 Java AES 加密/解密示例的可能副本 - JFPicard

嗯,可能是,但这些答案使用 IVParameterSpec,我想知道是否 这行代码实际上是安全的,或者是不好的做法:

AesCipher.init(Cipher.DECRYPT_MODE, secretKey, new SecureRandom());

因为我每次都使用new SecureRandom(), 而且我还没有看到有人使用这样的 SecureRandom 对象。

【问题讨论】:

标签: java file encryption aes secure-random


【解决方案1】:
  1. 加密密钥
    • 密码是作为字符串传递的,但 Encryption 函数 Base64 对其进行了解码,这是一个编码错误。
    • 使用密码时,应使用PBKDF2(又名Rfc2898DeriveBytes)函数从中派生加密密钥。
    • 使用密钥派生时,盐和迭代计数需要可用于解密,通常在加密数据的前缀中提供它们。
  2. 加密模式
    • 未提供加密模式。
    • 使用随机 IV 的 CBC 模式。
    • 只需在加密数据前加上 IV 即可用于解密。
  3. 填充
    • AES 是一种分组密码,因此要求输入数据大小是分组大小的倍数。
    • 指定 PKCS#7(née PKCS#5)填充,它将在加密时添加填充并在解密时将其删除。
    • 解密时不返回“填充”错误,它们可以提供“填充 Oracle”攻击。
  4. 显式
    • 指定所有加密参数和大小。
    • 不要依赖实现默认值。
  5. 加密认证
    • 考虑是否需要知道数据是否正确解密。
  6. 版本控制
    • 添加版本指示器,以便以后需要更改时有一个兼容性路径。

或者考虑使用RNCryptor 来处理所有这些以及更多问题。

更新:(感谢 Andy 的评论)
如果 GCM 模式可用并且跨平台和库的互操作性不是问题,那么 GCM 可以说是更好的加密模式。 GCM 具有身份验证和填充内置功能,使其更加强大和更安全的解决方案。

【讨论】:

  • 我会推荐 AES/GCM 而不是 CBC -- CBC 提供机密性但没有完整性保证,并且 GCM 身份验证标签的开销很小(在 AES-NI 芯片上,它的性能非常好) .
  • 我同意 GCM 模式在几个方面更好——除了跨平台和库的可用性差到缺乏。
  • 真的很好奇——您是否也在考虑硬件实现或缩小范围的平台?我想不出在过去 4 年中运行 Java 但无法处理 GCM 的任何东西。 OP 正在使用 NIO2,因此至少是 Java 7。我原则上同意您对 GCM 可用性的评估,但不认为这是一个限制因素。
  • 我正在解决全球平台和库问题,即使问题是,答案也不限于 Java。互操作性通常是决策中的一个因素。特别是,一个大型平台 iOS 不支持 GCM,除非经过严格审查的 3rd 方实现,而且这些实现不支持硬件加密。
猜你喜欢
  • 2019-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-11
  • 2021-04-04
  • 2020-11-25
  • 2019-10-30
  • 2018-05-29
相关资源
最近更新 更多