首页  >  文章  >  Java  >  如何在没有 Bouncycastle 的情况下在 Java 中读取 PEM 编码的 RSA 私钥?

如何在没有 Bouncycastle 的情况下在 Java 中读取 PEM 编码的 RSA 私钥?

Susan Sarandon
Susan Sarandon原创
2024-11-09 21:44:02930浏览

How to Read PEM Encoded RSA Private Keys in Java Without Bouncycastle?

读取 PEM 编码的 RSA 私钥(不使用 Bouncycastle)

大多数用于从 PEM 文件读取私钥的 Java 解决方案都依赖于 Bouncycastle 提供程序,而这可能不依赖于 Bouncycastle 提供程序在某些环境下是可以接受的。本文介绍了一种仅利用 Java 加密扩展 (JCE) 和 sun.security 进行 DER 解析的替代方法。

代码示例

下面是支持 PKCS#8 和PEM 文件中私钥的 PKCS#1 格式:

import sun.security.util.DerInputStream;
import sun.security.util.DerValue;

import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.util.Base64;

public static PrivateKey pemFileLoadPrivateKeyPkcs1OrPkcs8Encoded(File pemFileName) throws GeneralSecurityException, IOException {
    // PKCS#8 format
    final String PEM_PRIVATE_START = "-----BEGIN PRIVATE KEY-----";
    final String PEM_PRIVATE_END = "-----END PRIVATE KEY-----";

    // PKCS#1 format
    final String PEM_RSA_PRIVATE_START = "-----BEGIN RSA PRIVATE KEY-----";
    final String PEM_RSA_PRIVATE_END = "-----END RSA PRIVATE KEY-----";

    Path path = Paths.get(pemFileName.getAbsolutePath());

    String privateKeyPem = new String(Files.readAllBytes(path));

    if (privateKeyPem.indexOf(PEM_PRIVATE_START) != -1) { // PKCS#8 format
        privateKeyPem = privateKeyPem.replace(PEM_PRIVATE_START, "").replace(PEM_PRIVATE_END, "");
        privateKeyPem = privateKeyPem.replaceAll("\s", "");

        byte[] pkcs8EncodedKey = Base64.getDecoder().decode(privateKeyPem);

        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePrivate(new PKCS8EncodedKeySpec(pkcs8EncodedKey));

    } else if (privateKeyPem.indexOf(PEM_RSA_PRIVATE_START) != -1) {  // PKCS#1 format

        privateKeyPem = privateKeyPem.replace(PEM_RSA_PRIVATE_START, "").replace(PEM_RSA_PRIVATE_END, "");
        privateKeyPem = privateKeyPem.replaceAll("\s", "");

        DerInputStream derReader = new DerInputStream(Base64.getDecoder().decode(privateKeyPem));

        DerValue[] seq = derReader.getSequence(0);

        if (seq.length < 9) {
            throw new GeneralSecurityException("Could not parse a PKCS1 private key.");
        }

        // skip version seq[0];
        BigInteger modulus = seq[1].getBigInteger();
        BigInteger publicExp = seq[2].getBigInteger();
        BigInteger privateExp = seq[3].getBigInteger();
        BigInteger prime1 = seq[4].getBigInteger();
        BigInteger prime2 = seq[5].getBigInteger();
        BigInteger exp1 = seq[6].getBigInteger();
        BigInteger exp2 = seq[7].getBigInteger();
        BigInteger crtCoef = seq[8].getBigInteger();

        RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2, exp1, exp2, crtCoef);

        KeyFactory factory = KeyFactory.getInstance("RSA");

        return factory.generatePrivate(keySpec);
    }

    throw new GeneralSecurityException("Not supported format of a private key");
}

用法

要使用此代码,只需将包含私钥的 PEM 文件的路径作为参数传递给 pemFileLoadPrivateKeyPkcs1OrPkcs8Encoded方法。该方法将返回 PrivateKey 类的实例,然后可以将其用于解密或任何其他适当的目的。

以上是如何在没有 Bouncycastle 的情况下在 Java 中读取 PEM 编码的 RSA 私钥?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn