簡體   English   中英

如何在Java中AES256加密/解密PKCS#12存檔文件?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM