用密码学原理阐述HTTPS为什么安全
发布于 5 年前 作者 zhanzhenzhen 4021 次浏览 来自 分享

HTTPS之所以安全,是因为它构建于密码学之上。更具体地,它基于密码学中的三大基石:对称加密、非对称加密、哈希(hash)。了解其中的原理,至少有助于程序员树立对HTTPS的信心,要不然,你会总感到HTTPS说得很安全,但为啥安全,因为不了解,所以不放心。

对称加密

我们要对一段文字加密,过程可能是这样的:

明文 "Hello World"      算法
                     ------->   密文 "gsHgw832iSI"
密钥 "111222"

解密过程是这样的:

密文 "gsHgw832iSI"      算法
                     ------->   明文 "Hello World"
密钥 "111222"

这里的关键是,加密和解密,密钥相同,算法也相同(互逆),所以称之为“对称”。

最安全的对称加密算法:一次性板

有没有绝对安全的加密算法呢?有!

如果明文中的每一个字符,都通过密钥中的一个字符,映射成密文中的一个字符,密钥的长度等于文字的长度,且密钥只用一次,那么这种密钥被形象地称作“一次性板(one-time pad)”。

由于一次性板的长度等于明文和密文的长度,而且用完就要放弃,所以密钥不可能产生重复,因而相当安全,即使在理论上也不可能破解。试想一下,即使你猜对了密钥,得出了明文,但是也有可能,密钥是另一个,能够得出另一种明文,你怎能确定明文是前一个而不是后一个呢?事实上,在密文确定的情况下,任意指定一个明文,都有相应的密钥和它对应!所以试图破解它完全没有意义。

但是,我们通常需要加密的信息量都很大,如果要加密1GB的文件,密钥也得有1GB,那传输和保存密钥就太过恐怖。所以,一次性板不现实。

妥协:密钥长度固定的对称加密

对于密钥长度小于明文和密文长度的算法,理论上是可以破解的,因为在密文确定的情况下,并不是任意指定一个明文,都有相应的密钥和它对应(因为同一个密钥要加密不同的块,如果明文不是原文,则不可能求出一个密钥,使之能够适用于所有的块)。

但如果密钥长度足够,可近似认为不可破解。专家们认为,112位密钥已足够安全,因为要破解它所花的时间是天文数字。为了凑整,通常使用128位。AES算法是当今对称加密算法的标准。

大问题:密钥如何发送

A要向B发送一份机密文件,他一定会用密钥K来加密。他先把密文发给了B,这没有问题。但问题是,如何把密钥K告诉B,以便他解密?

如果直接发送密钥,那么任何人都可以窥知该密钥。只要该人曾截获过他发送的文件,就可以解密。

把密钥K再用一个新密钥加密,行吗?当然不行,因为,你如何传输这个新密钥?

这时A终于想出了一个办法,把密钥保存在USB盘里,亲手交给B。这是个好方法,确实“解决”了密钥发送的问题。但是仔细想想,他完全可以把文件直接放在USB盘里给B,又何必加密,弄得那么麻烦?不过最重要的是,如果在当今世界,传输信息居然还要见面,这岂不是回到了原始时代了吗?

这是个著名的问题:密钥交换(key exchange)问题。看来,没有一个办法可以解决这个问题。

直到,出现了非对称加密算法。

非对称加密

如果有一种算法,用于加密和解密的密钥是不同的(即:非对称),它能否解决密钥交换问题?

答案是:可以。B可以先把加密密钥发送给A,然后A对文件加密,接着A把密文发送给B,最后B用解密密钥来解密。整个过程,极其完美。因为加密密钥只能用来加密,所以即使该密钥被截获,也并不会导致文件被解密。于是我们就可以把加密密钥叫做“公钥”,把解密密钥叫做“私钥”。

但是仔细想想,这种机制对算法有着极高的要求:

  • 公钥和私钥必须通过确定的函数一一对应。
  • 但通过公钥直接求得私钥必须极难。

利用质数的算法,就是最简单的满足此要求的算法。它基于这样的数学原理:给出两个很大的质数,要求出它们的乘积很容易;但知道它们的乘积,要求出是哪两个质数相乘却极难(人类并没有找到快速的办法,只能一个个试)。举个例子,让计算机分解一下这个大合数:

15226050279225333605356183781326374297180681149613
80688657908494580122963258952897654000350692006139
=
37975227936943673922808872755445627854565536638199
×
40094690950920881030683735292761468389214899724061

通过质数求得乘积,任何计算机都可以在不到1微秒的时间内完成,但分解的话就得花很长时间。这还只是330位(十进制100位)的合数,RSA算法中实际应用的大合数高达2048位,分解的话几百亿年也完不成,所以非常安全。

试想一下,如果我们把两个大质数当作私钥,把它们的乘积当作公钥,只要有相应的加密和解密算法,就可以解决密钥交换问题。RSA的原理即是基于这一理论,具体实现稍微复杂些(公钥和私钥并不是直接通过这个方法得出,要经过一些变换,这里就不做讨论了)。

但是,这样的密钥交换真的一点问题也没有了吗?不!

数字签名

有一个极其重要的问题还未解决,即:谁能证明向A发送公钥的是B?如果随便哪个人都能冒充B,那么A就很容易上当了。A可能会用别人的公钥来加密,然后发送给B,发送的过程中又被别人截获。结果,B不能读取这个文件,不怀好意的人倒解密了这个文件。

看来,有必要模仿在生活中有着悠久历史的“签名”。

我们先看看传统签名的特点:

  • 只有签名者自己才能签出这个名字(图案)。
  • 外人虽无法模仿,但可以检查。模仿很难,但检查很容易。

您是否由此联想到了非对称加密?“正向容易、反向很难”不正是非对称加密的特点吗?传统的非对称加密是“公钥加密、私钥解密”。如果反一反,变成“私钥加密、公钥解密”,我们惊讶地发现这简直是天作之合:

  • 只有签名者自己可以通过用私钥加密信息来对该信息进行签名。
  • 外人可以通过用公钥解密来检查,如解密成功,即证实,否则即证伪。

这就是数字签名。

到了这里,只剩最后一个环节了,那就是:谁来证明该公钥代表B?看来,只有引入权威机构,告诉大家每个公钥代表的分别是谁,检查才有意义。

这是密码学中最复杂的难题,促使人们提出了“数字证书”和“公钥基础设施”的光辉思想。

数字证书、公钥基础设施

这样的权威机构称为CA (Certificate Authority,证书机构),它们的职责就是颁发证书,证明每个公钥代表的分别是谁。这里的“谁”可以是个人,可以是组织,也可以是另一个CA。这样,就可以组成一个庞大的“公钥基础设施(PKI)”。

              根CA
               |
      -------------------
      |                 |
    二级CA            二级CA
      |                 |
  ----------           个人
  |        |
三级CA   三级CA
           |
       ----------
       |        |
      个人     个人

试想,我们让每个证书含有如下内容:

  • 主体(颁发者的公钥和被颁发者的公钥)
  • 颁发者用私钥对主体所做的数字签名

这样,只要根CA确定,一个庞大的信任链就建成了。

根CA,所对应的证书称为根证书,是操作系统生产商人为设定的。Windows、macOS、Linux中,默认信任的根CA有几十个至数百个不等。

我们开发软件的时候,也可以自己建一个根CA,方法是让颁发者的公钥和被颁发者的公钥相同,这样的证书(即“自签名证书”)会被操作系统识别为根证书,然后,你需要让操作系统“信任该证书”。但注意,绝对不要把这种证书发送给陌生人,然后叫他点击信任该证书,因为这对别人有风险,毕竟我们不能强迫别人信任。

HTTPS

最后我们终于可以回到HTTPS了。要了解HTTPS的详情对程序员来说意义不大,重要的是,通过以上章节,我们终于可以相信,HTTPS的安全性是有技术保障的。人们可以确信,访问的网站的确是这个网站,而不是黑客冒充的。也可以确信,传输的所有数据都经过加密,外人无法读取。

CA如何给网站颁发证书?首先你在自己的电脑中生成私钥和公钥,把公钥发给CA,然后CA验证你是否是网站的所有者,有数种方法:

  • 发一封邮件给webmaster@该域名.compostmaster@该域名.com,如果你能收到,就证明你是网站的所有者。
  • 让你在网站的某个目录加入一个文件,如果你能,就证明你是网站的所有者。
  • 让你在域名的DNS中加入一个项目,如果你能,就证明你是网站的所有者。

验证后,CA会把证书发给你。

性能优化

非对称加密比对称加密慢100倍(软件实现)或1000倍(硬件实现)。如果纯粹使用上述加密、解密和签名手段,性能是很差的。这时要用到密码学中的另一个工具:哈希(hash)。

Hash有很多同义词:指纹、摘要、杂凑、校验和、散列,指的是一种数学方法,用很少的信息来使它“等价于”大量信息。这听起来有些不可思议,但想想,指纹不正是具有这个特征吗?通过一个指纹,可以确定一个人;反过来,通过一个人,也可以确定他的指纹。其妙处在于,指纹所含的信息量远比一个人所含的信息量要少(但仍然是天文数字,所以仍然不会重复)。

例如,我们计算这段文字的hash:

A hash function is any function that can be used to map data of arbitrary size to data of fixed size. The values returned by a hash function are called hash values, hash codes, digests, or simply hashes. One use is a data structure called a hash table, widely used in computer software for rapid data lookup. Hash functions accelerate table or database lookup by detecting duplicated records in a large file. An example is finding similar stretches in DNA sequences. They are also useful in cryptography. A cryptographic hash function allows one to easily verify that some input data maps to a given hash value, but if the input data is unknown, it is deliberately difficult to reconstruct it (or equivalent alternatives) by knowing the stored hash value. This is used for assuring integrity of transmitted data, and is the building block for HMACs, which provide message authentication.

采用SHA-256哈希算法,得出的hash是:

4da07b60cb90742026d7fd9ece673bfad677422e8261c1cc29ff00d0d6be4b7a

无论输入的数据有多大,哪怕100GB,其SHA-256值也始终是256位(十六进制64位)。Hash算法的速度比非对称加密快得多,所以在实际应用中,都是先把信息hash一下,再给hash签名,而不是给整个信息签名。这样做大大加快了速度,又不失安全。

回到顶部