无法解析 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.
兼容
我正在使用以下代码块来解析任何要加密的 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);
}
}
您的问题类似于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中的问题。
你可以
注意这不是 'generic'。您的格式与 algorithm-generic 相反,如前所述,这是 SPKI 和 PCKS8 的目的。也不是applciation-generic;除其他事项外,OpenSSH、PGP、Microsoft、PKCS11、JWK 和 XML 都使用与此不同的公钥格式,并且不易与 Java.
兼容