没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
使用 OpenSSL API 进行安全编程
创建基本的安全连接和非安全连接
Kenneth Ballard (kenneth.ballard@ptk.org), 自由程序员
简介:学习如何使用 OpenSSL —— 用于安全通信的最著名的开放库 —— 的
API 有些强人所难,因为其文档并不完全。您可以通过本文中的提示补充这方
面的知识,并驾驭该 API。在建立基本的连接之后,就可以查看如何使用
OpenSSL 的 BIO 库来建立安全连接和非安全连接。与此同时,您还会学到一些
关于错误检测的知识。
OpenSSL API 的文档有些含糊不清。因为还没有多少关于 OpenSSL 使用的教程,
所以对初学者来说,在应用程序中使用它可能会有一些困难。那么怎样才能使
用 OpenSSL 实现一个基本的安全连接呢? 本教程将帮助您解决这个问题。
学习如何实现 OpenSSL 的困难部分在于其文档的不完全。不完全的 API 文档通
常会妨碍开发人员使用该 API,而这通常意味着它注定要失败。但 OpenSSL 仍
然很活跃,而且正逐渐变得强大。这是为什么?
OpenSSL 是用于安全通信的最著名的开放库。在 google 中搜索“SSL library”得
到的返回结果中, 列表最上方就是 OpenSSL。它诞生于 1998 年,源自 Eric
Young 和 Tim Hudson 开发的 SSLeay 库。其他 SSL 工具包包括遵循 GNU
General Public License 发行的 GNU TLS,以及 Mozilla Network Security
Services(NSS)(请参阅本文后面的 参考资料 ,以获得 其他信息)。
那么,是什么使得 OpenSSL 比 GNU TLS、Mozilla NSS 或其他所有的库都优越
呢?许可是一方面因素 (请参阅 参考资料)。此外,GNS TLS(迄今为止)只
支持 TLS v1.0 和 SSL v3.0 协议,仅此而已。
Mozilla NSS 的发行既遵循 Mozilla Public License 又遵循 GNU GPL,它允许开
发人员进行选择。 不过,Mozilla NSS 比 OpenSSL 大,并且需要其他外部库来
对库进行编译,而 OpenSSL 是完全 自包含的。与 OpenSSL 相同,大部分 NSS
API 也没有文档资料。Mozilla NSS 获得了 PKCS #11 支持,该支持可以用于诸
如智能卡这样的加密标志。OpenSSL 就不具备这一支持。
先决条件
要充分理解并利用本文,您应该:
精通 C 编程。
熟悉 Internet 通信和支持 Internet 的应用程序的编写。
并不绝对要求您熟悉 SSL ,因为稍后将给出对 SLL 的简短说明;不过,如果您
希望得到详细论述 SSL 的文章的链接,请参阅 参考资料部分。拥有密码学方面
的知识固然好,但这 并不是必需的。
什么是 SSL?
SSL 是一个缩写,代表的是 Secure Sockets Layer。它是支持在 Internet 上
进行安全通信的标准,并且将数据密码术集成到了协议之中。数据在离开您的
计算机之前就已经被加密,然后只有 到达它预定的目标后才被解密。证书和密
码学算法支持了这一切的运转,使用 OpenSSL,您将有机会切身体会它们。
理论上,如果加密的数据在到达目标之前被截取或窃听,那些数据是不可
能被破解的。不过, 由于计算机的变化一年比一年快,而且密码翻译方法有了
新的发展,因此,SSL 中使用的加密协议被破解的可能性也在增大。
可 以 将 SSL 和 安 全 连 接 用 于 Internet 上 任 何 类 型 的 协 议 , 不 管 是
HTTP、POP3,还是 FTP。还可以用 SSL 来保护 Telnet 会话。虽然可以用 SSL
保护任何连接,但是不必对每一类连接都使用 SSL。 如果连接传输敏感信息,
则应使用 SSL。
什么是 OpenSSL?
OpenSSL 不仅仅是 SSL。它可以实现消息摘要、文件的加密和解密、数字
证书、数字签名 和随机数字。关于 OpenSSL 库的内容非常多,远不是一篇文章
可以容纳的。
OpenSSL 不只是 API,它还是一个命令行工具。命令行工具可以完成与 API
同样的工作, 而且更进一步,可以测试 SSL 服务器和客户机。它还让开发人员
对 OpenSSL 的能力有一个 认识。要获得关于如何使用 OpenSSL 命令行工具的
资料,请参阅 参考资料部分。
您需要什么
首先需要的是最新版本的 OpenSSL。查阅参考资料部分,以确定从哪里可
以获得最新的可以自己编译的源代码, 或者最新版本的二进制文件(如果您不
希望花费时间来编译的话)。不过,为了安全起见, 我建议您下载最新的源代
码并自己编译它。二进制版本通常是由第三方而不是由 OpenSSL 的开发人员来
编译和发行的。
一些 Linux 的发行版本附带了 OpenSSL 的二进制版本,对于学习如何使用
OpenSSL 库来说,这足够了;不过, 如果您打算去做一些实际的事情,那么一
定要得到最新的版本,并保持该版本一直是最新的。
对于以 RPM 形式安装的 Linux 发行版本(Red Hat、Mandrake 等),建议
您通过从发行版本制造商那里获得 RPM 程序包来更新您的 OpenSSL 发行版本。
出于安全方面的原因,建议您使用 最新版本的发行版本。如果您的发行版本不
能使用最新版本的 OpenSSL,那么建议您只覆盖库文件,不要覆盖 可执行文件。
OpenSSL 附带的 FAQ 文档中包含了有关这方面的细节。
还要注意的是,OpenSSL 并没有在所有的平台上都获得官方支持。虽然制
造商已经尽力使其能够跨平台兼容, 但仍然存在 OpenSSL 不能用于您的计算机
和/或 操作系统的可能。请参阅 OpenSSL 的 Web 站点( 参考资料 中 的链接),
以获得关于哪些平台可以得到支持的信息。
如果想使用 OpenSSL 来生成证书请求和数字证书,那么必须创建一个配置
文件。在 OpenSSL 程序包 的 apps 文件夹中,有一个名为 openssl.cnf 的 可用模
板文件。我不会对该文件进行讨论,因为这不在本文要求范围之内。不过,该
模板文件有一些非常好的注释,而且如果 在 Internet 上搜索,您可以找到很多
讨论修改该文件的教程。
头文件和初始化
本教程所使用的头文件只有三个:ssl.h、bio.h 和 err.h。它们都位于 openssl
子目录中,而且都是开发您的项目 所必需的。要初始化 OpenSSL 库,只需要三
个代码行即可。清单 1 中列出了所有内容。其他的头文件 和/或 初始化函数可
能 是其他一些功能所必需的。
清单 1. 必需的头文件
/* OpenSSL headers */
#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
/* Initializing OpenSSL */
SSL_load_error_strings();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();
建立非安全连接
不管连接是 安全的还是不安全的,OpenSSL 都使用了一个名为 BIO 的抽象库
来处理包括文件和套接字在内的各种类型的通信。您还可以将 OpenSSL 设置成
为一个过滤器,比如用于 UU 或 Base64 编码的过滤器。
在这里对 BIO 库进行全面说明有点麻烦,所以我将根据需要一点一点地介绍它。
首先, 我将向您展示如何建立一个标准的套接字连接。相对于使用 BSD 套接
字库,该操作需要 的代码行更少一些。
在建立连接(无论安全与否)之前,要创建一个指向 BIO 对象的指针。这类似
于在标准 C 中 为文件流创建 FILE 指针。
清单 2. 指针
BIO * bio;
打开连接
创建新的连接需要调用 BIO_new_connect 。您可以在同一个调用中同时 指定主
机名和端口号。也可以将其拆分为两个单独的调用:一个是创建连接并设置主
机名的 BIO_new_connect 调用,另一个是设置端口号的 BIO_set_conn_port (或
者 BIO_set_conn_int_port )调用。
不管怎样,一旦 BIO 的主机名和端口号都已指定,该指针会尝试打开连接。没
有什么可以影响它。如果创建 BIO 对象时遇到问题,指针将会是 NULL。为了
确保连接成功,必须执行 BIO_do_connect 调用。
清单 3. 创建并打开连接
bio = BIO_new_connect("hostname:port");
if(bio == NULL)
{
/* Handle the failure */
}
if(BIO_do_connect(bio) <= 0)
{
/* Handle failed connection */
}
在这里,第一行代码使用指定的主机名和端口创建了一个新的 BIO 对象,并以
所示风格对该对象进行 格式化。例如, 如果您要连接到 www.ibm.com 的 80 端
口,那么该字符串将是 www.ibm.com:80 。调用 BIO_do_connect 检查连接是否
成功。如果出错,则返回 0 或 -1。
与服务器进行通信
不管 BIO 对象是套接字还是文件,对其进行的读和写操作都是通过以下两个函
数来完成的: BIO_read 和 BIO_write 。 很简单,对吧?精彩之处就在于它始终
如此。
BIO_read 将尝试从服务器读取一定数目的字节。它返回读取的字节数、 0 或者
-1。在受阻塞的连接中,该函数返回 0,表示连接已经关闭,而 -1 则表示连接
出现错误。在非阻塞连接的情况下,返回 0 表示没有可以获得的数据,返回 -1
表示连接出错。可以调用 BIO_should_retry 来确定是否可能重复出现该错误。
清单 4. 从连接读取
int x = BIO_read(bio, buf, len);
if(x == 0)
{
/* Handle closed connection */
}
else if(x < 0)
{
if(! BIO_should_retry(bio))
{
/* Handle failed read here */
}
/* Do something to handle the retry */
}
BIO_write 会试着将字节写入套接字。它将返回实际写入的 字节数、0 或者 -
1。同 BIO_read ,0 或 -1 不一定表示错误。 BIO_should_retry 是找出问题的途
径。如果需要重试写操作,它必须 使用和前一次完全相同的参数。
清单 5. 写入到连接
if(BIO_write(bio, buf, len) <= 0)
{
if(! BIO_should_retry(bio))
{
/* Handle failed write here */
}
/* Do something to handle the retry */
}
关闭连接
关闭连接也很简单。您可以使用以下两种方式之一来关闭连接: BIO_reset 或
BIO_free_all 。如果您还需要重新使用对象,那么请使用第一种方式。 如果您
不再重新使用它,则可以使用第二种方式。
BIO_reset 关闭连接并重新设置 BIO 对象的内部状态,以便可以重新使用连接。
如果要在整个应用程序中使用同一对象,比如使用一台安全的聊天 客户机,那
么这样做是有益的。该函数没有返回值。
BIO_free_all 所做正如其所言:它释放内部结构体,并释放 所有相关联的内存,
其中包括关闭相关联的套接字。如果将 BIO 嵌入于一个类中,那么应该在类的
析构函数中使用这个调用。
剩余27页未读,继续阅读
资源评论
marcellen
- 粉丝: 3
- 资源: 34
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- apk.tw_LineLite_v8a_v.2.17.1_sign.apk
- Elasticsearch实战:构建高效搜索系统的秘诀.zip
- HTML+CSS+JS网页设计:从入门到精通.zip
- 数据库课程设计:从理论到实践的全面指南.zip
- Python闭包:深入理解与应用场景解析.zip
- Win64OpenSSL-3-3-0.exe
- 课高分程设计-基于C++实现的民航飞行与地图简易管理系统-南京航空航天大学
- 航天器遥测数据故障检测系统python源码+文档说明+数据库(课程设计)
- 北京航空航天大学操作系统课设+ppt+实验报告
- 基于Vue+Echarts实现风力发电机中传感器的数据展示监控可视化系统+源代码+文档说明(高分课程设计)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功