#java #encryption #elliptic-curve
#Ява #шифрование #эллиптическая кривая
Вопрос:
Небольшой вопрос о том, как использовать закрытый ключ эллиптической кривой с java 11, пожалуйста.
У меня есть эти команды:
openssl pkcs12 -in file.p12 -out output.txt Enter Import Password: MAC verified OK Enter PEM pass phrase: Verifying - Enter PEM pass phrase:
затем я могу запустить cat на выходе:
cat output.txt Bag Attributes friendlyName: localKeyID: Key Attributes: lt;No Attributesgt; -----BEGIN ENCRYPTED PRIVATE KEY----- MI[...]0= -----END ENCRYPTED PRIVATE KEY----- Bag Attributes friendlyName: localKeyID: subject=/CN= issuer=/CN= -----BEGIN CERTIFICATE----- MII[...]Z -----END CERTIFICATE-----
Обратите внимание, я использую […] для редактирования фактического содержимого.
И я просто хочу использовать этот закрытый ключ, тот, что в -----BEGIN ENCRYPTED PRIVATE KEY----- -----END ENCRYPTED PRIVATE KEY-----
блоке
Поэтому я попробовал следующее: сначала я удалил ЗАШИФРОВАННЫЙ ЗАКРЫТЫЙ ключ BEGIN, разрывы строк, ЗАШИФРОВАННЫЙ ЗАКРЫТЫЙ КЛЮЧ END
String privateKeyPEM = "MI[...]0="; //the same private key as above byte[] keyData = Base64.getDecoder().decode(privateKeyPEM); EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(keyData); KeyFactory kf = KeyFactory.getInstance("EC"); PrivateKey privKey = kf.generatePrivate(privKeySpec);
Однако я получаю эту ошибку:
aused by: java.security.InvalidKeyException: IOException : DER input, Integer tag error at java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:350) at java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:355) at jdk.crypto.ec/sun.security.ec.ECPrivateKeyImpl.lt;initgt;(ECPrivateKeyImpl.java:74) at jdk.crypto.ec/sun.security.ec.ECKeyFactory.implGeneratePrivate(ECKeyFactory.java:237) at jdk.crypto.ec/sun.security.ec.ECKeyFactory.engineGeneratePrivate(ECKeyFactory.java:165)
Могу я спросить, в чем, пожалуйста, проблема? Кроме того, могу я спросить, как это исправить?
Спасибо
Ответ №1:
Проблем нет, но ключ (EC), который вы пытаетесь прочитать, зашифрован — чистая Java не может считывать ключи такого рода.
Вы можете написать много кода для анализа и расшифровки ключа или использовать Надувной замок, чтобы выполнить эту работу за вас.
Добавьте эту строку в начало вашей программы:
Security.addProvider(new BouncyCastleProvider());
затем используйте эту функцию, где строка s принимает зашифрованный ключ, включая строки «— Begin — / end:
static public PrivateKey stringToPrivateKey(String s, String password) throws IOException, PKCSException { PrivateKeyInfo pki; try (PEMParser pemParser = new PEMParser(new StringReader(s))) { Object o = pemParser.readObject(); if (o instanceof PKCS8EncryptedPrivateKeyInfo) { // encrypted private key in pkcs8-format System.out.println("key in pkcs8 encoding"); PKCS8EncryptedPrivateKeyInfo epki = (PKCS8EncryptedPrivateKeyInfo) o; System.out.println("epki:" epki.getEncryptionAlgorithm().getAlgorithm()); JcePKCSPBEInputDecryptorProviderBuilder builder = new JcePKCSPBEInputDecryptorProviderBuilder().setProvider("BC"); InputDecryptorProvider idp = builder.build(password.toCharArray()); pki = epki.decryptPrivateKeyInfo(idp); } else if (o instanceof PEMEncryptedKeyPair) { // encrypted private key in pkcs8-format System.out.println("key in pkcs1 encoding"); PEMEncryptedKeyPair epki = (PEMEncryptedKeyPair) o; PEMKeyPair pkp = epki.decryptKeyPair(new BcPEMDecryptorProvider(password.toCharArray())); pki = pkp.getPrivateKeyInfo(); } else if (o instanceof PEMKeyPair) { // unencrypted private key System.out.println("key unencrypted"); PEMKeyPair pkp = (PEMKeyPair) o; pki = pkp.getPrivateKeyInfo(); } else { throw new PKCSException("Invalid encrypted private key class: " o.getClass().getName()); } JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); return converter.getPrivateKey(pki); } }
Комментарии:
1. Действительно, большое спасибо @Michael!