31.openssl编程——SSL实现

31.1 概述
SSL协议最先由netscape公司提出,包括sslv2和sslv3两个版本。当前形成标准为tls协议(rfc2246规范)和DTLS(rfc4347,用于支持UDP协议)。sslv3和tls协议大致一样。
SSL协议能够保证通信双方的信道安全。他能提供数据加密、身份验证以及消息完整性保护。
SSL协议通过客户端和服务端握手来协商各种算法和密钥。
31.2 openssl实现
SSL协议源码位于ssl目录下。
XXX_clnt.c:客户端实现
XXX_srvr.c:服务端实现
XXX_enc.c:加密实现
XXX_pkt.c:记录协议实现
XXX_meth.c:METHOD方法
XXX_both.c:方法实现
XXX_lib.c:对外提供的函数实现
31.3 建立SSL测试环境
a.建立自己的CA
在openssl安装目录的misc目录下,运行./CA.sh -newca
b.生成客户端和服务端正数申请
openssl req -newkey rsa:1024 -out req1.pem -keyout sslclientkey.pem
openssl req -newkey rsa:1024 -out req2.pem -keyout sslserverkey.pem
c.签发客户端和服务端正数
openssl ca -in req1.pem -out sslclientcert.pem
openssl ca -in req2.pem -out sslservercert.pem
d.运行ssl服务端和客户端
openssl s_server -cert sslservercert.pem -key sslserverkey.pem -CAfile cacert.pem -ssl3
openssl s_client -ssl3 -CAfile cacert.pem
31.4 数据结构
     ssl的主要数据结构定义在ssl.h中。
SSL_CTX数据结构主要用于SSL握手前的环境准备,设置CA文件和目录、设置SSL握手中的证书文件和私钥、设置协议版本以及其他一些SSL握手时的选项。SSL数据结构主要用于SSL握手以及传送应用数据。
SSL_SESSION中保存了主密钥、session id、读写加解密钥、读写MAC密钥等信息。SSL_CTX中缓存了所有SSL_SESSION信息,SSL中包含SSL_CTX。一般SSL_CTX的初始化在程序最开始调用,然后再生成SSL数据结构。由于SSL_CTX中缓存了所有的SESSION,新生成的SSL结构又包含SSL_CTX数据,所以通过SSL数据结构能查找以前用过的SESSION id,实现SESSION重用。
31.5 加密套件
一个加密套件指明了SSL握手阶段和通信阶段所应该采用的各种算法。算法:认证算法、密钥交换算法、对称算法和摘要算法。
字符串的形式举例:ALL:!ADH:RC4+RSA:+SSLv2:@STRENGTH
Openssl定义了4中选择符号:“+”,“-”,“!”,“@”。其中,“+”表示取交集;“-”表示临时删除一个算法;“!”表示永久删除一个算法;“@“表示了排序方法
SSL建立链接之前,客户端和服务器端用openssl函数来设置自己支持的加密套件。
int SSL_set_cipher_list(SSL *s, const char *str);
int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str)
31.6 密钥信息
ssl中的密钥相关信息包括:预主密钥、主密钥、读解密密钥及其iv、写加密密钥及其iv、读MAC密钥、写MAC密钥
a.预主密钥
预主密钥是主密钥的计算来源。他由客户端生成,采用服务端的公钥加密发送给服务端。
b.主密钥
主密钥分别由客户端和服务端根据预祝密钥、客户端随机数和服务端随机数生成,他们的主密钥是相同的。主密钥用于生成各种密钥信息,它存放在SESSION数据结构中。
c.对称密钥和MAC密钥
对称密钥(包括IV)和读写MAC密钥通过主密钥、客户端随机数和服务端随机数生成。
31.7 SESSION
当客户端和服务端在握手中新建session,服务端生成一个session ID,通过session ID,通过哈希表缓存SESSION信息,并通过server hello消息发送给客户端。此ID是一个随机数,SSL_v2版本长度为16字节,SSLv3和TLSv1长度为32字节。此ID语安全无关,但是在服务端必须是唯一的。当需要session重用时,客户端发送包含session id的clientHello消息给服务端,服务端可用根据此ID来查询缓存。session重用可以免去诸多SSL握手交互,特别是客户端的公钥加密和服务端的私钥解密所带来的性能开销。
session相关函数有
a.int SSL_has_matching_session_id(const SSL *ssl, const unsgined char *id, unsigned int id_len)
SSL中查询session id, id和id_len为输入的要查询的session id,查询哈希表
b.int ssl_get_new_session(SSL *s, int session)
生成ssl用的session,此函数可用被服务端或客户端调用,当服务端调用时,传入参数session为12,生成新的session;当客户端调用时,传入参数session为0
c.int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len)
获取以前用过的session id, 用于服务端session重用,本函数由服务端调用,session_id为输入session ID首地址,len为其长度,如果返回1,表明要session重用,返回0,表示没有找到,返回-1表示错误。
d.int SSL_set_session(SSL *s, SSL_SESSION *session)
设置session,本函数用于客户端,用于设置session信息;如果输入参数session为空值,他将置空s->session;如果不为空,他将输入信息作为session信息。
e.void SSL_CTX_flush_session
清除超时的SESSION,输入参数值t指定一个时间,如果t=0,则清楚所有SESSION,一般用time(NULL)去当前时间。词函数调用了哈洗白哦函数lh_doall_arg来处理每一个SESSION数据
f.int ssl_clear_bad_session(SSL *s)
清除无效SESSION
31.8 多线程支持
编写openssl多线程程序时,需要设置两个回调函数:
CRYPTO_set_id_callback((unsignec long(*))pthreas_thread_id);
CRYPTO_set_locking_callback(void(*)()pthread_locking_callback);
31.9 函数
a.SSL_accept
对应于socket函数accept,该函数在服务端调用,用来进行SSL握手
b.int SSL_add_client_CA(SSL *ssl, X509 *x)
添加客户端CA名
c.const char *SSL_alert_desc_string_long(int value)
根据错误号得到错误原因
d.SSL_check_private_key
检查SSL结构中的私钥
e.SSL_CIPHER_description
获取SSL加密套件描述
f.SSL_CIPHER_get_bits
获取加密套件中对称算法的加密长度
g.SSL_CIPHER_get_name
得到加密套件的名字
h.SSL_CIPHER_get_version
根据加密套件获取SSL协议版本
i.SSL_clear
清除SSL结构
j.SSL_connect
对应于socket函数connect,该函数在客户端调用,用来进行SSL握手
k.SSL_CTX_add_client_CA
给SSL_CTX添加客户端CA.
l.int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
往SSL_CTX添加session.
m.SSL_CTX_check_private_key
检查
n.SSL_CTX_free
释放SSL_CTX空间
o.long SSL_CTX_get_timeout(const SSL_CTX *s)
获取超时时间
p.SSL_CTX_get_verify_callback
获取证书验证回调函数
q.SSL_CTX_verify_depth
获取证书验证深度
r.SSL_CTX_get_verify_mode
获取各个版本的客户端和服务端的SSL方法。
s.SSL_read
读取数据
t.SSL_write
发送数据
u.SSL_get_current_compression
获取当前的压缩算法的COMP_METHOD
v.SSL_COMP_get_name
获取压缩解压算法的名称
w.SSL_CTX_set/get_ex_data
设置/读取用户扩展数据
z.SSL_dup
复制函数
posted @ 2018-01-25 17:09  艾小小雨  阅读(2018)  评论(0编辑  收藏  举报