从字符串创建RSA公钥 [英] Creating RSA Public Key From String

查看:326
本文介绍了从字符串创建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.如果没有诸如Bouncy Castle之类的其他库,该解决方案将更易于执行.因此,如果您不需要外部库,那么可以在此处.


或者,可以编写一个简单的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解码器功能支持的.


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

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.

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

         }

解决方案

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.

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.


Alternatively a simple BER decoder could be written to decode the structure into the two BigInteger values. The structure itself is not that complicated but the BER/DER length encoding takes some getting used to.

However, you can also use Bouncy Castle (lightweight API) to solve your issues:

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.


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.

这篇关于从字符串创建RSA公钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆