【问题标题】:Failed to parse RSA publicKey in Java无法在 Java 中解析 RSA publicKey
【发布时间】:2020-08-17 16:05:13
【问题描述】:

我正在使用以下代码块来解析任何要加密的 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 公钥解析代码。

【问题讨论】:

标签: java security rsa bouncycastle pkcs#8


【解决方案1】:

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

您可以parse and use it 'manually' with BouncyCastleconvert it to SPKI and use that。或者(给定 BC 或另一个 ASN.1 库)您可以使用与 #31941413 中相同的方法,除了省略整数版本 (0) 并将数据包装在 DERBitString 而不是 DEROctetString 中,或者我展示的更简单和更直接的方法在RSA should I use X.509 or PKCS #1

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

【讨论】:

  • 我已经解决了这个问题并编写了代码从 PKCS#1 创建 publicKey
【解决方案2】:

您的公钥(这里只是 Base64 编码的部分)似乎是“RSA 公钥” 而不是“公钥”。后者是Java能够使用的格式。

要读取“RSA 公钥”,您需要 Bouncy Castle 库和额外的 7 行代码。因为你有没有“包装”页眉和页脚的钥匙,所以我添加了这两个 手动排队。

请记住,以下代码没有适当的异常处理,仅用于教育目的。

结果:

key: Sun RSA public key, 2048 bits
  params: null
  modulus: 22678610734153400983507431374302231631648011897672768754638644005690558018788055145838420912495825001883497816406549666369767766949853573723573636289962789479998547620264293389522975840594912755684410510779642046063268111520844008640320545114702934792800828432077361704284837605938354936920018742130341245366517474980128047515437565419306561322350155414838564407700303406271838590880852369997316303577351737008942081641382006211591786506015023574950120763293965668830106827392978781367691242570394862298000041087969687942746452359360224223895623579995775734139473237799095359767270215802792812274542667250920043135261
  public exponent: 65537

代码:

import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import java.io.IOException;
import java.io.StringReader;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

public class MainSO {
    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        System.out.println("https://stackoverflow.com/questions/63454577/failed-to-parse-rsa-publickey-in-java");
        Security.addProvider(new BouncyCastleProvider());
        String rsaPublicKeyHeader = "-----BEGIN RSA PUBLIC KEY-----\n";
        String rsaPublicKeyFooter = "\n-----END RSA PUBLIC KEY-----";
        String rsaPublicKeyString = "MIIBCgKCAQEAs6YyGDXibkazM7QSeFBXjkAn5A8P87k+nuU6v5+zLJiD1KwkZ/SYnLwVSluOx19AzPHj07abDTJtthKtKpp2997UiV4CNUSzkZM1Eorf1+iLFhqeOiz9J5tYfFkKN5qPzwoPK4aFz35hQi7R1ORF9rFDPL+Ex79Tc+ABQF/CH5tn/NTXCNUYzLezg2Y1VOZGNhxd2LIv/29ZDxpJS8dD34H20HMMZCMGGolTXUIxVKI3cR0d1XzNCvAx3jcSkEUEPPH0lfusXqQOfCxJSIjorAzi5ucaWicvXYq6BNGulPqLoGBZnJ4HrFQF0oq1SU4i60VHqOgoiqMPQ+8cyjFBHQIDAQAB";
        PEMParser pemParser = new PEMParser(new StringReader(rsaPublicKeyHeader +
                rsaPublicKeyString + rsaPublicKeyFooter));
        SubjectPublicKeyInfo subjectPublicKeyInfo = (SubjectPublicKeyInfo) pemParser.readObject();
        byte[] publicKey = subjectPublicKeyInfo.getEncoded();
        // original code starts here
        PublicKey key = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKey));
        // check key
        System.out.println("key: " + key);
    }
}

【讨论】:

    猜你喜欢
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多