InvalidKeySpecException: как извлечь частный ключ из файла.der?
У меня есть файл закрытого ключа в формате.der. Я пытаюсь сохранить этот закрытый ключ как объект PrivateKey (с Java) следующим образом:
PrivateKey clientPrivKey = getPrivateKeyFromKeyFile("C:\\Users\\Bob\\Desktop\\Assignments\\Project\\VPN Project\\src\\client-private.der");
Вот как выглядит метод getPrivateKeyFromKeyFile:
private static PrivateKey getPrivateKeyFromKeyFile(String keyfile) throws Exception
{
Path path = Paths.get(keyfile);
byte[] privKeyByteArray = Files.readAllBytes(path);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privKeyByteArray);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey myPrivKey = keyFactory.generatePrivate(keySpec);
return myPrivKey;
}
Но когда я пытаюсь это сделать, я получаю InvalidKeySpecException из-за этой строки кода:
PrivateKey myPrivKey = keyFactory.generatePrivate(keySpec);
Я не уверен, в чем здесь проблема. Я открыл файл закрытого ключа, и все выглядит хорошо. Начинается с -----BEGIN RSA PRIVATE KEY-----
и заканчивается -----END RSA PRIVATE KEY-----
,
И в случае, если это уместно, я создал этот закрытый ключ с помощью этой команды OpenSSL:
genrsa -out client-private.der 2048
1 ответ
Файл, созданный с
openssl genrsa -out <path to output-file> 2048
на самом деле не .der
-файл, но .pem
-file (см., например, Каковы различия между.pem,.cer и.der?) и данные не хранятся в PKCS8
-формат, но в PKCS1
-формат (см., например, формат PKCS#1 и PKCS#8 для закрытого ключа RSA). Ключи в PKCS1
-формат не может быть обработан напрямую с использованием стандартных инструментов Java. Для этого необходимы сторонние библиотеки, такие как BouncyCastle (см., Например, Чтение закрытого ключа RSA формата PKCS1 в JAVA).
Другая возможность заключается в преобразовании PKCS1
форматированный ключ в PKCS8
-форматированный ключ сначала с OpenSSL (см., например, Загрузка закрытого ключа RSA в Java (ошибка синтаксического анализа, а не последовательность)):
openssl pkcs8 -topk8 -inform PEM -outform PEM -in <path to the input-pkcs1-pem-file> -out <path to the output-pkcs8-pem-file> -nocrypt
И затем, после (программного) удаления Beginn-/End-line и после base64-декодирования, может быть сгенерирован закрытый ключ (см., Например, Как читать файл.pem, чтобы получить закрытый и открытый ключ), например, с помощью
private static PrivateKey getPrivateKeyFromKeyFile(String keyfile) throws Exception
{
Path path = Paths.get(keyfile);
byte[] privKeyByteArray = Files.readAllBytes(path);
// added ----------------------------------------------------------------
String privKeyString = new String(privKeyByteArray);
privKeyString = privKeyString.replace("-----BEGIN PRIVATE KEY-----", "");
privKeyString = privKeyString.replace("-----END PRIVATE KEY-----", "");
privKeyString = privKeyString.replace("\r\n", "");
privKeyByteArray = Base64.getDecoder().decode(privKeyString);
// ----------------------------------------------------------------------
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privKeyByteArray);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey myPrivKey = keyFactory.generatePrivate(keySpec);
return myPrivKey;
}