Чтение закрытого зашифрованного ключа в 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");
}
Другие вопросы по тегам