首页 > 解决方案 > 无法在 Java 中解析 RSA publicKey

问题描述

我正在使用以下代码块来解析任何要加密的 RSA 公钥。

    static byte[] encrypt(byte[] publicKey, byte[] inputData) throws Exception {

    PublicKey key = KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(publicKey));

    Cipher cipher = Cipher.getInstance(ALGORITHM);
    cipher.init(Cipher.ENCRYPT_MODE, key);

    byte[] encryptedBytes = cipher.doFinal(inputData);

    return encryptedBytes;
}

public static String getEncrypted(String data, String key) throws Exception {
    byte[] keyBytes = Base64.getDecoder().decode(key);
    return new String(Base64.getEncoder().encode(encrypt(keyBytes, data.getBytes())));
}

但是对于以下 RSA 公钥

MIIBCgKCAQEAs6YyGDXibkazM7QSeFBXjkAn5A8P87k+nuU6v5+zLJiD1KwkZ/SYnLwVSluOx19AzPHj07abDTJtthKtKpp2997UiV4CNUSzkZM1Eorf1+iLFhqeOiz9J5tYfFkKN5qPzwoPK4aFz35hQi7R1ORF9rFDPL+Ex79Tc+ABQF/CH5tn/NTXCNUYzLezg2Y1VOZGNhxd2LIv/29ZDxpJS8dD34H20HMMZCMGGolTXUIxVKI3cR0d1XzNCvAx3jcSkEUEPPH0lfusXqQOfCxJSIjorAzi5ucaWicvXYq6BNGulPqLoGBZnJ4HrFQF0oq1SU4i60VHqOgoiqMPQ+8cyjFBHQIDAQAB

解析时出现以下异常

Caused by: java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: algid parse error, not a sequence
    at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:205)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:334)
Caused by: java.security.InvalidKeyException: IOException: algid parse error, not a sequence
    at sun.security.x509.X509Key.decode(X509Key.java:397)
    at sun.security.x509.X509Key.decode(X509Key.java:402)
    at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:86)
    at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:298)
    at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:201)

知道什么是失败的以及如何制作通用的 RSA 公钥解析代码。

标签: javasecurityrsabouncycastlepkcs#8

解决方案


您的问题类似于 InvalidKeySpecException 中的问题:algid parse error, not a sequence,虽然不一样。就像 PKCS8 是(几乎)任何算法中私钥的通用格式一样,通过包含标识算法和算法特定数据的 AlgorithmIdentifier,Java 使用由 X.509/PKIX 定义的通用格式 SubjectPublicKeyInfo (SPKI)用于公共Java 调用的键,X509EncodedKeySpec包含一个 AlgId 和特定于算法的数据。(请参阅 javadoc java.security.Key;由于某种原因,我目前无法访问docs.oracle.com以获取链接。)您只有PKCS1 RSAPublicKey 定义的算法特定数据。

您可以使用 BouncyCastle 手动解析和使用它,或者将其转换为 SPKI 并使用它。或者(给定 BC 或另一个 ASN.1 库)您可以使用与 #31941413 中相同的方法,除了省略整数版本 (0) 并将数据包装在 DERBitString 而不是 DEROctetString 中,或者我展示的更简单和更直接的方法在RSA 中,我应该使用 X.509 还是 PKCS #1

请注意,这不是“通用的”。您的格式与算法通用相反,如前所述,这是 SPKI 和 PCKS8 的目的。它也不是应用程序通用的;除其他外,OpenSSH、PGP、Microsoft、PKCS11、JWK 和 XML 都使用与此不同的公钥格式,并且不易与 Java 兼容。


推荐阅读