在Android中将PEM转换为公钥

12

我看过很多类似的问题,但没有一个对我奏效。我只是想将从服务器检索到的PEM格式的RSA公钥转换为Android中的PublicKey。有人能指点我一下吗?

编辑: 我已成功使用以下代码将PEM转换为PublicKey,但在编码消息时,我得到了意外的输出......

 public PublicKey getFromString(String keystr) throws Exception
    {
        // Remove the first and last lines

        String pubKeyPEM = keystr.replace("-----BEGIN PUBLIC KEY-----\n", "");
        pubKeyPEM = pubKeyPEM.replace("-----END PUBLIC KEY-----", "");

        // Base64 decode the data

        byte [] encoded = Base64.decode(pubKeyPEM);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        PublicKey pubkey = kf.generatePublic(keySpec);

        return pubkey;
    }

    public String RSAEncrypt(final String plain) throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, IllegalBlockSizeException, BadPaddingException, IOException {

        if (pubKey!=null) {
            cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            encryptedBytes = cipher.doFinal(plain.getBytes());
            Log.d("BYTES", new String(encryptedBytes));
            return Hex.encodeHexString(encryptedBytes);
        }
        else
            return null;
    }

输出结果如下:

b6813f8791d67c0fa82890d005c8ff554b57143b752b34784ad271ec01bfaa9a6a31e7ae08444baef1585a6f78f3f848eecb1706bf7b2868fccefc9d728c30480f3aabc9ac5c3a9b4b3c74c2f7d6f0da235234953ea24b644112e04a2ec619f6bf95306ef30563c4608ec4b53ed7c15736d5f79c7fa1e35f2444beb366ae4c71

当我期望得到更接近以下内容时:

JfoSJGo1qELUbpzH8d4QXtafup+J2F9wLxHCop00BQ4YS0cRdRCKDfHpFPZQYjNeyQj00HwHbz+vj8haTPbpdqT94AHAl+VZ+TPAiUw1U5EXLLyy4tzbmfVI7CwvMm26lwB4REzYUZdedha1caxMEfxQ5duB+x4ol9eRZM/savg=

我是否遗漏了某些格式或文件类型?


你尝试过 https://dev59.com/AXA75IYBdhLWcg3wipmH/ 中的方法吗? - Barend
2
我需要能够在应用程序中完成所有操作,而不是使用命令行。 - cph2117
如果您需要Base64输出,为什么要在byte [] encoded = Base64.decode(pubKeyPEM);行中将密钥解码为二进制? - AaA
这是 X509EncodedKeySpec 的预期输入。 - cph2117
@cph2117 我正在尝试使用您的代码与我的.pem文件配合使用,但是我的包含公钥的.pem文件不包含字符串"-----BEGIN PUBLIC KEY-----\n",我该如何继续? - codeKiller
显示剩余3条评论
2个回答

8
回答我的问题...第一个输出是十六进制的,第二个输出是base64编码的。只需将返回语句更改为return new String(Base64.encode(encryptedBytes));,就可以了!

请帮我解决在Android中如何加密PEM格式的公钥问题。我找不到任何解决方案 :-( - Chandru
@Chandru - 你为什么想要加密公钥? - kilokahn

4

这个回答并没有解答问题,但我认为它的内容相关。我将其作为答案发布是因为它不适合作为评论。

PEM vs DER

  • PEM基本上封装了DER编码的证书或密钥。
  • DER是二进制的,PEM是文本的;所以PEM可以轻松地复制粘贴到电子邮件中,例如。
  • PEM所做的是:
    1. 使用Base64编码DER证书或密钥,并且
    2. -----BEGIN <something>----------END <something>-----来分隔结果。
  • 密钥或证书是相同的,只是用不同的格式表示。

大部分内容来自ASN.1(wiki)

DER转换为Android/Java公钥

The following is an example of how to use a key factory in order to instantiate a DSA public key from its encoding. Assume Alice has received a digital signature from Bob. Bob also sent her his public key (in encoded format) to verify his signature. Alice then performs the following actions:

X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey);
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);

...

请注意,此示例中的bobEncodedPubKey是DER编码的。

https://developer.android.com/reference/java/security/KeyFactory

将PEM转换为Android/Java公钥

与DER的操作类似,但需先执行以下步骤:

  1. 删除BEGIN/END边界,并
  2. 解码Base64内容以获取原始DER。

(问题已经展示了如何执行此操作的代码。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接