2017-2018-1 20155229 实验五 《通讯协议设计》
2017-2018-1 20155229 实验五 《通讯协议设计》
实验目的
通过学习openssl,了解openssl,并且能够通过它来实现密码算法的印证
实验步骤
实验五 通讯协议设计-1
- 在Ubuntu中完成 http://www.cnblogs.com/rocedu/p/5087623.html 中的作业
Linux下OpenSSL的安装与使用
OpenSSL简介
- 是一个安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。
- OpenSSL整个软件包大概可以分成三个主要的功能部分:密码算法库、SSL协议库、应用程序
- SSL是Secure Sockets Layer(安全套接层协议)的缩写,可以在Internet上提供秘密性传输。SSL能使用户/服务器应用之间的通信不被攻击者窃听,并且始终对服务器进行认证,还可选择对用户进行认证。SSL协议要求建立在可靠的传输层协议(TCP)之上。
- 密码算法库是一个强大完整的密码算法库,它是OpenSSL的基础部分,它实现了目前大部分主流的密码算法和标准。主要包括对称算法、非对称算法、散列算法、数字签名和认证、X509数字证书标准、PKCS12、PKCS7等标准。此外,OpenSSL还实现了DSS标准中规定的两种信息摘要算法DSS和DSS1。
- OpenSSL的应用程序主要包括密钥生成、证书管理、格式转换、数据加密和签名、SSL测试以及其它辅助配置功能。
下载openSSL
- 在官网下载程序 http://www.openssl.org/
- 使用
unzip openssl-master.zip
对压缩包进行解压 - 运行
./config
生成私钥:make
openssl rsa -in private.pem -out public.pem -pubout
查看密钥信息: openssl rsa -noout -text -in privatekey_test.pem
用生成的公钥加密 test:make test
make install
使用man openssl
查看帮助文档
运用老师给的测试代码test.c
#include <stdio.h>
#include <openssl/evp.h>
int main(){
OpenSSL_add_all_algorithms();
return 0;
}
使用gcc -o test test.c -I /usr/local/ssl/inlcude /usr/local/ssl/lib -ldl -lpthread
命令编译
执行./test;echo $?
,执行的结果为0
基于Socket实现TCP通信,一人实现服务器,一人实现客户端
研究OpenSSL算法,测试对称算法中的AES,非对称算法中的RSA,Hash算法中的MD5
AES
//设置加密密钥,使用字符缓冲区
int AES_set_encrypt_key(const unsigned char *userKey,const int bits,AES_KEY *key);
//设置解密密钥,同样适用字符缓冲区
int AES_set_decrypt_key(const unsigned char *userKey,const int bits,AES_KEY *key);
//加解密的接口,通过最后的enc来区分是加密还是解密操作
//每次执行AES_cbc_encrypt后,iv(向量)会被更新,
//所以需要自己保存它。
void AES_cbc_encrypt(const unsigned char
*in, unsigned char *out,const unsigned long length,const AES_KEY *key,unsigned char *ivec,const int enc);
RSA
- 生成一个密钥:
openssl genrsa -out test.key 1024
这里-out指定生成文件的。需要注意的是这个文件包含了公钥和密钥两部分,也就是说这个文件即可用来加密也可以用来解密。后面的1024是生成密钥的长度。
- openssl可以将这个文件中的公钥提取出来:
openssl rsa -in test.key -pubout -out test_pub.key
-in指定输入文件,-out指定提取生成公钥的文件名。至此,我们手上就有了一个公钥,一个私钥(包含公钥)。现在可以将用公钥来加密文件了。
在目录中创建一个文本文件,然后利用此前生成的公钥加密文件:
openssl rsautl -encrypt -in xxx -inkey test_pub.key -pubin -out xxx
-in指定要加密的文件,-inkey指定密钥,-pubin表明是用纯公钥文件加密,-out为加密后的文件。
- 解密文件:
openssl rsautl -decrypt -in xxx -inkey test.key -out xxx
-in指定被加密的文件,-inkey指定私钥文件,-out为解密后的文件。
*RSA_generate_key(int bits, unsigned long e_value,void (*callback)(int,int,void *), void *cb_arg)
//生成RSA密钥,bits是模数比特数,e_value是公钥指数e,callback回调函数由用户实现,用于干预密钥生成过程中的一些运算,可为空。
MD5
openssl MD5 接口
int MD5_Init(MD5_CTX *c);
//初始化MD5上下文结构
int MD5_Update(MD5_CTX *c, const void *data, size_t len);
//刷新MD5,将文件连续数据分片放入进行MD5刷新。
int MD5_Final(unsigned char *md, MD5_CTX *c);
//产生最终的MD5数据
unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md);
//直接产生字符串的MD5
实验五 通讯协议设计-2
- 在Ubuntu中实现对实验二中的“wc服务器”通过混合密码系统进行防护
openssl实现服务器和客户端
ssl的初始化
使用openssl提供的函数设置算法、证书等。
-
创建根证私钥命令:
openssl genrsa -out root-key.key 1024
-
创建根证书请求文件命令:
openssl req -new -out root-req.csr -key root-key.key -keyform PEM
-
要求校验对方证书
SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);
-
加载CA的证书
EXIT_IF_TRUE(!SSL_CTX_load_verify_locations(ctx, "cacert.cer", NULL));
-
加载自己的证书
EXIT_IF_TRUE(SSL_CTX_use_certificate_file(ctx,"client.cer",SSL_FILETYPE_PEM) <= 0) ;
-
加载自己的私钥
EXIT_IF_TRUE(SSL_CTX_use_PrivateKey_file(ctx, "client.key",SSL_FILETYPE_PEM)<= 0) ;
主要代码为
SSL_load_error_strings(); /*为打印调试信息作准备*/
OpenSSL_add_ssl_algorithms(); /*初始化*/
//meth = TLSv1_server_method(); /*采用什么协议(SSLv2/SSLv3/TLSv1)在此指定*/
//注意这里是server,客户端那里会是client
ctx = SSL_CTX_new (TLSv1_server_method());
CHK_NULL(ctx);
SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); /*验证与否*/
SSL_CTX_load_verify_locations(ctx,CACERT,NULL); /*若验证,则放置CA证书*/
if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
getchar();
exit(3);
}
if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stdout);
getchar();
exit(4);
}
if (!SSL_CTX_check_private_key(ctx)) {
printf("Private key does not match the certificate public keyn");
getchar();
exit(5);
}
SSL_CTX_set_cipher_list(ctx,"RC4-MD5");
ssl连接通信
生成客户端文件:
1.生成客户端key
openssl genrsa -out client-key.key 1024
2.生成客户端请求文件
openssl req -new -out client-req.csr -key client-key.key
3.生成客户端证书(root证书,rootkey,客户端key,客户端请求文件这4个生成客户端证书)
openssl x509 -req -in client-req.csr -out client-cert.cer -signkey client-key.key -CA root-cert.cer -CAkey root-key.key -CAcreateserial -days 3650
4.生成客户端p12格式根证书
openssl pkcs12 -export -clcerts -in client-cert.cer -inkey client-key.key -out client.p12
生成服务端文件:
1.生成服务端key
openssl genrsa -out server-key.key 1024
2.生成服务端请求文件
openssl req -new -out server-req.csr -key server-key.key
3.生成服务端证书(root证书,rootkey,客户端key,客户端请求文件这4个生成客户端证书)
openssl x509 -req -in server-req.csr -out server-cert.cer -signkey server-key.key -CA root-cert.cer
-CAkey root-key.key -CAcreateserial -days 3650
4.生成服务端p12格式根证书
openssl pkcs12 -export -clcerts -in server-cert.cer -inkey server-key.key -out server.p12
建立TCP套接字,并且进入监听,当接收到客户端连接请求后,使用accept建立和客户端通信的套接字s,从初始化的SSL_CTX创建一个SSL,将该SSL和与客户端通信的套接字s绑定,然后使用SSL_accept建立和客户端的SSL连接,如果建立成功就可以检查客户端的证书并获取客户端的证书信息,实现相互认证。之后,可以使用异步通信机制处理该SSL连接的消息。原理图如下图所示:
实验结果截图:
实验五 通讯协议设计-3(未完成)
实验感想与体会
通过本次实验,对openssl有了深入的了解,openssl作为一个基于密码学的安全开发包,提供的功能相当的强大和全面,囊括了主要的密码算法和常用的密钥和证书封装管理功能以及ssl'协议。在实验中,对RSA、AES、MD5等密码算法一一进行了验证,同时还学习了openssl实现双向认证的内容,再一次深深的感受到了openssl对于密码学的方便。