本文转载和翻译自:techxperiment.blogspot.com/2016/10/cre…html
在这篇简短的文章中,我将向您展现如何在 java 中以 pkcs8 格式存储私钥,并再次在 java 中读回存储的密钥。java
PKCS#8 定义了用于存储私钥信息的标准语法。咱们能够经过 2 种方式存储 pkcs8 格式的私钥。算法
1)未加密密钥 2)加密密钥dom
我将在 java 中建立两种类型的密钥并将它们存储在文件中。以后我将从文件中读取它们并从存储文件中建立 privatekey java 对象。咱们正在使用充气城堡 API 进行此计划ui
import org.bouncycastle.openssl.PKCS8Generator;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.openssl.jcajce.JcaPKCS8Generator;
import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.OutputEncryptor;
import org.bouncycastle.util.io.pem.PemObject;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
public class App3 {
public static void main(String[] args) throws NoSuchAlgorithmException, IOException, OperatorCreationException, InvalidKeySpecException {
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
kpGen.initialize(2048, new SecureRandom());
KeyPair keyPair = kpGen.generateKeyPair();
//unencrypted form of PKCS#8 file
JcaPKCS8Generator gen1 = new JcaPKCS8Generator(keyPair.getPrivate(), null);
PemObject obj1 = gen1.generate();
StringWriter sw1 = new StringWriter();
try (JcaPEMWriter pw = new JcaPEMWriter(sw1)) {
pw.writeObject(obj1);
}
String pkcs8Key1 = sw1.toString();
FileOutputStream fos1 = new FileOutputStream("D:\\privatekey-unencrypted.pkcs8");
fos1.write(pkcs8Key1.getBytes());
fos1.flush();
fos1.close();
//encrypted form of PKCS#8 file
JceOpenSSLPKCS8EncryptorBuilder encryptorBuilder = new JceOpenSSLPKCS8EncryptorBuilder(PKCS8Generator.PBE_SHA1_RC2_128);
encryptorBuilder.setRandom(new SecureRandom());
encryptorBuilder.setPasssword("abcde".toCharArray()); // password
OutputEncryptor encryptor = encryptorBuilder.build();
JcaPKCS8Generator gen2 = new JcaPKCS8Generator(keyPair.getPrivate(), encryptor);
PemObject obj2 = gen2.generate();
StringWriter sw2 = new StringWriter();
try (JcaPEMWriter pw = new JcaPEMWriter(sw2)) {
pw.writeObject(obj2);
}
String pkcs8Key2 = sw2.toString();
FileOutputStream fos2 = new FileOutputStream("D:\\privatekey-encrypted.pkcs8");
fos2.write(pkcs8Key2.getBytes());
fos2.flush();
fos2.close();
}
}
复制代码
所以,您能够看到,对于未加密的密钥,咱们不提供任何包含有关算法,密码等信息的加密器对象。在建立加密密钥时,咱们会提供详细信息。加密
做为此计划的结果,咱们的文件系统中将包含如下 2 个文件 spa
让咱们在记事本中打开它们并检查差别。加密密钥文件:翻译
import org.bouncycastle.util.encoders.Base64;
import javax.crypto.EncryptedPrivateKeyInfo;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
public class App4 {
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
String encrypted = new String(Files.readAllBytes(Paths.get("D:\\privatekey-encrypted.pkcs8")));
String unencrypted = new String(Files.readAllBytes(Paths.get("D:\\privatekey-unencrypted.pkcs8")));
//Create object from unencrypted private key
unencrypted = unencrypted.replace("-----BEGIN PRIVATE KEY-----", "");
unencrypted = unencrypted.replace("-----END PRIVATE KEY-----", "");
byte[] encoded = Base64.decode(unencrypted);
PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(encoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey unencryptedPrivateKey = kf.generatePrivate(kspec);
//Create object from encrypted private key
encrypted = encrypted.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "");
encrypted = encrypted.replace("-----END ENCRYPTED PRIVATE KEY-----", "");
EncryptedPrivateKeyInfo pkInfo = new EncryptedPrivateKeyInfo(Base64.decode(encrypted));
PBEKeySpec keySpec = new PBEKeySpec("abcde".toCharArray()); // password
SecretKeyFactory pbeKeyFactory = SecretKeyFactory.getInstance(pkInfo.getAlgName());
PKCS8EncodedKeySpec encodedKeySpec = pkInfo.getKeySpec(pbeKeyFactory.generateSecret(keySpec));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey encryptedPrivateKey = keyFactory.generatePrivate(encodedKeySpec);
//comparing both private key for equality
System.out.println(unencryptedPrivateKey.equals(encryptedPrivateKey));
}
}
复制代码
输出:code