数字签名是什么

数字签名是一种数字技术,用于验证和维护数据的完整性

数字签名是经过一些加密算法将消息或文件与公钥(假如对错对称加密就有公钥不然就不用)绑定在一起,并生成仅有的签名。

数字签名的工作原理

数字签名的中心在于加密算法。最常用的对错对称加密算法,它将原文经过特定HASH函数得到的摘要信息用发送者的私钥加密,与原文一起传送给接收者。接收者只需用发送者的公钥才干解密被加密的摘要信息,然后用HASH函数对收到的原文提炼出一个摘要信息,与解密得到的摘要进行比照。

数字签名也能够运用哈希函数对文件或消息的散列值进行加密,保证消息不会被篡改。(也有人以为摘要算法不能逆向也便是解密所以不是加密算法,在此不做评论)

数字签名能够与数字证书结合运用,以证明密钥的归属和真实性,然后维护数字签名进程不被破坏。

数字签名的运用

JWT

JWT通常由三个部分组成:头部(Header)、载荷(Payload)和签名(Signature),以点号分隔。第一部分是头部,第二部分是载荷,第三部分是签名。以下是一个包含了用户ID、用户名和时刻戳的JWT实例,格式为 Header.Payload.Signature

// 为方便展示,在'.'处作了换行处理,能够更好地看清楚结构
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

HeaderPayload都是经过 Base64URL 编码的,所以每个人都能经过解码得到本来的信息,固不应该在里边存一些敏感信息。

数字签名为什么可以防篡改

Signature便是咱们要评论的数字签名了!Signature 部分是对前两部分的签名,防止数据篡改。首要,需求指定一个密钥(secret)。这个密钥只需服务器才知道,不能泄露给用户。然后,运用 Header 里边指定的签名算法(默认是 HMAC SHA256),按照下面的公式发生签名。Signature = HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

HMAC算法 是一种依据密钥的报文完整性的验证办法。HMAC算法运用哈希运算,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。其安全性是建立在Hash加密算法基础上的。

由于Signature是依据HeaderPayload以及服务器的secret来生成的,由于secret只需服务器知道,所以只需HeaderPayloadSignature其中一个被篡改了,那么后续验证的时分就不能经过。一起只需知道secret才干发生与HeaderPayload配对的Signature,所以也能确认该 Token 是否是该服务器所颁布的。

验证进程是用服务器的密钥经过相同的算法计算出一个新的 Signature 然后和旧的 Signature 进行比较,只需被篡改那么 Signature就会跟着改变,所以经过比较, Signature 相同的话则证明没有被篡改,不然则以为被篡改了。

CA 证书

其实便是这个 CA 证书的数字签名为什么能够防篡改,困扰了我良久,所以才去略微深化了解了一下然后写下了这篇博客。便是为了这点醋,我才包的这顿饺子~

之前学习 https 的时分,看了各大论坛的帖子发现有挺多帖子对于 CA 证书是怎么做放篡改的讲的不太对或者讲的不太清晰,所以这个问题困扰了我挺久。以下是随意找的一些帖子(对事不对人):

例1:

数字签名为什么可以防篡改

例2:

数字签名为什么可以防篡改

例3:

数字签名为什么可以防篡改

(例1和例2是随意在上面搜到的相关文章,例3是newbing的回答)

先回顾一下数字证书验证的大概进程:

CA 签发证书的进程:

  • 首要 CA 会把持有者的公钥、用处、颁布者、有效时刻等信息打成一个包,然后对这些信息进行 Hash 计算,得到一个 Hash 值;
  • 然后 CA 会运用自己的私钥将该 Hash 值加密,生成 Certificate Signature,也便是 CA 对证书做了签名;
  • 最终将 Certificate Signature 添加在文件证书上,形成数字证书;

客户端校验服务端的数字证书的进程:

  • 首要客户端会运用相同的 Hash 算法获取该证书的 Hash 值 H1;
  • 浏览器收到证书后能够运用 CA 的公钥解密 Certificate Signature 内容,得到一个 Hash 值 H2 ;
  • 最终比较 H1 和 H2,假如值相同,则为可信赖的证书,不然则以为证书不可信。

中心问题在于验证服务器发来的数字证书的数字签名时所用到的公钥是哪里来的。

假设有那么一个场景:

客户端A 和 服务器A 的通讯进程中,私钥是Secret_RSA_A,公钥是Secret_PUB_A。服务器A 将自己的证书CA发给客户端A的进程中被 中间人B 给截获了,中间人B 用自己的公钥Secret_PUB_B 替换了 服务器A 发给 客户端A 的CA证书的公钥Secret_PUB_A,并且用和公钥Secret_PUB_B 配对的私钥Secret_RSA_B 对替换公钥后的CA证书的公钥、用处、颁布者、有效时刻等信息生成的新HASH 进行加密,生成新的 Certificate Signature 并把原本证书上的 Certificate Signature 替换掉。但客户端A 对这并不知情。然后在后续客户端对该 CA证书验证的进程中,假如运用的是证书上的公钥,那么计算出来的 H1 和 H2 就会相同,也便是以为证书是可信的。(实际上加密运用的是CA私钥而不是服务器私钥所以中间人伪造不了一对新的公私钥,但是假如运用服务器发送过来的公钥去验证的话那么就有或许被伪造)

所以更加安全的做法应该是不运用传过来的证书上面的公钥(证书上的公钥是服务器持有者的公钥而不是CA公钥),而是运用预置在操作系统里边的公钥,由于证书加密是用CA私钥加密的而不是用服务器持有者的私钥进行加密的,传服务器持有者的公钥过来是为了和客户端洽谈然后生成后续对称加密通讯需求用到的秘钥。这也是我之前看到的一些文章没有提到的(如上面的图1/2/3所示,没有针对原作者的意思),容易让人困惑。服务器发送过来的证书中的公钥是服务器的公钥而不是能够解密数字签名的公钥(数字签名的公钥也便是和CA证书配对的公钥)。 通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后能够运用操作系统内置的 CA 的公钥解密 Certificate Signature 内容。这行验证进程中存在一个证书信赖链的问题。客户端收到服务器发送过来的CA证书后,浏览器开始查找操作系统中已内置的受信赖的证书发布组织CA,与服务器发来的证书中的颁布者CA比对,用于校验证书是否为合法组织颁布,假如找不到,浏览器就会报错,阐明服务器发来的证书是不可信赖的。假如找到,那么浏览器就会从操作系统中取出 颁布者CA 的公钥,然后对服务器发来的证书里边的签名进行解密。

综上,数字签名只能验证数据的完整性(JWT 只需服务端能够验证他的身份,由于它有解密需求的密钥,而客户端是验证不了的),而验证身份需求的是数字证书。

最终

以上是自己在学习数字签名原理的进程中的一些感悟,由于个人的局限性,所以或许存在疏忽的情况,欢迎我们批评指正。