InvalidKeySpecException: как извлечь закрытый ключ из файла .der? - PullRequest
0 голосов
/ 13 января 2019

У меня есть файл закрытого ключа в формате .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 Ответ

0 голосов
/ 13 января 2019

Файл, созданный с помощью

openssl genrsa -out <path to output-file> 2048

на самом деле не .der -файл, а .pem -файл (см., Например, В чем различия между .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 и после 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;
}
...