从String创建RSA公钥

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

您拥有的密钥是PKCS#1格式,而不是Java接受的SubjectPublicKeyInfo结构。 PKCS#1仅是RSA参数的编码,并且缺少诸如算法标识符之类的东西。 SubjectPublicKeyInfo在内部使用PKCS#1 – 无论如何都用于RSA公钥。

由于PKCS#1公钥位于SubjectPublicKeyInfo结构的末尾,因此可以简单地为字节添加前缀,使它们成为RSA SubjectPublicKeyInfo。

或者,可以编写简单的BER解码器以将结构解码为两个BigInteger值。 结构本身并不复杂,但BER / DER长度编码需要一些时间来习惯。

但是,您也可以使用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); 

正如您所看到的,它实际上只需要一个类作为接口,尽管当然在Bouncy Castle中支持整个ASN.1 / BER解码器function。


请注意,可能需要将Base 64解码器更改为Android特定的解码器( android.util.Base64 ) 。 此代码在等效的Java运行时上进行了测试。

对于那些不想使用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); } }