Hash是用来算原文的“摘要”(digest)。
而签名是签名一方(通常是服务器)用自己的私钥签在“摘要”上。(Signing with the private key on the digest)
“摘要”所有人都能算,只要知道原文,因为hash中并未使用任何原文之外的保密信息。
验证签名的是否有效,通常是先算“摘要”, 再以摘要和公钥作为输入,调用验证算法来验证(verify)签名是否有效。而不是先验证签名(即题主所说的公钥解密),再算摘要来比对。
再强调一下,Hash是公开的,原文是公开的,所以不需要解密。
因此,数字签名的安全性基于:
1. Hash算法的抗碰撞性(collision-resistance)
即很难找到两个不同的原文 m0, m1,让它们的摘要Hash(m0) = Hash(m1)。
例:SHA-3现在比MD5,SHA-2都要安全,很难碰撞。
2. 伪造数字签名的难度
即对于“新鲜”的原文摘要hash(m*),很难算出一个在它上面的合法签名,除非掌握服务器私钥。
所谓“新鲜”是指这个摘要hash(m*)没有被服务器签名过。(签过的原文-签名对没意义,本来就是服务器签的)
所以,理论上来说,有下面两种典型的攻击:
1. 找与“旧”原文摘要值相同的原文,等价于攻击hash算法,找出碰撞。如使用题主提到的用彩虹表或者其他的手段。
2. 直接伪造数字签名。
其实,达到伪造任意签名,就可以说完全攻破了这个数字签名系统……
回到https, 如果使用的cipher suite是类似TLS_DHE_RSA_WITH_AES_256_CBC_SHA256的, 签名通常出现在server key exchange这条消息中。数字签名使用的算法是RSA,对象是客户端发送的随机数、服务器端发送的随机数、服务器端的密钥交换内容,产生摘要所用的hash函数是SHA256。