当前位置: 首页 > 知识库问答 >
问题:

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

狄誉
2023-03-14

我在理解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或十六进制对消息进行签名。我只能用我从这里得到的东西来签名:

         myPrivateKey = pair.getPrivate();  

我知道验证需要用每个人都可见的公钥来完成。当消息由接收者验证时,接收者是否只使用模和指数?发送方需要共享公钥的哪一部分?键的模数和指数还是Base64还是十六进制值?

共有1个答案

马华茂
2023-03-14

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

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

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

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

要反转,您需要keyfactory.getinstance(“rsa”)并使用x509encodedkeyspec派生密钥,该密钥是用给定的字节数组初始化的。

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

也可以自己编码模和公指数。您可以使用rsapublickey.getmodulus()rsapublickey.getpublicexponent()检索它们。要将它们反转回rsapublickey,可以使用keyfactory.getinstance(“rsa”)rsapublickeyspec。这样,您可以创建一个字符串“( )” 并使用它来分发密钥。不过,一般来说,您需要遵守预定义的标准。

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

同样地:SHA-1不再被认为是安全的,尤其是对于签名生成/验证。您至少需要使用SHA256withrsa,或者更高级、更安全的使用PSS的RSA方案。2048比特对舒适来说太小了;如果您的方案允许,建议使用4096位密钥。

 类似资料:
  • 在PHP中,我试图使用AWS的RSA公钥(我在https://cognito-identity.amazonaws.com/.well-known/jwks_uri). 密钥以适当的页眉/页脚开始,然后开始RSA公钥等等。我查看了一些PHP库,如Emarref\Jwt\Jwt\code>,但是我发现了错误:。这一切归结为基本的php函数:。 我已经研究了php。net/manual进行openss

  • 我已经使用Node rsa在Node中生成了一对私钥和公钥,并且可以在Node中使用这些密钥成功地进行签名和验证。 我尝试使用公钥的模和指数来验证中的签名(由节点中的私钥签名)。网 e、 g.我有一个string=“foo”,它有一个由Node生成的签名“abc123”。在里面NET我想使用公钥的模和指数来确认签名“abc123”对“foo”有效。 我想使用模数和指数而不是直接使用公钥的原因是因为

  • 我试图使用javascript创建ECDSA算法的密钥对,签名消息,然后在服务器端验证它(使用Java)。 示例javascript代码: 例如: 我做错了什么?

  • 另外,这里还有一个函数演示,它从mod和指数生成PEM(摘自http://stackoverflow.com/questions/18835132/xml-to-pem-in-node-js) 前面提到的jsonwebtoken库可以使用任何一种方法来验证JWT--但是为什么呢?如果这两种验证方法都可以验证一个JWT签名,为什么它们都存在呢?他们之间有什么权衡?一个比另一个更安全吗?我应该使用哪一

  • 问题内容: 我正在尝试使用RSA私钥加密某些内容。 我遵循以下示例:http : //www.junkheap.net/content/public_key_encryption_java, 但将其转换为使用私钥而不是公共密钥。遵循该示例,我认为我需要做的是: 读取DER格式的私钥 生成PCKS8EncodedKeySpec 从KeyFactory调用generatePrivate()获得一个私钥

  • 我想知道是否有一个示例C代码或库可以使用RSA公钥验证我的JWT令牌签名。我找不到任何涉及C的示例 openssl for C没有任何与RSA相关的示例。 谢谢