【问题标题】:Problem transmiting a RSA public key, javaME , bouncy castle传输 RSA 公钥、java、充气城堡时出现问题
【发布时间】:2011-06-11 23:58:04
【问题描述】:

我正在将一个实例消息传递应用程序从 Java 移植到 JavaME,这也实现了密码学。问题是我想将我的公钥发送到服务器。桌面客户端有这个工作的代码:

byte[] encoded_public_key=publick_key.getEncoded();

并且服务器有这个代码来检索密钥:

EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encoded_public_key);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey puKey = keyFactory.generatePublic(publicKeySpec);

现在我查看了 getEncoded 的 API,它说它将密钥的 DER 编码形式作为字节数组返回 (http://www.docjar.com/docs/api/sun/s. ..tml#getEncoded)

我在 JavaME 中的实现是这样的:

RSAPublicKeyStructure public_key_JAVAME=new RSAPublicKeyStructure(modulus,exponent);
byte[] DER_encoded_public_key_JAVAME=public_key_JAVAME.getDEREncoded();

//the getEncoded functions returns exact the same byte array.

但是,当我尝试使用服务器代码检索 JavaME 创建的 DER 编码密钥时,换句话说,当我尝试这样做时:

EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(DER_encoded_public_key_JAVAME);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey puKey = keyFactory.generatePublic(publicKeySpec);

我明白了

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException: algid parse error, not a sequence
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:188)
at java.security.KeyFactory.generatePublic(KeyFactory.java:304)

Caused by: java.security.InvalidKeyException: IOException: algid parse error, not a sequence
at sun.security.x509.X509Key.decode(X509Key.java:380)
at sun.security.x509.X509Key.decode(X509Key.java:386)
at sun.security.rsa.RSAPublicKeyImpl.<init>(RSAPublicKeyImpl.java:66)
at sun.security.rsa.RSAKeyFactory.generatePublic(RSAKeyFactory.java:281)
at sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:184)

有趣的一点:来自普通 Java 的 DER 编码密钥(使用 getencoded() 函数)是一个字节数组,长度为 162 字节,而在 JavaME 中使用 bouncy castle 编码的 SAME 密钥 DER 长度为 140 字节。这 2 个 DER 编码的密钥不应该具有相同的长度吗?我的意思是它是 DER 编码格式的相同密钥,所以它们应该是相同的。

我做错了什么?


确实我没有注意到。问题是你知道如何从 bouncyCastle 中的 PublicKey 创建 subjectPublickeyInfo 对象吗?我试过了:

ByteArrayInputStream bIn = new ByteArrayInputStream(RSApublickey.toString().getbytes()); SubjectPublicKeyInfo info = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(bIn).readObject());

但它没有用。我也试过了:

ByteArrayInputStream(RSApublicKeyStructure.getEncoded()); SubjectPublicKeyInfo info = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(bIn).readObject());

实际上,我确实希望这不起作用,但我不得不尝试一下。那么如何从 RSAkeyparameters 创建 Subjectpublickeyinfo 呢?(我猜这是 bouncy 的城堡 API 的默默无闻的真正亮点之一)

再次感谢您的回复,您帮了大忙。您让我走上了正轨。

【问题讨论】:

    标签: encryption java-me bouncycastle


    【解决方案1】:

    DER 编码只是一种编码标准。说密钥是 DER 编码的等同于说它是 XML 编码的:您需要同意如何它是 DER-/XML 编码的,才能对其进行解码。

    在这种情况下,您的 RSAPublicKeyStructure.getEncoded() 将密钥作为 ASN.1 RSAPublicKey 的 DER 编码返回:

    RSAPublicKey ::= SEQUENCE {
      modulus INTEGER, -- n
      publicExponent INTEGER -- e 
    }
    

    另一方面,X509EncodedKeySpec 期望获得 ASN.1 PublicKeyInfo 的 DER 编码:

    PublicKeyInfo ::= SEQUENCE {
      algorithm AlgorithmIdentifier,
      PublicKey BIT STRING
    }
    

    要使用 BouncyCastle 创建 PublicKeyInfo,请执行以下操作(由 GregS 提供):

    RSAPublicKeyStructure rsaPublicKey = /* ... */
    AlgorithmIdentifier rsaEncryption = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE); 
    SubjectPublicKeyInfo publicKeyInfo = new SubjectPublicKeyInfo(rsaEncryption, rsaPublicKey);
    byte[] encodedPublicKeyInfo = publicKeyInfo.getEncoded();
    

    【讨论】:

    • 我不知道我没有通过 cmets 回答是否正确,但由于代码示例,我的回答太难阅读了,作为评论
    • @user581979 您可以更新您的问题。将其视为答案可能会让人们感到困惑。
    • 根据 rfc3279 #2.3.1,RSA 的 AlgorithmIdentifier 必须将参数设置为显式 ASN.1 NULL,而不是像 Java null 那样省略 -- 改用 DERNull.INSTANCE
    • @dave_thompson_085 谢谢。我犯了这个错误(将编程语言 null 与 ASN.1 null 混为一谈)太多次了。
    猜你喜欢
    • 2013-05-25
    • 1970-01-01
    • 2015-08-09
    • 2015-06-07
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    • 2022-11-07
    • 1970-01-01
    相关资源
    最近更新 更多