Чтобы проверить ваш сценарий, я создал закрытый ключ RSA с openssl
.
openssl genrsa -out private.pem 1024
Затем я преобразовал этот ключ в формат PKCS # 8 DER.
openssl pkcs8 -topk8 -inform PEM -in private.pem -outform DER -out private.der -nocrypt
Руководство по openssl
относится к PKCS # 8 и DER как к форматам , поэтому, насколько я понимаю, происходит следующее:
pkcs8
openssl
сообщает, что я хочу работать с закрытыми ключами в формате PKCS # 8. -topk8
сообщает, что секретный ключ, который я собираюсь указать с помощью -in
, равен , а не в PKCS # 8 (иначе это будет предполагаться). -inform
и -in
указывают, что я хочу преобразовать закрытый ключ (PEM) в PKCS # 8 (без -topk8
itпопробую преобразовать ключ уже в формате PKCS # 8 в стандартный формат ключа). -outform
и -out
сообщают, что я хочу отформатированный ключ DER в качестве вывода. -nocrypt
говорит, что я не хочу шифровать ключ.
Затем, с моим ключом RSA (в стандартном формате), я создал сертификат.
openssl req -new -x509 -keyform PEM -key private.pem -outform DER -out public.der
Сертификатns открытый ключ, соответствующий моему личному ключу.
После всего этого я закодировал и личный ключ, и сертификат с Base64.
base64 private.der > private.der.b64
base64 public.der > public.der.b64
Были сгенерированы следующие файлы.
private.pem # standard
private.der # pkcs8/DER
private.der.b64
public.der # x509/DER
public.der.b64
public static void main(String[] args) throws IOException, GeneralSecurityException {
// get a handle on the base64 encoded key and certificate
File privateKeyFile = new File("private.der.b64");
File publicKeyFile = new File("public.der.b64");
// pull them into arrays
byte[] privateKeyBytes = toByteArray(privateKeyFile);
byte[] publicKeyBytes = toByteArray(publicKeyFile);
// decode them
privateKeyBytes = toDecodedBase64ByteArray(privateKeyBytes);
publicKeyBytes = toDecodedBase64ByteArray(publicKeyBytes);
// get the private key
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
KeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
// get the public key
CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
Certificate certificate = certificateFactory.generateCertificate(new ByteArrayInputStream(publicKeyBytes));
PublicKey publicKey = certificate.getPublicKey();
}
private static byte[] toByteArray(File file) throws IOException {
// java 7's try-with-resources statement
try (FileInputStream in = new FileInputStream(file);
FileChannel channel = in.getChannel()) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
channel.transferTo(0, channel.size(), Channels.newChannel(out));
return out.toByteArray();
}
}
private static byte[] toDecodedBase64ByteArray(byte[] base64EncodedByteArray) {
return DatatypeConverter.parseBase64Binary(
new String(base64EncodedByteArray, Charset.forName("UTF-8")));
}
Основная проблема заключалась в том, что у вас был сертификат вместо открытого ключа.Сертификат содержит открытый ключ, но его нельзя загрузить с помощью X509EncodedKeySpec(...)
, поэтому вместо него следует использовать CertificateFactory
.
(Кстати, здесь - отличныйстатья / учебное пособие по openssl
и использованию криптографии Java. Оттуда я получил частично информацию.)