[英]How to AES256 encrypt/decrypt a PKCS#12 archive file in Java?
我的應用程序需要加密一個已經使用密碼notasecret
加密的PKCS#12存檔文件 。 該文件應該是AES256加密的。
我嘗試將這種解決方案用於加密本身。 我的想法是對從文件讀取的字符串進行加密,然后將其寫入新文件,然后在需要時對其進行解密。
現在,我正在測試字符串是否正確加密和解密(創建的新文件是否與原始文件相同)。 不是這種情況。
我下面的代碼應該通過加密和解密.p12文件來創建一個相同的文件,但是生成的文件更大(原始文件:1.7KB,新文件:2.5KB),不能作為PKCS#12存檔讀取。 中間的字符串長度測試顯示相同的長度。
有什么線索嗎? 文件是一種格式還是另一種格式(PKCS#12存檔,二進制,明文)是否重要? 如果要加密的文件為純文本格式,則以下代碼非常有用。
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();
}
}
您正在將二進制文件視為字符串。 二進制文件將包含許多不能視為字符的字符。 請重寫您的代碼,並假定PKCS#12文件是二進制文件(例如,使用FileInputStream
/ FileOutputStream
組合,或者-對於不那么大的文件,請使用readAllBytes
而不是輸入流。
感謝@owlstead提出的有關錯誤使用數據的提示,通過將數據視為byte[]
而不是String
,我設法正確地加密和解密了文件。 這些是相關的更改:
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.