Как сгенерировать секретный ключ RSA из строки * pem в Java

Я хочу сгенерировать закрытый ключ из строки (a .pem file) в Java.

private static final String test = "-----BEGIN RSA PRIVATE KEY-----\n" +
 "******************************************************//PN0BtRW2\n" +
// and so on
 "-----END RSA PRIVATE KEY-----";
try {
 String privKeyPEM = test.replace("-----BEGIN RSA PRIVATE KEY-----\n", "");
 privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");
 byte [] encoded = Base64.decode(privKeyPEM);
 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
 KeyFactory kf = KeyFactory.getInstance("RSA");
 PrivateKey privKey = kf.generatePrivate(keySpec);
}
catch (Exception e) {
 e.printStackTrace();
}

Последняя строка (функция generatePrivate) выбрасывает это исключение:

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
 at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(Unknown Source)
 at java.security.KeyFactory.generatePrivate(Unknown Source)
 at Test.main(Test.java:52)
Caused by: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
 at sun.security.pkcs.PKCS8Key.decode(Unknown Source)
 at sun.security.pkcs.PKCS8Key.decode(Unknown Source)
 at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(Unknown Source)
 at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(Unknown Source)
 at sun.security.rsa.RSAKeyFactory.generatePrivate(Unknown Source)
 ... 3 more
</init>

Если я изменил закрытый ключ на значение из файла .der, он работает правильно, но мне нужно сгенерировать файл закрытого ключа из файла .pem.

Я приложил скриншот байтов, напечатанных как строка (один раз жестко закодированный с \n и один раз жестко закодированный без \n) и один раз из файла.

Изображение большего размера

Странно, что вывод из файла отличается от вывода из строк.

Если я попытаюсь закодировать файл .der с Base64, результат будет отличаться от строки в файле .pem. Почему это так?

1 ответ

Вы говорите, что последняя строка выбрасывает исключение, т.е.

PrivateKey privKey = kf.generatePrivate(keySpec);

Над строкой работает настройка ключей, т.е.

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);

Итак, актуальная проблема связана с массивом закодированных байтов. Вы сделали System.out после byte [] encoded = Base64.decode(privKeyPEM); и посмотрели, что такое выход.

Я понимаю, что если сообщение находится в формате MIME, то после определенных символов оно добавляет комбинацию возврата каретки и новой строки, поэтому строки не слишком длинны для системы электронной почты или где бы вы ее не использовали.

В финальном тесте String есть некоторый "\n" в исходном тексте, который вы используете. Вы избавились от другого текста в строке ниже,

String privKeyPEM = test.replace("-----BEGIN RSA PRIVATE KEY-----\n", "");
 privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");

Но посмотрите на строку,

"******************************************************//PN0BtRW2\n" +
// and so on
 "-----END RSA PRIVATE KEY-----";

у него может быть несколько "\n" слева, что может привести к появлению некоторых нежелательных символов при создании ключей. Попробуйте еще раз System.out и посмотрите, как выглядит кодированный байтовый массив, а также перед этим проверьте String privKeyPEM и посмотрите, не останется ли в нем лишний символ.

Надеюсь, что это будет.

licensed under cc by-sa 3.0 with attribution.