【问题标题】:Android RSA Encryption throws InvalidKeySpecExceptionAndroid RSA 加密抛出 InvalidKeySpecException
【发布时间】:2018-11-11 03:25:02
【问题描述】:

我正在尝试使用给定的公钥加密数据。

public static final String public_key = "MIIBCgKCAQEAr/oYAoxIcXnLzVDNN6TPJVjkwOJZnDcSEeoRntqhOvgjiycfswMWZZ5+UClJ4CMgMCVAs71BzAJzPv902Jt763SPkAO/vh6CwfLq2S3YcqDoRQJYZuSKQHW40R6sN7eFvQdxYhJnF45ketCdLdPFuF5o/ieChwLcCEDKzkWD7xio2TQlZ8jfzB4jNGr6bmW/aqF5ihe0pbhtfvlyM+jNF2vWeB1SCJ4v5zHLNKKYNy4cMsmIGHKB+0BaGVz87eYp65FFc2K9LawBBbWtVCxykYBzEnXRuU+0YzcTi4LThXg1cUsf++LK9qL/G7PZdN6HMGP7DYzgstFLfp8VRpKhqQIDAQAB";

String encryptData(String txt)
{
    String encoded = null;
    try {
        PublicKey key = KeyFactory.getInstance("RSA").generatePublic(
                new X509EncodedKeySpec(Base64.decode(public_key, Base64.DEFAULT)));

        Cipher cph = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cph.init(Cipher.ENCRYPT_MODE, key);
        encoded = Base64.encodeToString(cph.doFinal(txt.getBytes()),
                Base64.DEFAULT);
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    return encoded;
}

然后得到错误

W/System.err: java.security.spec.InvalidKeySpecException: 
java.lang.RuntimeException: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag
    at com.android.org.conscrypt.OpenSSLKey.getPublicKey(OpenSSLKey.java:143)
    at com.android.org.conscrypt.OpenSSLRSAKeyFactory.engineGeneratePublic(OpenSSLRSAKeyFactory.java:47)
    at java.security.KeyFactory.generatePublic(KeyFactory.java:172)

我在 Python3 中使用了相同的公钥,带有“BEGIN PUBLIC KEY...END PUBLIC KEY”页眉/页脚,它工作正常:

public_key = """-----BEGIN PUBLIC KEY-----
MIIBCgKCAQEAr/oYAoxIcXnLzVDNN6TPJVjkwOJZnDcSEeoRntqhOvgjiycfswMWZZ5+UClJ4CMgMCVAs71BzAJzPv902Jt763SPkAO/vh6CwfLq2S3YcqDoRQJYZuSKQHW40R6sN7eFvQdxYhJnF45ketCdLdPFuF5o/ieChwLcCEDKzkWD7xio2TQlZ8jfzB4jNGr6bmW/aqF5ihe0pbhtfvlyM+jNF2vWeB1SCJ4v5zHLNKKYNy4cMsmIGHKB+0BaGVz87eYp65FFc2K9LawBBbWtVCxykYBzEnXRuU+0YzcTi4LThXg1cUsf++LK9qL/G7PZdN6HMGP7DYzgstFLfp8VRpKhqQIDAQAB
-----END PUBLIC KEY-----
"""

def encode(msg):
    rsa_key = RSA.importKey(public_key)
    pks1_v1_5 = PKCS1_v1_5.new(rsa_key)
    encrypted = pks1_v1_5.encrypt(msg.encode('utf-8'))
    encrypted = base64.b64encode(encrypted)
    return encrypted

有人可以帮帮我吗?

--- 编辑 ---

我对 Python 代码进行了一些调试:进入 'RSA.importKey(public_key)' 我看到它将密钥识别为 PEM 编码密钥,删除了页眉/页脚并将其转换为二进制 (binascii.a2b_base64)。二进制文件被传递给 RSA._importKeyDER,RSA._importKeyDER 发现它遵循 PKCS#1 标准,并且在评论中,“DER 对象是一个具有两个元素的 RSAPublicKey SEQUENCE”。

【问题讨论】:

  • 您的密钥格式不适合 X509EncodedKeySpec。最简单的解决方法是将其放入正确的格式。
  • @JamesKPolk 我通过 HTTP 请求从另一个系统获取了公钥,并且我已经测试并成功使用此密钥和我的帖子中的 Python3 代码进行了加密。
  • 太棒了,比你在 python 代码中的rsa_key.export_key(format='DER') 更好,结果将是 Java 的 X509EncodedKeySpec 的正确格式。
  • @JamesKPolk 问题是public_key不是静态的,如上面的代码,我是从HTTP请求中收到的,每次都不一样,所以我需要找到Java的方式来从我收到的公钥中正确获取 RSA 密钥
  • 好吧,那么您将不得不编写一些代码来转换它。 Bouncycastle Java 库可以为您完成大部分工作,如果您可以在项目中使用它。

标签: android rsa public-key-encryption


【解决方案1】:

你是从 openssl 生成你的公钥吗,因为你的公钥太长了:

例如,我从 openssl 生成并替换您的公钥,一切正常:

openssl genrsa -out key.pem 1024

openssl rsa -in key.pem -pubout > key.pub

并将 key.pub 字符串粘贴到您的代码中。

【讨论】:

  • 我从另一个系统收到 public_key,我需要使用他们的公钥对数据进行编码,所以我不知道他们是如何生成的。
猜你喜欢
  • 1970-01-01
  • 2010-12-10
  • 2013-04-20
  • 1970-01-01
  • 2015-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-10
相关资源
最近更新 更多