[英]How to AES256 encrypt/decrypt a PKCS#12 archive file in Java?
My application needs to encrypt a PKCS#12 archive file which is already encrypted with the passphrase notasecret
. 我的应用程序需要加密一个已经使用密码
notasecret
加密的PKCS#12存档文件 。 The file should be AES256 encrypted. 该文件应该是AES256加密的。
I tried using this solution for the encryption itself. 我尝试将这种解决方案用于加密本身。 My idea is to encrypt the string of characters read from file and writing that to a new file and then later decrypt it when I need it.
我的想法是对从文件读取的字符串进行加密,然后将其写入新文件,然后在需要时对其进行解密。
Right now I'm testing whether the string is encrypted and decrypted back correctly (whether the new file that is created is identical to the original). 现在,我正在测试字符串是否正确加密和解密(创建的新文件是否与原始文件相同)。 This is not the case.
不是这种情况。
My code below is supposed to create an identical file by encrypting and decrypting a .p12 file, but the resulting file is bigger (original: 1.7KB, new: 2.5KB) and it's unreadable as a PKCS#12 archive. 我下面的代码应该通过加密和解密.p12文件来创建一个相同的文件,但是生成的文件更大(原始文件:1.7KB,新文件:2.5KB),不能作为PKCS#12存档读取。 The string length test in the middle displays identical lengths.
中间的字符串长度测试显示相同的长度。
Any clues? 有什么线索吗? Does it matter if the file is in one format or the other (PKCS#12 archive, binary, plaintext)?
文件是一种格式还是另一种格式(PKCS#12存档,二进制,明文)是否重要? The below code works great if the file to encrypt is in plaintext.
如果要加密的文件为纯文本格式,则以下代码非常有用。
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.security.AlgorithmParameters;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class FileEncryptionTest {
public static void main(String[] args) throws Exception {
char[] password = "password".toCharArray();
byte[] salt = new byte[8];
/* Derive the key, given password and salt. */
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
/* Encrypt the message. */
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
String file = "someprivatekey.p12";
String keyFileText = readFile(file);
byte[] ciphertext = cipher.doFinal(keyFileText.getBytes("UTF-8"));
Cipher otherCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
otherCipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
String plaintext = new String(otherCipher.doFinal(ciphertext), "UTF-8");
if (plaintext.equals(keyFileText))
System.out.println("decrypted plaintext same as plaintext");
System.out.println("plaintext length: " + plaintext.length() + " keyFileText length: " + keyFileText.length());
writeFile(plaintext, "new-" + file);
}
private static void writeFile(String contents, String filePath) {
PrintWriter out = null;
try {
out = new PrintWriter(new FileOutputStream(filePath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
out.write(contents);
out.close();
}
private static String readFile(String filePath) {
FileInputStream fis = null;
int buf;
StringBuilder contents = null;
try {
fis = new FileInputStream(filePath);
contents = new StringBuilder();
while ((buf = fis.read()) != -1) {
contents.append((char) buf);
}
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
return contents.toString();
}
}
You are treating a binary file as a String. 您正在将二进制文件视为字符串。 A binary file will contain many characters that cannot be treated as a character.
二进制文件将包含许多不能视为字符的字符。 Please rewrite your code and assume the PKCS#12 file is binary (using eg a
FileInputStream
/ FileOutputStream
combination or - for not such a big file - use readAllBytes
instead of the input stream. 请重写您的代码,并假定PKCS#12文件是二进制文件(例如,使用
FileInputStream
/ FileOutputStream
组合,或者-对于不那么大的文件,请使用readAllBytes
而不是输入流。
Thanks to @owlstead 's tip about using the data wrong, I managed to encrypt and decrypt the file correctly by treating the data as a byte[]
, not a String
. 感谢@owlstead提出的有关错误使用数据的提示,通过将数据视为
byte[]
而不是String
,我设法正确地加密和解密了文件。 These are the relevant changes: 这些是相关的更改:
private static void writeFile(byte[] contents, String filePath) {
FileOutputStream out = null;
try {
out = new FileOutputStream(filePath);
out.write(contents);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static byte[] readFile(String filePath) {
FileInputStream fis = null;
File f = new File(filePath);
int buf, i = 0;
byte[] array = null;
try {
fis = new FileInputStream(f);
array = new byte[(int) f.length()];
while ((buf = fis.read()) != -1) {
array[i++] = (byte) buf;
}
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
return array;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.