InvalidKeySpecException:如何从.der文件提取私钥?

时间:2019-01-13 11:26:23

标签: java rsa private-key der pkcs#8

我有一个.der格式的私钥文件。我正在尝试将此私钥另存为PrivateKey对象(使用Java):

    public T[] ActionContext<T>(sql)
    {
        using (var db = new ActionContext())
        {
            return  db.Database.SqlQuery<T>(sql).ToArray();
        }
    }

这是getPrivateKeyFromKeyFile方法的样子:

PrivateKey clientPrivKey = getPrivateKeyFromKeyFile("C:\\Users\\Bob\\Desktop\\Assignments\\Project\\VPN Project\\src\\client-private.der");

但是当我尝试此操作时,由于此行代码,我不断收到InvalidKeySpecException:

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;
    }

我不确定这里是什么问题。我打开了私钥文件,一切看起来都很好。它以PrivateKey myPrivKey = keyFactory.generatePrivate(keySpec); 开头,以-----BEGIN RSA PRIVATE KEY-----结尾。

在相关的情况下,我使用以下OpenSSL命令创建了此私钥:

-----END RSA PRIVATE KEY-----

1 个答案:

答案 0 :(得分:2)

使用生成的文件

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

实际上不是一个.der文件,而是一个.pem文件(请参阅What are the differences between .pem, .cer and .der?),并且数据不是以PKCS8格式存储,而是以PKCS1格式显示(例如,参见PKCS#1 and PKCS#8 format for RSA private key)。 PKCS1格式的密钥无法使用标准Java工具直接处理。为此,必须使用BouncyCastle之类的第三方库(请参见例如Read RSA private key of format PKCS1 in JAVA)。

另一种可能性是先使用OpenSSL将PKCS1格式的密钥转换为PKCS8格式的密钥(例如,参见Load a RSA private key in Java (algid parse error, not a sequence)):

openssl pkcs8 -topk8 -inform PEM -outform PEM -in <path to the input-pkcs1-pem-file> -out <path to the output-pkcs8-pem-file> -nocrypt

然后,在(编程)删除开始/结束行之后以及在base64解码之后,可以生成私钥(例如,参见How to read .pem file to get private and public key),例如与

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;
}