Java中的RSA密钥签名和验证(Android)

山姆

我在理解RSA签名和验证的概念时遇到了一个小问题。问题是我可以创建完美的密钥对(公钥和私钥)。

        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        random = SecureRandom.getInstance("SHA1PRNG");
        keyGen.initialize(2048, random);
        KeyPair pair = keyGen.generateKeyPair();
        myPrivateKey = pair.getPrivate();
        myPublicKey = pair.getPublic();

签名和验证如下:

        //Singing with private key
        Signature s = Signature.getInstance("SHA1withRSA");
        s.initSign(javaPrivateKey);

        //Verifying with public key
        Signature s = Signature.getInstance("SHA1withRSA");
        s.initVerify(javaPublicKey);

当我打印myPrivateKey和myPublicKey时,我看到公钥和私钥的模数(n)和公有指数(e)相同。

我已经将公钥和私钥转换为base64和hex,并且得到了完全不同的不同值。但是,我无法使用base64或hex签署消息。我只能用从中得到的签名:

         myPrivateKey = pair.getPrivate();  

我知道必须使用每个人都可以看到的公钥进行验证。接收者验证消息后,接收者是否仅使用模数和指数?发送者需要共享公共密钥的哪一部分?模数和指数还是Base64或十六进制值的键?

马丁·波德威斯

是的,接收器仅使用模数和指数。从数学上讲,没有其他组件需要验证RSA的签名。

使用大量数字(BigInteger在软件中实施RSA时通常使用的值)执行数学运算为了执行任何类型的计算,实现必须重新生成这些数字。这些数字的传输方式与算法无关紧要。

通常,RSA公钥是使用基于PKCS#1的某种东西编码的,后者使用ASN.1(定义结构)和BER / DER(定义该结构的编码)指定公钥格式。当然,不同的协议可以使用不同的公钥编码。例如,PGP使用完全不同的“包格式”对密钥进行编码。


但是,Java返回X.509(证书和CRL)规范中定义的SubjectPublicKeyInfo结构。除了模数和指数外,还包含一个算法标识符,以表明它RSA公钥。因此,此结构还可用于分配其他类型的键值。它可以通过调用来检索getEncoded()RSAPublicKey假设该实例是兼容Oracle提供的一个- -它们通常是实例。Android的实现当然应该与此结构兼容。注意,SubjectPublicKeyInfo进行结构包含PKCS#1公钥结构在它的内部

要进行反向操作,您需要KeyFactory.getInstance("RSA")使用X509EncodedKeySpec并使用派生密钥,并使用给定的字节数组进行初始化。


如果需要文本字符串而不是二进制字符串,则可以将返回的字节转换getEncoded()为基数64和十六进制。当然,在这种情况下,您需要先对结果进行编码(即解码),然后才能对字节本身进行解码。

您也可以自己编码模数和公共指数。您可以使用RSAPublicKey.getModulus()检索它们RSAPublicKey.getPublicExponent()要将它们恢复为,RSAPublicKey您可以使用KeyFactory.getInstance("RSA")RSAPublicKeySpec这样,您可以例如仅创建一个字符串"(<modulus>, <exp>)"并使用它来分发密钥。通常,您可能希望遵守预定义的标准。


该答案未涵盖的事实是,要使用公共密钥进行验证,您首先需要建立对公共密钥的信任如果您不能信任公共密钥,那么您将不知道是谁创建了公共密钥。在这种情况下,您也不能相信验证操作的结果;签名可能是用对手的密钥对创建的。不过,对于这个答案,深入研究公钥基础结构(PKI / PKIX)有点过多。

同样:SHA-1不再被认为是安全的,尤其是对于签名生成/验证。您可能希望至少使用SHA256withRSA-稍微更高级,更安全-使用PSS的RSA方案。2048位太小,无法舒适使用;如果方案允许,建议使用4096位密钥。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章