由于hash的四个特性,接受者需要通过头、载体、密码一起来样子签名是正确的,使用他们进行哈希之后对签名进行比较,如果一致,则是有效的token。
也就是接受者必须要有同样的密码才能够有效的接受消息,而不是抛弃他。
这也就是数字签名和HMACs的原理。下面我们来实际看看。
验证SHA-256 JWT签名我们先看看上面的JWT,然后把签名部分和第二个点号删除,像下面我们看到的:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9现在你可以把字符串复制到这个网站,然后用secret作为密码,我们就重新得到了JWT 签名!
其实我们得到的是Base64编码版本的签名,因为=在最后,这和Base64Url相似,但是不会:
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ=等号在url里会被展示成%3D,有一点麻烦,但是这也解释了为什么我们在Url参数中传输时需要Base64Url。
网上并没有一些可用的Base64Url转换器,但是我们可以通过命令行完成这一工作。为了真正的验证HS256签名,这里有一个npm 包实现了Base64Url,也实现了Base64编解码。
base64url npm 包的使用让我们把经过base64编码的字符串转换一下,来准确验证签名,npm包使用如下:
mkdir quick-test && cd quick-test npm init npm install base64url node > const base64url = require(\'base64url\'); > base64url.fromBase64("TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ=") TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ最后我们转换成功了,和上面JWT 签名中的一模一样。
现在恭喜你,你真正了解并实践了HS256 JWT签名是怎么产生的,并可以用这些工具来一步步调试了。
为什么还需要有其他的签名算法上面是一个JWT签名的验证例子,HS256也仅仅是一个算法。但是还有很多其他的签名算法存在,比如最通常使用的RS256。
那么他们有什么不同呢?我们之前介绍了HS256算法,主要是让我们简单的理解MAC code。而且你可以在很多生成环境的应用中被使用。
但是通常来讲,我们一般使用RS256 这种算法替代HS256。因为接下来要讲的RS256 算法有很多优势。
HS256算法的不足加入秘钥很简单的话,HS256签名是可以被暴力破解的。这里可能涉及更多的关键技术。
基于哈希的签名算法相比其他类型会特别容易被暴力破解。
而且,实际上HS256的缺点是,产生JWT服务器和接受服务器之间需要提前约定一个密码,用于验证和认证。
不可行的秘钥更新这意味着如果我们想要更新密码,我们需要让是分布式的,而且需要让网络上所有需要的节点都保存,这并不容易,且会造成系统下线。
如果系统被不同的团队维护或是被第三方组织托管,这更加不可行了。
token的产生和验证方式一样归结起来,产生JWTs 和验证方式是一样的,也就是说使用HS256算法,网络上有密码的节点都可以产生和验证token。
这也加大了密码被盗的风险,因为每个需要信息的节点都需要密码。而且不是所有的应用都有同样的安全等级,攻击者可以容易的获取到密码。
一种可以避免风险的方式是,每一个应用创建一个共享的密码。但是我们将要学到一个新的签名算法,它解决了所有的问题,这也是现在JWT的默认签名算法:RS256。
RS256 JWT签名算法使用RS256算法,我们也要像之前一样产生一个MAC 码,目的是创建签名并且验证特定的JWT是有效的。
但是现在我们要把产生token和验证token分开,只有验证服务可以产生token,而应用服务器来验证token。
我们这么做的方式是,我们产生2个秘钥,而不是一个秘钥:
只有认证服务器有一个私钥,用来给JWTs加签
私钥可以用来加签,但是不可用来验签
应用服务器有一个公钥,用来验证JWTs
公钥可以用来验签,但是不可以加签
公钥可以不必保密,因为攻击者得到它也不能够伪造签名
RSA加密技术介绍RS256签名用来一组特定的秘钥,被称为RSA秘钥。RSA是一种加解密算法,一个秘钥用于加密,一个秘钥用于解密。
我们要知道RSA不是哈希算法,因为从定义上看,加密后的信息是要被还原,得到最初加密前的数据。