gpt4 book ai didi

android - Java(Android) 中的 RSA key 签名和验证

转载 作者:行者123 更新时间:2023-11-29 23:20:35 31 4
gpt4 key购买 nike

我在理解 RSA 签名和验证的概念时遇到了一些小问题。问题是我可以创建非常好的 key 对(公钥和私钥)。

        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) 和公共(public)指数 (e) 相同。

我已将公钥和私钥转换为 base64 和十六进制,我得到了不同的值,这完全没问题。但是,我无法使用 base64 或 hex 对消息进行签名。我只能用我从中得到的东西来签名:

         myPrivateKey = pair.getPrivate();  

我知道需要使用每个人都可以看到的公钥进行验证。当接收方验证消息时,接收方是否仅使用模数和指数?发件人需要共享公钥的哪一部分? key 的模数和指数或 Base64 或十六进制值?

最佳答案

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

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

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


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

要反转你需要一个KeyFactory.getInstance("RSA")并使用 X509EncodedKeySpec 导出 key , 用给定的字节数组初始化。


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

也可以自己对模数和公共(public)指数进行编码。您可以使用 RSAPublicKey.getModulus() 检索它们和 RSAPublicKey.getPublicExponent() .将它们反转回 RSAPublicKey你可以使用 KeyFactory.getInstance("RSA")RSAPublicKeySpec .这样你就可以创建一个字符串 "(<modulus>, <exp>)"并用它来分发 key 。不过,通常您会希望遵守预定义的标准。


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

同样:SHA-1 不再被认为是安全的,尤其是用于签名生成/验证。您至少要使用 SHA256withRSA或者 - 稍微更高级和更安全一些 - 使用 PSS 的 RSA 方案。 2048 位对于舒适度来说太小了;如果您的方案允许,建议使用 4096 位 key 。

关于android - Java(Android) 中的 RSA key 签名和验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54390330/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com