Чтение закрытого зашифрованного ключа в Java
У меня есть следующий кусок кода:
PEMParser pemParser;
File telexuskeys = new File(locationKey);
if(telexuskeys.exists())
pemParser = new PEMParser(new FileReader(telexuskeys));
else{
usage(ops);
throw new FileNotFoundException("The key file (company's certificate) doesn't exist!");
}
System.out.println("Loading company's certificate");
Object object = pemParser.readObject();
Object object2 = pemParser.readObject();
PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(passwordPem.toCharArray());
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
byte[] keyBytes = PrivateKeyInfo.getInstance(object2).getEncoded();
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
PrivateKey pk = kf.generatePrivate(spec);
У моего файла pem просто есть сертификат и закрытый ключ. Раньше я мог читать файл и получать закрытый ключ, но теперь файл защищен (зашифрован) паролем. Какую инструкцию я до сих пор скучаю. Я знаю, что мне нужно использовать объекты PEMDecryptorProvider и JcaPEMKeyConverter, чтобы получить его, но я не нашел правильную комбинацию.
2 ответа
Следующий код делает работу за меня. (Использование библиотек bcpkix и bcprov из Bouncy Castle).
private PrivateKey readPrivateKey(String privateKeyPath, String keyPassword) throws IOException {
FileReader fileReader = new FileReader(privateKeyPath);
PEMParser keyReader = new PEMParser(fileReader);
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
PEMDecryptorProvider decryptionProv = new JcePEMDecryptorProviderBuilder().build(keyPassword.toCharArray());
Object keyPair = keyReader.readObject();
PrivateKeyInfo keyInfo;
if (keyPair instanceof PEMEncryptedKeyPair) {
PEMKeyPair decryptedKeyPair = ((PEMEncryptedKeyPair) keyPair).decryptKeyPair(decryptionProv);
keyInfo = decryptedKeyPair.getPrivateKeyInfo();
} else {
keyInfo = ((PEMKeyPair) keyPair).getPrivateKeyInfo();
}
keyReader.close();
return converter.getPrivateKey(keyInfo);
Мой ключ был сгенерирован с помощью команды ниже.
openssl req -new -newkey rsa:2048 -keyout key.pem -pubkey -out pubreq.p10 -subj "/CN=MyKey"
Судя по всему, выход былPKCS8EncryptedPrivateKeyInfo
и после прочтения материала тут и там, вот что я придумал:
try {
File file = ResourceUtils.getFile("classpath:" + decryptionKeystore);
try (FileReader fileReader = new FileReader(file);
PEMParser keyReader = new PEMParser(fileReader)) {
Object keyPair = keyReader.readObject();
PrivateKeyInfo keyInfo;
if (keyPair instanceof PEMEncryptedKeyPair) {
PEMDecryptorProvider decryptionProv = new JcePEMDecryptorProviderBuilder().build(passphrase);
PEMKeyPair decryptedKeyPair = ((PEMEncryptedKeyPair) keyPair).decryptKeyPair(decryptionProv);
keyInfo = decryptedKeyPair.getPrivateKeyInfo();
} else if (keyPair instanceof PKCS8EncryptedPrivateKeyInfo) {
InputDecryptorProvider decryptorProvider = new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase);
keyInfo = ((PKCS8EncryptedPrivateKeyInfo) keyPair).decryptPrivateKeyInfo(decryptorProvider);
} else {
keyInfo = ((PEMKeyPair) keyPair).getPrivateKeyInfo();
}
return new JcaPEMKeyConverter().getPrivateKey(keyInfo);
} catch (Exception e) {
LOGGER.error("Exception while getting private key", e);
}
} catch (FileNotFoundException e) {
LOGGER.debug("Decryption keystore file not found");
}