如何解密加密的 rsa 2048 编码字符串?

问题描述 投票:0回答:1

我需要将未加密的 RSA 私钥替换为加密的私钥。 我用过

openssl -newKey rsa:2048 -new sha256 ... 

生成pem。我看到生成的 pem 以“----BEGIN ENCRYPTED PRIVATE KEY-----”开头。 (过去只是说 -----BEGIN PRIVATE KEY-----")

当我尝试在现有 Java 代码中使用该 pem 文件时,它会抛出 InvalidKeySpecException

 PrivateKey getPrivateKey(String path) throws Exception{
    String algorithm = "RSA";
    try{
        String rsaPrivateKey = String.join("", Files.readAllLines(Paths.get(path)));
        Files.readAllLines(Paths.get(path)));
// tried with and without the following replaceAll() 
        rsaPrivateKey = rsaPrivateKey.replaceAll("-----.*?.....");
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder(rsaPrivateKey)).decode(rsaPrivateKey);
        KeyFactory kf = KeyFactor.getInstance(algorithm);
// next line throws the exception 
        PrivateKey privKey = kf.generatePrivate(keySpec);
        return privKey;
    }catch(InvalidKeySpecException e){
// this is getting thrown 
    }
}

我尝试添加新的EncryptedPrivateKeyInfo(rsaPrivateKey.getBytes())在decode()调用之前对其进行解密,但这引发了自己的异常。

java rsa private-key
1个回答
0
投票

初步来说你的问题有很多错误。

  • 没有命令

    openssl -newKey rsa:2048 -new sha256 ...
    。您的意思是
    openssl req -newkey rsa:2048 -new -sha256 ...
    req
    必须存在,
    -newkey
    必须小写,摘要必须以
    -
    开头)。

  • rsaPrivateKey.replaceAll("-----.*?.....")
    无法编译。如果您将所需的第二个参数添加为
    ""
    ,它会编译,但会做完全错误的事情并破坏您的数据。

  • Base64.getDecoder(rsaPrivateKey)
    无法编译(假设
    java.util.Base64
    ),如果编译了,则不是
    new PKCS8EncodedKeySpec
    的正确参数,而是可以通过对来自
    未加密
    密钥文件的数据调用 .decode(body) 的结果来代替.

对您的文件类型进行 PEM 解码的正确方法是

String body = string_without_linebreaks.repaceAll ("-----(BEGIN|END) ENCRYPTED PRIVATE KEY-----","");
// or if you have some fetish about generality
// = string_without_linebreaks.replaceAll ("-----(BEGIN|END)[A-Z ]*-----","");
// followed by 
Base64.getDecoder().decode(body)

但是您不能直接将其用作

PKCS8EncodedKeySpec
,因为它必须未加密。

javax.crypto.EncryptedPrivateKeyInfo
确实是读取加密 PKCS8 的纯 Java 方式 - 但对于使用 PBES2 的 PKCS8(如 OpenSSL 现在所做的那样),它仅在密码为 AES-128 或 AES-256 时才有效,而
openssl req
创建一个文件使用 PBES2 和三重 DES(又名 TDEA、DES3、3DES、DESede)加密。如果您使用例如重新加密您的文件

openssl pkey -in from_req.key -aes-128-cbc -out fixed.key

然后对于上面的 de-PEM 之后的 that 文件,您可以使用

解析结果
EncryptedPrivateKeyInfo epki = new EncryptedPrivateKeyInfo( base64_decoded );

在Java 19以上你可以简单地解密它

SecretKey kek = SecretKeyFactory.getInstance( epki.getAlgName() )
    .generateSecret( new PBEKeySpec (your_password_as_chararray) );
PrivateKey pkey = KeyFactory.getInstance("RSA") .generatePrivate (epki.getKeySpec(kek));

但低于 19 你必须使用我在这里展示的hack或硬编码,例如

PBEwithHmacSHA256andAES_128
对于 SKF -- 或 SHA1,如果您使用 (d) OpenSSL 低于 1.1.0,现在已经有 8 年多了并且很少见。

或者,在所有版本的 Java 中以及对于所有(通常使用的)PKCS8 加密,您可以使用 BouncyCastle 直接读取 PEM,正如我在那里提到的,并且许多其他问题已经解决。

© www.soinside.com 2019 - 2024. All rights reserved.