Java 从字符串创建 RSA 公钥
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33425446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Creating RSA Public Key From String
提问by raximus
I've generated this test public key using 1024 RSA and then encoded it to DER and Base64 in another coding platform. I copied the key into a string in Android/Eclipse and I am trying to turn it into a public key using KeyFactory. It just keeps giving me an InvalidKeySpecException no matter what I try. Any advice at all would be appreciated.
我已经使用 1024 RSA 生成了这个测试公钥,然后在另一个编码平台中将其编码为 DER 和 Base64。我将密钥复制到 Android/Eclipse 中的字符串中,并尝试使用 KeyFactory 将其转换为公钥。无论我尝试什么,它都会不断给我一个 InvalidKeySpecException。任何建议都将不胜感激。
private void prepKeys() {
String AppKeyPub = "MIGHAoGBAOX+TFdFVIKYyCVxWlnbGYbmgkkmHmEv2qStZzAFt6NVqKPLK989Ow0RcqcDTZaZBfO5" +
"5JSVHNIKoqULELruACfqtGoATfgwBp4Owfww8M891gKNSlI/M0yzDQHns5CKwPE01jD6qGZ8/2IZ" +
"OjLJNH6qC9At8iMCbPe9GeXIPFWRAgER";
// create the key factory
try {
KeyFactory kFactory = KeyFactory.getInstance("RSA");
// decode base64 of your key
byte yourKey[] = Base64.decode(AppKeyPub,0);
// generate the public key
X509EncodedKeySpec spec = new X509EncodedKeySpec(yourKey);
PublicKey publicKey = (PublicKey) kFactory.generatePublic(spec);
System.out.println("Public Key: " + publicKey);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
采纳答案by Maarten Bodewes
The key you have is in PKCS#1 format instead of SubjectPublicKeyInfo structure that Java accepts. PKCS#1 is the encoding of the RSA parameters only and lacks things such as an algorithm identifier. SubjectPublicKeyInfo uses PKCS#1 internally - for RSA public keys anyway.
您拥有的密钥采用 PKCS#1 格式,而不是 Java 接受的 SubjectPublicKeyInfo 结构。PKCS#1 只是 RSA 参数的编码,缺少诸如算法标识符之类的东西。SubjectPublicKeyInfo 在内部使用 PKCS#1 - 无论如何都用于 RSA 公钥。
As the PKCS#1 public key is at the end of the SubjectPublicKeyInfo structure it is possible to simply prefix the bytes so that they become an RSA SubjectPublicKeyInfo. That solution is easier to perform without additional libraries such as Bouncy Castle. So if you need to go without an external library then you may have a look at my answer here.
由于 PKCS#1 公钥位于 SubjectPublicKeyInfo 结构的末尾,因此可以简单地为字节加上前缀,使它们成为 RSA SubjectPublicKeyInfo。该解决方案更易于执行,无需额外的库,例如 Bouncy Castle。因此,如果您不需要外部库,那么您可以在此处查看我的答案。
Alternatively a simple BER decoder could be written to decode the structure into the two BigInteger values. The structure itself is not that complicatedbut the BER/DER length encoding takes some getting used to.
或者,可以编写一个简单的 BER 解码器来将结构解码为两个 BigInteger 值。结构本身并不复杂,但 BER/DER 长度编码需要一些时间来适应。
However, you can also use Bouncy Castle (lightweight API) to solve your issues:
但是,您也可以使用 Bouncy Castle(轻量级 API)来解决您的问题:
String publicKeyB64 = "MIGHAoGBAOX+TFdFVIKYyCVxWlnbGYbmgkkmHmEv2qStZzAFt6NVqKPLK989Ow0RcqcDTZaZBfO5"
+ "5JSVHNIKoqULELruACfqtGoATfgwBp4Owfww8M891gKNSlI/M0yzDQHns5CKwPE01jD6qGZ8/2IZ"
+ "OjLJNH6qC9At8iMCbPe9GeXIPFWRAgER";
// ok, you may need to use the Base64 decoder of bouncy or Android instead
byte[] decoded = Base64.getDecoder().decode(publicKeyB64);
org.bouncycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(decoded);
BigInteger modulus = pkcs1PublicKey.getModulus();
BigInteger publicExponent = pkcs1PublicKey.getPublicExponent();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, publicExponent);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey generatedPublic = kf.generatePublic(keySpec);
System.out.printf("Modulus: %X%n", modulus);
System.out.printf("Public exponent: %d ... 17? Why?%n", publicExponent); // 17? OK.
System.out.printf("See, Java class result: %s, is RSAPublicKey: %b%n", generatedPublic.getClass().getName(), generatedPublic instanceof RSAPublicKey);
As you can see it actually only requires a single class as interface, although that is of course backed up with the entire ASN.1/BER decoder functionality within Bouncy Castle.
正如您所看到的,它实际上只需要一个类作为接口,尽管这当然是由 Bouncy Castle 中的整个 ASN.1/BER 解码器功能支持的。
Note that it may be required to change the Base 64 decoder to the Android specific one (android.util.Base64
). This code was tested on an equivalent Java runtime.
请注意,可能需要将 Base 64 解码器更改为 Android 特定的android.util.Base64
解码器( )。此代码在等效的 Java 运行时上进行了测试。
回答by Vikrama Kumar
For those who dont want to use Bouncy Castle
对于那些不想使用充气城堡的人
public class RSAKeySeperation {
public static void main(String[] args) throws InvalidKeySpecException, NoSuchAlgorithmException {
String publicKeyB64 = "MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQBV8xakN/wOsB6qHpyMigk/5PrSxxd6tKTJsyMIq5f9npzZue0mI4H2o8toYImtRk6VHhcldo0t7UwsQXmFMk7D"
+ "i3C53Xwfk7yEFSkXGpdtp/7fbqNnjVoJl/EPcgoDsTPrHYF/HgtmbhzuYvYeY1zpV0d2uYpFxAuqkE9FreuuH0iI8xODFe5NzRevXH116elwdCGINeAecHKgiWe"
+ "bGpRPml0lagrfi0qoQvNScmi/WIN2nFcI3sQFCq3HNYDBKDhO0AEKPB2FjvoEheJJwTs5URCYsJglYyxEUon3w6KuhVa+hzYJUAgNTCsrAhQCUlX4+5LOGlwI5gonm1DYvJJZAgMBAAEB";
byte[] decoded = Base64.getDecoder().decode(publicKeyB64);
X509EncodedKeySpec spec =
new X509EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPublicKey generatePublic = (RSAPublicKey) kf.generatePublic(spec);
BigInteger modulus = generatePublic.getModulus();
System.out.println(modulus);
BigInteger exponent = generatePublic.getPublicExponent();
System.out.println(exponent);
}
}