Skip to content

Latest commit

 

History

History
68 lines (43 loc) · 5 KB

File metadata and controls

68 lines (43 loc) · 5 KB

身份认证

TLS握手的第三步中,用到了数字证书中的公钥,为什么会出现数字证书呢?先假设不采用数字证书,在我们建立安全通信的过程中会面临哪些风险。

无数字证书场景

我们假设这样一种不使用证书进行TLS建立连接的场景;

TLS/SSL握手的第一步中,客户端(Client)发送明文消息client_hello给服务端(Server)。

黑客在服务端收到client_hello之前,截获了这个消息,发送给客户端伪造的协商信息(server_hello)。

客户端收到黑客发来的伪造的协商信息,如果不验证证书,继续进行后续的秘钥协商过程,流程也是可以走完。

后续的通信依然使用客户端和服务端协商的秘钥加密通信,但是问题显而易见,我们并没有和最初预想的服务端建立连接,而是和黑客的服务器建立连接。

黑客可以冒充客户端再和真正的服务端建立连接,黑客作为中间人,监听转发通信。

产生这个问题的根源在于,大家都可以生成公私钥对,而我们无法确认这对公私钥到底是属于谁,这个时候就需要一种方法可以证明一对公私钥的所有者是谁。

数字证书

数字证书是一个经数字证书认证机构CA(Certificate Authority)认证签名的文件,包含拥有者的公钥以及相关的身份信息。用户想要获得证书,应该先向CA提出申请,CA验证申请者的身份后,为其分配一个公钥与其身份信息绑定,为该信息信息进行签名,作为证书的一部分,然后把整个证书发送给申请者。

当需要鉴别证书真伪时,只需要用CA的公钥对证书上的签名进行验证,验证通过则证书有效。

证书结构

证书的结构一般遵循X.509规范,结构如下所示:

Alt text

字段含义

  • 版本: 使用X.509的版本,目前普遍使用v3版本;
  • 序列号:CA分配给证书的一个整数,作为证书的唯一标识;
  • 签名算法:CA颁发证书使用的签名算法;
  • 有效期:包含证书的起止日期;
  • 主体名:该证书拥有者的名称,如果与颁发者相同则说明证书是一个自签名证书;
  • 公钥信息: 对外公开的公钥以及公钥算法;
  • 扩展信息:通常包含证书的用法,证书吊销列表(Certificate Revocation List,CRL)的发布地址等可选字段;
  • 签名:颁发者用私钥对证书信息的签名;

可以通过查看浏览器查看网站证书来方便理解: Alt text

证书类型

数字证书根据不同的用途,又有不同的分类:

  • 自签名证书:自签名证书又称根证书,是自己发给自己的证书,证书的颁发者和主体同名,也就意味着证书中的公钥和用于验证证书的密钥是相同的。这种自签名证书通常不会被广泛信任,使用时可能会遇到电脑软件的安全警告。
  • 本地证书:CA颁发给申请者的证书;
  • 设备本地:设备根据CA证书给自己颁发的证书,证书中的颁发者名称是CA服务器的名称。

证书格式

数字证书在计算机中的表示方法也有不同,但是都是可以相互转换的:

  • PKCS#12#12是标准号,常见后缀是.P12,可包含私钥也可不包含私钥;
  • DER:二进制格式保存证书,不包含私钥,常见后缀.DER;
  • PEM:以ASCII格式保存的证书,可包含私钥,也可不包含私钥,常见后缀.PEM

简单应用

假设一个简单的场景,A需要通过银行,转给B转一笔钱,而使用之前的密码学知识就可以保证这个过程的安全可靠。

可以通过对称加密的方式,生成公私钥对,其中公钥a可以公开,作为银行账户,私钥b作为账户密码,不予公开。

当A向B转100元时,可以在计算机中向银行发送这样一条请求<form:A, to:B, value: 100>表示A向B转账100元,但是如果整个过程不加验证,被黑客发现这个漏洞后就可以不断的重复这个过程把A的账户转空。

为了表示这个交易确实是由A发出的,所以可以增加A的签名,用A的私钥a对这个请求签名。整个请求就成了{<form:A, to:B, value: 100>, signature: foo},这样银行收到这笔交易后,就可以用A的公钥,也就是地址A对交易进行验证,判断是不是由A发出。

但是由于A太富有,转账成了{<form:A, to:B, value: 1000000000.002>, signature: bar}, 交易请求<form:A, to:B, value: 1000000000.002>太大,签名算法对大量数据的输入签名太慢,这个时候,就可以采用摘要算法,减少计算签名输入的长度,比如采用哈希算法hash(<form:A, to:B, value: 1000000000.002>) = baz 对baz签名即可,当银行收到这笔交易时,同样先对交易计算hash,在验证签名即可。