当前位置: 首页 > 科技观察

什么是HTTPS的证书信任链?不能自己发吗?

时间:2023-03-14 11:48:50 科技观察

互联网应用的网络通信一般都是通过HTTP,但是HTTP是明文传输的,容易泄露信息,所以大部分应用都会升级到HTTPS。HTTP的底层是通过TCP传输的。HTTPS是在TCP和HTTP之间增加了一层加密和认证的协议。该层称为SSL/TLS。为什么叫这个名字呢?因为最早的时候是SSL协议,后来发现漏洞,就改成了TLS协议,而且TLS协议也在不断升级,从1.1、1.2到现在的TLS1.3。不管叫SSL还是TLS,都是指这一层。该层实现加密、身份认证、防篡改等功能。加密很容易理解。就是将内容通过加密算法处理生成密文,然后另一端通过解密算法将密文处理成原始内容。但是只有加解密算法是不够的。一定要加上一些随机性,让它每次都不一样,这样就会有一个key。每次随机生成密钥,然后用这个密钥和加密算法进行通信过程。加密和解密。这个密钥是随机生成的,所以生成后只有一端可以告诉另一端。那么问题来了,如何安全地告诉另一端这个密钥呢?这就需要使用一种特殊的加密算法---非对称加密。这种加密算法的特殊之处在于它有两个密钥。用一个密钥加密的数据只能用另一个密钥解密。然后暴露一个密钥,留下另一个密钥,这样用剩下的密钥加密的数据别人可以解密数据,但是只有你才能解密用暴露的密钥加密的数据。暴露的密钥称为公钥,剩下的密钥称为私钥。这样,当有人要给你发一些信息的时候,就会用你暴露的公钥对信息进行加密,其他人无法解密,只有你才能解密。这保证了信息传输的安全性。比如上面提到的密钥传递问题,就可以通过这种公私钥的非对称加密机制来解决。可能有同学会问,既然基于公私钥的非对称加密机制可以保证安全,为什么还需要传递其他密钥呢?因为这种非对称加密太慢了,多传输几次信息还好,但是这种频繁加解密数据的效率就太低了。因此,一般只采用这种方式来传输会话密钥以保证安全性,之后再使用传输的会话密钥对数据进行加解密。如前所述,TLS层主要实现加密、身份认证、防篡改等功能。加密采用对称加密,使用的密钥通过基于公钥和私钥的非对称加密机制传输。身份验证呢?其实也是通过公私钥机制。前面说过,用公钥加密的内容只有用私钥才能解密,保证了信息的安全传输。另一方面,如果用私钥加密的数据可以用公钥解密,这不就证明信息是你传送的吗?因为只有你有私钥。因此,私钥的加密也称为签名,可用于身份认证。那么用私钥加密的是什么呢?一般是对传输的信息进行哈希运算,生成数据指纹,然后用私钥对数据指纹进行加密,即签名。这样,数据传输到另一端,用公钥取出数据指纹,然后对内容进行哈希,生成数据指纹,两者进行比对。如果它们相同,则意味着它们没有被篡改。这就是TLS层的第三个功能,防篡改,就是保证数据的完整性。至此,我们了解了HTTPS在HTTP基础上增加的加密、认证、防篡改等功能的实现原理。但是不知道同学们有没有发现这个漏洞。非对称加密算法是公开的。您可以生成公钥和私钥,其他人也可以。我如何保证我得到的公钥是你的?万一我拿到的公钥是别人的,我用它加密的数据不就被别人截获了吗?解决这个问题涉及到一个新的概念,数字证书:数字证书目前的问题是如何验证公钥是否属于某人。如果我有一个值得信赖的人说公钥属于那个人,我会相信的。凭着这样的信任去验证可以吗?也就是说,我信任的人有自己的公钥和私钥,他用自己的私钥对消息进行签名。我收到消息后,用他的公钥解密,我能解密消息,说明是他签名的。通过后,我相信我收到的公钥是可靠的。这没问题,但我如何确保我收到的受信任人的公钥是真实的呢?这是一个无限循环。在现实中,这样的死循环是绝对不会发生的。解决办法是操作系统内置了一组可信组织的公钥,这些组织签名的一定是对方的公钥。这个受信任的组织叫做CA(CertificationAuthority),电子认证机构,CA认证的公钥和相关信息称为数字证书。操作系统内置了所有可信CA的证书,即CA的公钥和相关信息,称为根证书。mac下在keychain中可以看到系统内置的所有根证书:当你打开一个https网站时,会下载该网站的证书,看是否被系统内置的CA根证书信任证书,如果是,则表示收到的网站公钥是可信的。证书是颁发给某个域名的,也就是说证书中的公钥属于这个域名。比如打开https://baidu.com,查看它的证书:你会看到这样一个三级证书。根证书是系统内置CA的证书。它信任一个中间证书,然后这个中间证书信任baidu.com的证书。(信任就是用自己的私钥签名)这个CA签发的根证书是系统内置的,是可信的,所以它也信任他信任的中间证书,从而信任中间证书trustedbaidu.com的证书,这是一个信任链。打开淘宝网,你也会看到这样一个三级证书链:为什么都是三级呢?因为在这种情况下,如果不能信任中间证书,根证书可以找到另一个中间证书。因为根证书是可信的,新的中间证书自然是可信的,但是如果根证书直接信任某个网站的证书,万一根证书被泄露,不能被信任,那么就没有人可以信任了.因此,三级证书会更加安全。就是这样一条信任链??:也就是说,你的网站要升级HTTPS,你得找CA去申请证书。一般的云计算平台都提供代理申请服务,但一年的费用相当昂贵。比如阿里云:如果我只是想测试HTTPS,我需要花那么多钱去CA申请证书吗?那不是必须的,我们可以自己创建一个CA根证书,然后用它来给自己颁发证书。这称为自签名证书:在测试自签名证书时,您可以使用openssl库自己创建CA根证书。第一步是使用genrsa命令生成私钥:opensslgenrsa-outca-key.pem-des1024过程中需要输入密码,用于保护私钥。然后使用req命令创建证书签名请求,输入域名及相关信息:opensslreq-new-keyca-key.pem-outca-csr.pem在这个过程中,需要输入一些信息,最重要的是域名信息,因为证书是为了证明公钥属于这个域名:然后使用x509命令生成根证书:opensslx509-req-inca-csr.pem-signkeyca-key.pem-outca-cert.pem此时根证书就创建好了,生成ca-key.pem、ca-csr.pem、ca-cert.pem三个文件,分别是私钥、证书签名请求和根证书。然后使用这个根证书为网站创建证书。同样三步:使用genrsa生成私钥:opensslgenrsa-outserver-key.pem1024然后使用req命令创建证书签名请求。opensslreq-new-keyserver-key.pem-outserver-csr.pem最重要??的是域名信息:最后一步是生成证书,但是这里需要指定生成的QA的根证书早些时候:opensslx509-req-CAca-cert.pem-CAkeyca-key.pem-CAcreateserial-inserver-csr.pem-outserver-cert.pem-extensionsv3_req这会产生server-key.pem、server-csr.pem,server-cert.pem这三个文件分别是网站的私钥、证书签名请求、证书。您可以使用私钥和证书创建https服务,我们使用nodejs创建:consthttps=require('https');constfs=require('fs');让options={key:fs.readFileSync('./server-key.pem'),cert:fs.readFileSync('./server-cert.pem')};https.createServer(options,function(req,res){res.write('你好https');res.end();}).listen(3000);然后访问浏览器,可以看到https服务返回的内容:chrome会被标记为不安全,我们点击查看证书:会看到只有一级www.ggg.com的证书是没有的还值得信赖。这是因为颁发给他的根证书还没有导入keychain。我们导入一下:importca-cert.pem,在keychain中可以找到guangguangguang.com的根证书,已经标记为自签名证书:再次访问该网站,会看到二级结构:但是还没有被信任,让我们信任自签名的根证书:再去网站上看,可以看到证书是信任的,因为签发它的根证书是信任的:但是网站还是会被标记为不安全。这是chrome的政策,不支持自签名证书。一般我们还是会去CA机构申请证书,但是在测试的时候,我们可以自己创建一个CA根证书,然后给自己颁发网站证书。总结一下,HTTPS就是在TCP和HTTP之间增加了一个SSL或TLS层,实现加密、身份认证、防篡改等功能。为了增加随机性,每次加密和解密都必须生成一个密钥,并且需要一个非对称加密的公私密钥机制来传输这个密钥。只有私钥才能解开公钥加密的内容,防止被盗。只有一个人拥有私钥,因此加密后的内容可用于身份认证,即签名。对内容进行哈希处理,然后用私钥对其进行签名,以验证完整性并防止篡改。但是如何保证得到的公钥一定是对方的,是一个复杂的问题。目前的解决方案是系统内置一些CA的根证书,然后这些CA证书为一些网站颁发证书。如果访问网站获得的证书是由这些CA机构颁发的,那么它们就是可信的。但在现实中,一般会有三级证书信任链来增加安全性。向CA申请证书,可以使用阿里云等云计算提供商的代理服务,但费用较高。如果要测试的话,可以使用openssl创建一个CA根证书,自己签名。这称为自签名证书。理解了这个证书信任链也就理解了HTTPS的核心。