我有一个关于使用AES加密文件的信息安全项目。本算法的使用密钥也采用RSA算法和公钥进行加密,问题是:加密随机密钥后,它返回数组字节[],如何将此数组字节转换为密钥,以便我可以加密文件? [public_Key]是通过JPasswordField从user生成的这是我在课程设计中面临的挑战]
public void AESEncryption(File file) throws FileNotFoundException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
String data;
SecretKey random_key;
int key_size=128;
Scanner myReader = new Scanner(file);
while (myReader.hasNextLine()) {
data = myReader.nextLine();
}
// create GenerateKey object to access public key
// GenerateKey is my personal class and contain public key
GenerateKey key = new GenerateKey();
// convert public key to string
String public_Key = key.PublicKey.getText();
// convert string public key to secret key
byte[] decodedKey = Base64.getDecoder().decode(public_Key);
SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
// generate random key
KeyGenerator g = KeyGenerator.getInstance("AES");
// give it size
g.init(key_size);
random_key = g.generateKey();
// encrypt the random key with RSA and public key
byte[] random_byteKey = random_key.getEncoded();
Cipher cipher_Key = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher_Key.init(Cipher.ENCRYPT_MODE, originalKey);
byte[] encrypted_key = cipher_Key.doFinal(random_byteKey); //RSA key
// after generating RSA key we will Encrypt file using RSA key
byte[] byte_message = data.getBytes();
Cipher cipherTxt = Cipher.getInstance("AES/GCM/NoPadding");
// the problem in here
cipherTxt.init(Cipher.ENCRYPT_MODE, encrypted_key);
byte[] encByte = cipherTxt.doFinal(byte_message);
}
你不明白你需要做什么。首先生成一个仅用于数据加密的随机AES密钥。然后使用可信的RSA公钥用RSA加密该密钥,该公钥是接收方密钥对的一部分。因此,您永远不必将公钥或RSA密文转换为对称密钥。
作为题外话,您应该使用Cipher#wrap()
,而不是使用Cipher#doFinal()
,它接受一个对称密钥。这样就不必将它们编码为字节数组。如果使用硬件模块,也可能更安全,例如,取决于Cipher
的实现。
我强烈建议您为这些单独的步骤以及文件处理生成单独的方法。
最后,您将需要更类似于这样的内容:
public static void hybridEncrypt(RSAPublicKey publicKey, File in, File out) throws IOException, InvalidKeyException {
int key_size=128;
try {
KeyGenerator g = KeyGenerator.getInstance("AES");
g.init(key_size);
SecretKey dataKey = g.generateKey();
// encrypt the random data key with the RSA public key
Cipher cipher_Key = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher_Key.init(Cipher.WRAP_MODE, publicKey);
byte[] encryptedKey = cipher_Key.wrap(dataKey);
Cipher cipherTxt = Cipher.getInstance("AES/GCM/NoPadding");
cipherTxt.init(Cipher.ENCRYPT_MODE, dataKey);
byte[] message = Files.readAllBytes(in.toPath());
byte[] encryptedMessage = cipherTxt.doFinal(message);
out.createNewFile();
Files.write(out.toPath(), encryptedKey);
Files.write(out.toPath(), encryptedMessage, StandardOpenOption.APPEND);
} catch(NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException e) {
throw new RuntimeException("RSA or AES/GCM not available", e);
} catch (BadPaddingException e) {
throw new RuntimeException("Padding failed for NoPadding", e);
}
}
public static void main(String[] args) throws Exception {
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
kpGen.initialize(3072);
KeyPair keyPairReceiver = kpGen.generateKeyPair();
RSAPublicKey publicKeyReceiver = (RSAPublicKey) keyPairReceiver.getPublic();
hybridEncrypt(publicKeyReceiver, new File("plain.txt"), new File("bla.bin"));
}
注意,这仍然不是最佳实践代码,例如,它使用旧的pkcs# 1加密而不是OAEP。不要复制粘贴这些家伙——使用加密你需要知道你在做什么,最好使用一个经过严格审查的高级库。