可以从命令行编译和执行该程序(请注意 -lssl 和 -lcrypto 中的小写字母 L):
gcc -o client client.c -lssl -lcrypto
该程序尝试打开与网站 www.google.com 的安全连接 。在与 Google Web 服务器的 TLS 握手过程中,client 程序会收到一个或多个数字证书,该程序会尝试对其进行验证(但在我的系统上失败了) 。尽管如此,client 程序仍继续通过安全通道获取 Google 主页 。该程序取决于前面提到的安全工件,尽管在上述代码中只着重突出了数字证书 。但其它工件仍在幕后发挥作用,稍后将对它们进行详细说明 。
通常,打开 HTTP(非安全)通道的 C 或 C++ 的客户端程序将使用诸如文件描述符或网络套接字之类的结构,它们是两个进程(例如,这个 client 程序和 Google Web 服务器)之间连接的端点 。另一方面,文件描述符是一个非负整数值,用于在程序中标识该程序打开的任何文件类的结构 。这样的程序还将使用一种结构来指定有关 Web 服务器地址的详细信息 。
这些相对较低级别的结构不会出现在客户端程序中,因为 OpenSSL 库会将套接字基础设施和地址规范等封装在更高层面的安全结构中 。其结果是一个简单的 API 。下面首先看一下 client 程序示例中的安全性详细信息 。
- 该程序首先加载相关的 OpenSSL 库,我的函数 init_ssl 中对 OpenSSL 进行了两次调用:SSL_load_error_strings();
SSL_library_init(); - 下一个初始化步骤尝试获取安全上下文,这是建立和维护通往 Web 服务器的安全通道所需的信息框架 。如对 OpenSSL 库函数的调用所示,在示例中使用了 TLS 1.2:const SSL_METHOD* method = TLSv1_2_client_method(); /* TLS 1.2 */
如果调用成功,则将 method 指针被传递给库函数,该函数创建类型为 SSL_CTX 的上下文:SSL_CTX* ctx = SSL_CTX_new(method);
client 程序会检查每个关键的库调用的错误,如果其中一个调用失败,则程序终止 。 - 现在还有另外两个 OpenSSL 工件也在发挥作用:SSL 类型的安全会话,从头到尾管理安全连接;以及类型为 BIO( 基本输入/输出(Basic Input/Output))的安全流,用于与 Web 服务器进行通信 。BIO 流是通过以下调用生成的:
BIO* bio = BIO_new_ssl_connect(ctx);
请注意,这个最重要的上下文是其参数 。BIO 类型是 C 语言中 FILE 类型的 OpenSSL 封装器 。此封装器可保护 client 程序与 Google 的网络服务器之间的输入和输出流的安全 。 - 有了 SSL_CTX 和 BIO,然后程序在 SSL 会话中将它们组合在一起 。三个库调用可以完成工作:
BIO_get_ssl(bio, &ssl); /* 会话 */
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* 鲁棒性 */
BIO_set_conn_hostname(bio, name); /* 准备连接 */
安全连接本身是通过以下调用建立的:
BIO_do_connect(bio);
如果最后一个调用不成功,则 client 程序终止;否则,该连接已准备就绪,可以支持 client 程序与 Google Web 服务器之间的机密对话 。
为什么验证 Google 证书的尝试会失败?典型的 OpenSSL 安装目录为 /etc/ssl/certs,其中包含 ca-certificates.crt 文件 。该目录和文件包含着 OpenSSL 自带的数字证书,以此构成 信任库(truststore) 。可以根据需要更新信任库,尤其是可以包括新信任的证书,并删除不再受信任的证书 。
client 程序从 Google Web 服务器收到了三个证书,但是我的计算机上的 OpenSSL 信任库并不包含完全匹配的证书 。如目前所写,client 程序不会通过例如验证 Google 证书上的数字签名(一个用来证明该证书的签名)来解决此问题 。如果该签名是受信任的,则包含该签名的证书也应受信任 。尽管如此,client 程序仍继续获取页面,然后打印出 Google 的主页 。下一节将更详细地介绍这些 。
客户端程序中隐藏的安全性让我们从客户端示例中可见的安全工件(数字证书)开始,然后考虑其他安全工件如何与之相关 。数字证书的主要格式标准是 X509,生产级的证书由诸如 Verisign 的 证书颁发机构(Certificate Authority)(CA)颁发 。
数字证书中包含各种信息(例如,激活日期和失效日期以及所有者的域名),也包括发行者的身份和数字签名(这是加密过的加密哈希值) 。证书还具有未加密的哈希值,用作其标识指纹 。
推荐阅读
- 入户鞋柜高度多少合适,入门鞋柜有没有必要做到顶
- Redis从入门到精通,至少要看看这篇
- 内存|DIY从入门到放弃:不懂XMP买高频内存就是白花钱
- 最简单的python爬虫案例,适合入门学习
- 程序员和IT人都应该懂的知识:HTTP入门图解
- 防火墙入门基础之登录Web配置界面,看完小白也可配置,超简单
- Github入门使用指南
- 瑜伽入门体式有哪些?
- java日志logback入门
- XMLHttpRequest使用入门