Итак, вы «написали» (я полагаю, скопировал) код, который четко говорит, что вам нужны два файла в форме DER, содержащие PKCS8и кодировки «X509».(То, что Java называет X.509, на самом деле представляет собой компонент SubjectPublicKeyInfo из X.509.) Вы предоставляете ему один файл в форме PEM, а не DER, содержащий кодировку PKCS1, а не PKCS8 или .X509 - а ты удивлен, что это не работает?Python работает, потому что он вызывает OpenSSL, а OpenSSL поддерживает более десятка кодировок и форматов для приватных ключей, включая этот;Java поддерживает только один (вне хранилищ ключей), который не является этим.(Голые) публичные клавиши немного лучше;внутренне libcrypto поддерживает несколько форм, но на практике используются только две из них, и одна из них соответствует Java - хотя многие публичные ключи распространяются, хранятся и используются в форме сертификатов X.509, что предоставляет еще несколько форм для беспокойствао.
самое простое - использовать командную строку OpenSSL для преобразования вашего одного файла в два файла, которые хочет Java:
# (corrected! pkey is inconsistent!)
openssl pkcs8 -topk8 -nocrypt -in input.pem -outform der -out private.der
openssl pkey -in input.pem -pubout -outform der -out public.der
# or for very old versions (should not be needed now)
openssl rsa -in input.pem -pubout -outform der -out public.der
Эти файлы теперь могут быть прочитаны с помощью кода, который вы разместили (за исключением разделенных имен файлов).Обратите внимание, что это преобразование не должно быть сделано в той же системе;при необходимости вы можете сделать это в другом месте и скопировать файлы, если вы используете метод, который работает с двоичными файлами, т.е. НЕ вырезать и вставлять.
, если вы действительно хотите только один файл, но это может бытьконвертируйте, создайте файл private.der
, как указано выше, и прочитайте его, используя только части кода, связанные с закрытыми ключами, затем выполните:
RSAPrivateCrtKey priv2 = (RSAPrivateCrtKey)privKey;
PublicKey pubkey = keyFactory.generatePublic(new RSAPublicKeySpec(priv2.getModulus(), priv2.getPublicExponent()));
вы можете конвертировать файлы в PKCS8 и'X509' PEM , опуская -outform der
в приведенных выше преобразованиях, затем считывая эти файлы и вручную де-PEM, удаляя заголовок и строки трейлера и преобразовывая base64 в двоичный файл (удаляя или пропуская разрывы строк);это приводит к бинарным кодировкам PKCS8 и X509, которые вы можете запустить через существующий код.Это так же много работы на стороне openssl и больше работы на стороне Java, поэтому нет очевидного преимущества, за исключением того, что файлы PEM являются допустимым текстом и могут быть вырезаны и вставлены при необходимости.
комбинируя их, вы можете конвертировать только в PEM PKCS8, читать это по пуле 3 (de-PEM, затем части вашего закрытого ключа), а затем извлекать publickey из privatekey по пуле 2
один из способов использовать формат, который у вас есть (не преобразованный) в простой Java, - это де-PEM для пули 3, давая вам кодировку PKCS1, затем вручную создать кодировку PKCS8, а затем продолжить работу, как раньшечтобы запустить PKCS8 через KeyFactory
и извлечь publickey по пуле 2. См. мой ответ на Java: преобразовать закрытый ключ DKIM из RSA в DER для JavaMail , чтобы получить действительно уродливый способ сделать это (включая один де-PEM метод).Есть лучший способ, если вы используете BouncyCastle (у которого есть класс для этого типа ASN.1), но если вы используете BouncyCastle, лучше вообще не использовать этот метод, см. Ниже.
Еще один способ использовать не преобразованный формат в простой Java - это де-PEM для каждого пункта 3, затем проанализировать структуру ASN.1 PKCS1 и создать RSAPrivateCrtKeySpec
, который вы можете запустить через KeyFactory
вместо кодировки PKCS8 затем извлекают publickey для пули 2. Это еще более сложно, хотя я думаю, что где-то видел это;добавлю если найду.И снова BouncyCastle может улучшить этот метод, но не нуждается в этом, см. Ниже.
наконец, если у вас есть BouncyCastle, это очень просто.Вы не говорите, что пытались «без удачи», но следующий код BouncyCastle - это все, что вам нужно и работает:
try( Reader r = new FileReader(filename) ){
KeyPair pair = new JcaPEMKeyConverter().getKeyPair((PEMKeyPair)new PEMParser(r).readObject());
}
Обратите внимание, что это дает вам KeyPair
с объектами privatekey и publickeyиз одного файла.