(AES加密) 代码漏洞,需要注意什么? [提供的代码][Java]
(AES Encryption) Code flaws, what should I be carefull with? [Code Provided][Java]
感谢您抽出宝贵时间协助我!
此 POST 已编辑,信息较少请参阅编辑部分
好吧,我花了很多时间研究这个问题,最后我得到了一段有效的代码..
但是加密不是出错的地方,我想问一下我的代码是否真的安全!这对我来说真的很重要,因为我想将它实现到一个程序中,所以我的代码是...
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);
}
}
编辑
Possible duplicate of Simple Java AES encrypt/decrypt example – JFPicard
可能是,但这些答案使用 IVParameterSpec,我想知道是否
这行代码实际上是安全的,或者如果它是不好的做法:
AesCipher.init(Cipher.DECRYPT_MODE, secretKey, new SecureRandom());
因为我每次都用new SecureRandom()
,
而且我还没有看到有人像这样使用 SecureRandom 对象。
- 加密密钥
- 密码作为字符串传递,但
Encryption
函数对其进行了 Base64 解码,这是一个编码错误。
- 使用密码时,应使用
PBKDF2
(又名 Rfc2898DeriveBytes
)函数从密码中导出加密密钥。
- 使用密钥派生时,盐和迭代计数需要可用于解密,通常它们在加密数据的前缀中提供。
- 加密模式
- 未提供加密模式。
- 使用带有随机 IV 的 CBC 模式。
- 只需在加密数据前加上用于解密的 IV。
- 填充
- AES 是一种块密码,因此要求输入数据大小是块大小的倍数。
- 指定 PKCS#7(née PKCS#5)填充,它将在加密时添加填充并在解密时删除它。
- 解密时不会return"padding"错误,他们可以提供"Padding Oracle"攻击。
- 显式
- 指定所有加密参数和大小。
- 不要依赖实现默认值。
- 加密认证
- 考虑是否需要知道数据是否被正确解密。
- 版本控制
- 添加一个版本指示符,以便以后需要更改时有一个兼容性路径。
或者考虑使用 RNCryptor 来处理所有这些以及更多。
更新:(感谢 Andy 的评论)
如果 GCM 模式可用并且跨平台和库的互操作性不是问题,则 GCM 可以说是更好的加密模式。 GCM 具有身份验证和填充功能 build-in 使其更健壮且更安全。
感谢您抽出宝贵时间协助我!
此 POST 已编辑,信息较少请参阅编辑部分
好吧,我花了很多时间研究这个问题,最后我得到了一段有效的代码..
但是加密不是出错的地方,我想问一下我的代码是否真的安全!这对我来说真的很重要,因为我想将它实现到一个程序中,所以我的代码是...
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);
}
}
编辑
Possible duplicate of Simple Java AES encrypt/decrypt example – JFPicard
可能是,但这些答案使用 IVParameterSpec,我想知道是否 这行代码实际上是安全的,或者如果它是不好的做法:
AesCipher.init(Cipher.DECRYPT_MODE, secretKey, new SecureRandom());
因为我每次都用new SecureRandom()
,
而且我还没有看到有人像这样使用 SecureRandom 对象。
- 加密密钥
- 密码作为字符串传递,但
Encryption
函数对其进行了 Base64 解码,这是一个编码错误。 - 使用密码时,应使用
PBKDF2
(又名Rfc2898DeriveBytes
)函数从密码中导出加密密钥。 - 使用密钥派生时,盐和迭代计数需要可用于解密,通常它们在加密数据的前缀中提供。
- 密码作为字符串传递,但
- 加密模式
- 未提供加密模式。
- 使用带有随机 IV 的 CBC 模式。
- 只需在加密数据前加上用于解密的 IV。
- 填充
- AES 是一种块密码,因此要求输入数据大小是块大小的倍数。
- 指定 PKCS#7(née PKCS#5)填充,它将在加密时添加填充并在解密时删除它。
- 解密时不会return"padding"错误,他们可以提供"Padding Oracle"攻击。
- 显式
- 指定所有加密参数和大小。
- 不要依赖实现默认值。
- 加密认证
- 考虑是否需要知道数据是否被正确解密。
- 版本控制
- 添加一个版本指示符,以便以后需要更改时有一个兼容性路径。
或者考虑使用 RNCryptor 来处理所有这些以及更多。
更新:(感谢 Andy 的评论)
如果 GCM 模式可用并且跨平台和库的互操作性不是问题,则 GCM 可以说是更好的加密模式。 GCM 具有身份验证和填充功能 build-in 使其更健壮且更安全。