扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
利用客户端对证书进行校验。
浏阳ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为成都创新互联的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:13518219792(备注:SSL证书合作)期待与您的合作!
1、服务端可以要求对客户端的证书进行校验,以更严格识别客户端的身份,限制客户端的访问。
2、要对客户端数字证书进行校验,客户端需要先有自己的证书。
本篇文章中,将描述如何使用go创建CA,并使用CA签署证书。在使用openssl创建证书时,遵循的步骤是 创建秘钥 创建CA 生成要颁发证书的秘钥 使用CA签发证书。这种步骤,那么我们现在就来尝试下。
首先,会从将从创建 CA 开始。 CA 会被用来签署其他证书
接下来需要对证书生成公钥和私钥
然后生成证书:
我们看到的证书内容是PEM编码后的,现在 caBytes 我们有了生成的证书,我们将其进行 PEM 编码以供以后使用:
证书的 x509.Certificate 与CA的 x509.Certificate 属性有稍微不同,需要进行一些修改
为该证书创建私钥和公钥:
有了上述的内容后,可以创建证书并用CA进行签名
要保存成证书格式需要做PEM编码
创建一个 ca.go 里面是创建ca和颁发证书的逻辑
如果需要使用的话,可以引用这些函数
panic: x509: unsupported public key type: rsa.PublicKey
这里是因为 x509.CreateCertificate 的参数 privatekey 需要传入引用变量,而传入的是一个普通变量
extendedKeyUsage :增强型密钥用法(参见"new_oids"字段):服务器身份验证、客户端身份验证、时间戳。
keyUsage : 密钥用法,防否认(nonRepudiation)、数字签名(digitalSignature)、密钥加密(keyEncipherment)。
文章来自
摘自 HTTPS 精读之 TLS 证书校验
这篇讲证书校验,写得很好。
1. 浏览器对服务器发送了一次请求,包含协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。
2. 服务器确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数(Server random)。
3. 浏览器确认数字证书有效,然后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给服务器。
4. 服务器使用自己的私钥,获取浏览器发来的随机数(即Premaster secret)。
5. 服务器和浏览器根据约定的加密方法,使用前面的三个随机数,生成"对话密钥"(session key),用来加密接下来的整个对话过程。
X.509 除了规范证书的内容之外,还规范了如何获取 CRL 以及 Certificate Chain 的验证算法。X.509 规范由国际电信联盟(ITU)定义, RFC 5280 只是定义了 X.509 的用法。
文章最开始,我们访问 时,浏览器并非只拿到了一个证书,而是一个证书链:
证书「*. 」的 Issuer 就是它的父节点「Go Daddy Secure Certificate Authority」。因为 UA(浏览器或操作系统)中会预先内置一些权威 CA 签发的根证书(Root Certificate)或中间证书(Intermediate Certificate),例如上面的 「Go Daddy Secure Certificate Authority」和 「Go Daddy Root Certificate Authority」。
Chain of trust - from wikipedia
当获得证书链之后,我们就可以很轻松的往上回溯到被 UA 信任的证书,虽然 UA 内置的可能是中间证书(Intermediate Certificate),但是如果一个 End-Entity 证书即使回溯到跟证书(Root Certificate)也没有在 UA 的受信列表中找到,那么这个站点就会被标记为不安全,例如 12306 的主页被标记为 “Not Secure",因为它的根证书不被信任。
我们上面所分析的校验方式属于单向校验,仅仅是客户端对服务端证书进行校验,这种方式无法避免中间人攻击(Man-In-the-Middle-Attack)。我们日常开发中用 Charles 抓包时, Charles 就扮演了一个中间人的角色 。抓包之前,我们需要在手机上安装一个 Charles 提供的根证书(Root Certificate),这个根证书加入到手机的 Trust Store 之后,它所签发的证书都会被 UA 认作可信。那么 Charles 就可以肆无忌惮地代表真正的 UA 与服务端建立连接,因为是单向认证,所以服务端并不会要求 Charles 提供证书。
但是实现双向校验的成本会比较高,因为 UA 端的证书管理比较复杂,例如证书的获取、有效期管理等等问题,而且需要用户手动添加到 Trust Store,这样也会降低用户体验。
既然双向认证的成本如此之高,那我们不妨利用 SSL Pinning 来解决证书认证被“劫持”的问题。
OkHttp 在 UA 端用一个类 Pin 来表示服务端的 TLS 证书。
证书的最终的表现形式是一个利用哈希算法(由 hashAlgorithm 字段表示)对证书公钥生成的哈希值(由 hash 字段表示),形式如下:
sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=
斜杠之前的字符串是 hashAlgorithm,之后的字符串是 hash 值。
TLS 证书的 Extension 字段中有一个 SAN,用于配置域名,例如 「*. 」的证书中配置了两个域名 —— *. 和 ,两者所匹配的域名是不同的,所以 Pin 用了一个 pattern 字段来表示两种模式。
我们知道,TLS 证书携带了端的公钥(Public Key),而这个公钥是 TLS 能够通过握手协商出“对称加密密钥”的关键,证书验证仅仅是为了证明当前证书确实是这个公钥的携带者,或者叫 Owner。所以我们只需要用一个 Pin 把服务端证书的公钥存储在本地,当得到证书链(Certificate Chain)之后,用 Pin 里的 hash 去匹配证书的公钥。
因为本地可以配置多个 Pin,因此 OkHttp 用了一个 CertificatePinner 来管理。
如此一来,在 TLS 握手过程中,校验证书那一步就可以保证服务端下发的证书是客户端想要的,从而避免了被中间人攻击(MIMA),因为本地没有存储中间人证书的 Pin,所以证书匹配会失败,握手也会失败,从而连接无法建立。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流