我在理解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还是十六进制值?
是的,接收器只使用模和指数;从数学上讲,不需要其他组件来验证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相关的示例。 谢谢