2015-10-29 75 views
4

我已经使用1024 RSA生成了此测试公钥,然后在另一个编码平台中将它编码为DER和Base64。我将密钥复制到Android/Eclipse中的一个字符串中,我试图用KeyFactory将它变成公钥。无论我尝试什么,它都会给我一个InvalidKeySpecException。任何建议都将不胜感激。从字符串创建RSA公钥

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

     } 
+0

X509EncodedKeySpec预计在SubjectPublicKeyInfo进行格式(参见RFC 5280)的一个关键。您的密钥采用Java不支持的更简单的RSAPublicKey格式。解决方案:使用正确的Java支持格式对密钥进行编码。 –

+0

好吧,我不确定我能否在其他平台上生成密钥,但我当然会欣赏这些信息,并会试一试。谢谢。 – raximus

回答

4

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

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

或者,可以编写一个简单的BER解码器将结构解码为两个BigInteger值。结构本身is not that complicated但BER/DER长度编码需要一些习惯。

但是,您也可以使用充气城堡(轻量级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解码器功能。


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

+0

或者,如果Bouncy Castle不起作用,您可以使用Spongy Castle,但在这种情况下可能不需要。 –

+0

我实际上花了一个多小时才得到在eclipse中工作的Bouncy Castle,并且正在测试一些代码以尝试将RSA密钥转换为SubjectPublicKeyInfo格式。我试过这段代码,它确实创建了一个键。我不知道它是否能与我的其他平台一起工作,但这是一个开始。谢谢。 – raximus

+0

我只需更改Base 64行即可使其工作。 'byte [] encoded = Base64.decode(AppKeyPub,0);' – raximus

-2

对于那些谁不想使用充气城堡

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

} 
+0

这个答案是错误的。 –

+0

这需要SubjectPublicKeyInfo,[正如我在我的答案中解释](http://stackoverflow.com/a/33426378/589259)所述,它是不正确的。 –