无法解析 Java 中的 RSA 公钥

Failed to parse RSA publicKey in Java

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

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

但是对于下面的RSApublic密钥

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 public 密钥解析代码。

您的 public 密钥(这里只是 Base64 编码的部分)似乎是 'RSA Public Key' 而不是 'Public Key'。后者是 Java 能够使用的格式。

要阅读 'RSA Public Key',您需要 Bouncy Castle 库和额外的 7 行代码。因为你有没有 'wrapping' 页眉和页脚的键,所以我添加了两个 手动排队。

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

结果:

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("
        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);
    }
}

您的问题类似于, though not the same. Just like PKCS8 is a generic format for private keys in (almost) any algorithm, by containing both an AlgorithmIdentifier that identifies the algorithm and algorithm-specific data, Java uses the generic format SubjectPublicKeyInfo (SPKI) defined by X.509/PKIX for public keys, which Java calls X509EncodedKeySpec, containing an AlgId plus algorithm-specific data. (See the javadoc for java.security.Key; for some reason I am currently unable to access docs.oracle.com to get a link.) You have only the algorithm-specific data defined by PKCS1 RSAPublicKey中的问题。

你可以, or . Or (given BC or another ASN.1 library) you could use the same approach as in #31941413 except omit the Integer version (0) and wrap the data in a DERBitString instead of a DEROctetString, or the simpler and more direct approach I show in RSA should I use X.509 or PKCS #1 .

注意这不是 'generic'。您的格式与 algorithm-generic 相反,如前所述,这是 SPKI 和 PCKS8 的目的。也不是applciation-generic;除其他事项外,OpenSSH、PGP、Microsoft、PKCS11、JWK 和 XML 都使用与此不同的公钥格式,并且不易与 Java.

兼容