如何解决jwt如何在nodejs中实现RSA256签名验证
我试图了解JWT如何执行RS256签名验证的内部工作。签名算法按以下基本步骤工作:
- 散列原始数据
- 使用RSA私钥加密哈希
为了进行验证,它遵循以下步骤:
- 使用RSA公钥解密
- 将解密产生的哈希与原始消息的SHA256哈希进行匹配。
尝试在jwt之一上对此进行测试时
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.POstGetfAytaZS82wHcjoTyoqhMyxXiWdR7Nn7A29DNSl0EiXLdwJ6xC6AfgZWF1bOsS_TuYI3OG85AmiExREkrS6tDfTQ2B3WXlrr-wp5AokiRbz3_oB4OxG-W9KcEEbDRcZc0nH3L7LzYptiy1PtAylQGxHTWZXtGz4ht0bAecBgmpdgXMguEIcoqPJ1n3pIWk_dUZegpqx0Lka21H6XxUTxiy8OcaarA8zdnPUnV6AmNP3ecFawIFYdvJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6gUY618iYv7tuPWBFfEbLxtF2pZS6YC1aSfLQxeNe8djT9YjpvRZA
我发现从签名获得的哈希包含一些额外的字符。 例如。如果十六进制编码中的jwt大于jwt,则原始消息的SHA256为
8041fb8cba9e4f8cc1483790b05262841f27fdcb211bc039ddf8864374db5f53
但是解密后从上述jwt的签名获得的哈希为
3031300d0609608648016503040201050004208041fb8cba9e4f8cc1483790b05262841f27fdcb211bc039ddf8864374db5f53
在哈希前面还有3031300d060960864801650304020105000420
个额外的字符。
这些字符代表什么,从消息和签名获得的哈希值不应该是相同的吗?
解决方法
rfc7518 3.3定义了JWS算法RS256,384,512:
This section defines the use of the RSASSA-PKCS1-v1_5 digital
signature algorithm as defined in Section 8.2 of RFC 3447 [RFC3447]
(commonly known as PKCS #1),using SHA-2 [SHS] hash functions.
和rfc3447 8.2定义了RSASS-PKCS1-v1_5
RSASSA-PKCS1-v1_5 combines the RSASP1 and RSAVP1 primitives with the
EMSA-PKCS1-v1_5 encoding method. ....
其中rfc3447 9.2中将EMSA-PKCS1-v1_5定义为:
1. Apply the hash function to the message M to produce a hash value
H:
H = Hash(M).
If the hash function outputs "message too long," output "message
too long" and stop.
2. Encode the algorithm ID for the hash function and the hash value
into an ASN.1 value of type DigestInfo (see Appendix A.2.4) with
the Distinguished Encoding Rules (DER),where the type DigestInfo
has the syntax
DigestInfo ::= SEQUENCE {
digestAlgorithm AlgorithmIdentifier,digest OCTET STRING
}
The first field identifies the hash function and the second
contains the hash value. Let T be the DER encoding of the
DigestInfo value (see the notes below) and let tLen be the length
in octets of T.
3. If emLen < tLen + 11,output "intended encoded message length too
short" and stop.
4. Generate an octet string PS consisting of emLen - tLen - 3 octets
with hexadecimal value 0xff. The length of PS will be at least 8
octets.
5. Concatenate PS,the DER encoding T,and other padding to form the
encoded message EM as
EM = 0x00 || 0x01 || PS || 0x00 || T.
6. Output EM. [added: which is then modexp'ed with d by RSASP1 to
sign,or matched to the value modexp'ed with e by RSAVP1 to verify]
Notes.
1. For the six hash functions mentioned in Appendix B.1,the DER
encoding T of the DigestInfo value is equal to the following:
MD2: (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 02 05 00 04
10 || H.
MD5: (0x)30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 05 05 00 04
10 || H.
SHA-1: (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H.
SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00
04 20 || H.
SHA-384: (0x)30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00
04 30 || H.
SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00
04 40 || H.
您发现的前缀与注释1中为SHA-256哈希值的DigestInfo结构的第2步中的编码完全对应。
注意rfc3447 = PKCS1v2.1已被rfc8017 = PKCS1v2.2取代,但该区域唯一相关的更改是添加了SHAWS / JACK所不使用的SHA512 / 224和SHA512 / 256。 >
将签名和验证描述为“加密”和“解密”哈希(实际上是哈希的编码又称为填充)被认为已过时。它最初是在几十年前使用的,并且仅用于RSA,而没有其他签名算法,因为用于加密和解密与签名和验证的modexp操作之间存在数学相似性,但是发现将它们视为相同或可互换会导致在易受攻击和损坏的系统实现中。特别请参见rfc3447 5.2:
The main mathematical operation in each primitive is
exponentiation,as in the encryption and decryption primitives of
Section 5.1. RSASP1 and RSAVP1 are the same as RSADP and RSAEP
except for the names of their input and output arguments; they are
distinguished as they are intended for different purposes.
nodejs使用了过时的术语,因为它使用的是OpenSSL,它通过其前身SSLeay可以追溯到1990年代初,当时这种错误仍然很普遍。 但是,这实际上不是编程/开发问题,而更多地涉及crypto.SX和security.SX。请参阅我在https://security.stackexchange.com/questions/159282/can-openssl-decrypt-the-encrypted-signature-in-an-amazon-alexa-request#159289收集的一些链接。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。