java - 从字符串创建 RSA 公钥

标签 java android cryptography rsa

我使用 1024 RSA 生成了这个测试公钥,然后在另一个编码平台中将其编码为 DER 和 Base64。我将 key 复制到 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(); 
            }

         }

最佳答案

您拥有的 key 采用 PKCS#1 格式,而不是 Java 接受的 SubjectPublicKeyInfo 结构。 PKCS#1 只是 RSA 参数的编码,缺少算法标识符等内容。 SubjectPublicKeyInfo 在内部使用 PKCS#1 - 无论如何用于 RSA 公钥。

由于 PKCS#1 公钥位于 SubjectPublicKeyInfo 结构的末尾,因此可以简单地为字节添加前缀,以便它们成为 RSA SubjectPublicKeyInfo。如果没有额外的库(如 Bouncy CaSTLe),该解决方案更容易执行。因此,如果您需要在没有外部库的情况下使用,那么您可以看看我的回答 here .


或者,可以编写一个简单的 BER 解码器来将结构解码为两个 BigInteger 值。结构本身is not that complicated但是 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);

如您所见,它实际上只需要一个类作为接口(interface),尽管这当然得到了 Bouncy CaSTLe 中整个 ASN.1/BER 解码器功能的支持。


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

关于java - 从字符串创建 RSA 公钥,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33425446/

相关文章:

java - 使用 JCo 打印 BAPI 列表

android - 如何在后台android中运行无限循环

java - 通过 JSCH 使用 sftp 连接时出现安全异常

encryption - 如果服务器受到攻击,如何防止中间人攻击?

mysql - MySQL 是否有加密安全的随机数生成器?

java - 从文件读取到列表

java: 将 DynaBean (apache-commons-beanutils) 转换为 List

java - 我需要解释 Android 的 JNI 代码行

java - 方法中的字符串参数不起作用

android - 运行我的应用程序时如何调用事件 "screen_off"?