2018-2019-1 20165309 20165312 20165330 实验五 通讯协议设计
任务一
任务详情
- 在Ubuntu中完成 http://www.cnblogs.com/rocedu/p/5087623.html 中的作业
相关知识点
OpenSSL
是一个SSL协议的开源实现,采用C语言作为开发语言,具备了跨平台的能力,支持Unix/Linux
、Windows
、Mac OS
等多种平台- 三个主要的功能部分:密码算法库、SSL协议库、应用程序
- 作为一个基于密码学的安全开发包,
OpenSSL
提供的功能相当强大和全面,囊括了主要的密码算法、常用的密钥和证书封装管理功能以及SSL协议,并提供了丰富的应用程序供测试或其它目的使用。 - OpenSSl详细简介参考:OpenSSL简介
实验过程及步骤
Linux下OpenSSL
的安装
- OpenSSL源码下载地址
- 解压源码:
unzip openssl-master.zip
- 进入源代码目录:
cd openssl-master
- 编译安装:
./config
make
sudo make install
- 使用
make test
进行测试
Linux下OpenSSL
的使用
- 通过
man openssl
查看帮助文档 - 编写测试代码
test_openssl.c
#include <stdio.h>
#include <openssl/evp.h>
int main(){
OpenSSL_add_all_algorithms();
return 0;
}
- 编译:
gcc -o test_openssl test_openssl.c -L/usr/local/ssl/lib -lcrypto -ldl -lpthread
,生成可执行文件test_openssl
- 执行
echo $?
,结果打印0
作业
基于Socket实现TCP通信,一人实现服务器,一人实现客户端
研究OpenSSL算法,测试对称算法中的AES,非对称算法中的RSA,Hash算法中的MD5
- AES
- 生成加密/解密的Key
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);
- 使用AES加密/解密
void AES_encrypt(const unsigned char *in, unsigned char *out,const AES_KEY *key);
void AES_decrypt(const unsigned char *in, unsigned char *out,const AES_KEY *key);
AES_encrypt/AES_decrypt
一次只处理16个字节。如果输入数据较长,需要使用循环语句,每16个字节处理一次,直到所有数据处理完毕;如果数据不足16字节,可以用0填充至16字节。- 码云链接
- 截图
- RSA
- 命令台下openssl工具的简单使用
- 生成一个密钥:
openssl genrsa -out test.key 1024
,这里-out
指定生成的文件名。 - 提取出公钥:
openssl rsa -in test.key -pubout -out test_pub.key
,-in
指定输入文件,-out
指定提取生成公钥的文件名,用公钥来加密文件。 - 在目录中创建一个
hello
的文本文件,然后利用此前生成的公钥加密文件:openssl rsautl -encrypt -in hello -inkey test_pub.key -pubin -out hello.en
,-in
指定要加密的文件,-inkey
指定密钥,-pubin
表明是用纯公钥文件加密,-out
为加密后的文件 - 解密文件:
openssl rsautl -decrypt -in hello.en -inkey test.key -out hello.de
,-in
指定被加密的文件,-inkey
指定私钥文件,-out
为解密后的文件。
- 生成一个密钥:
- 码云链接
- 截图
- 命令台下openssl工具的简单使用
- MD5
- 初始化MD5上下文结构:
int MD5_Init(MD5_CTX *c);
- 刷新MD5,将文件连续数据分片放入进行MD5刷新:
int MD5_Update(MD5_CTX *c, const void *data, size_t len);
- 产生最终的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上下文结构:
任务二
任务详情
- 在Ubuntu中实现对实验二中的“wc服务器”通过混合密码系统进行防护
混合密码系统
- 图解
- 混合密码系统组成机制
- 用对称密码加密消息
- 用伪随机数生成器生成对称密码加密中使用的会话密钥
- 用公钥密码加密会话密钥
- 从混合密码系统外部赋予公钥密码加密中使用的会话密钥
- 使用
OpenSSL API
进行安全编程(参考linux下的OPENSSL编程)- 头文件
#include <openssl/ssl.h> #include <openssl/err.h>
- 初始化
int SSL_library_int(void);
- 选择会话协议
- 创建会话环境
- 申请SSL会话环境:
SSL_CTX *SSL_CTX_new(SSL_METHOD * method);
- 申请SSL会话环境:
- 建立SSL套接字
- 申请一个SSL套接字:
SSL *SSl_new(SSL_CTX *ctx);
- 绑定读写套接字:
int SSL_set_fd(SSL *ssl,int fd);)
- 绑定只读套接字:
int SSL_set_rfd(SSL *ssl,int fd);
- 绑定只写套接字:
int SSL_set_wfd(SSL *ssl,int fd);
- 申请一个SSL套接字:
- 完成SSL握手
- 在成功创建SSL套接字后,客户端应使用函数SSL_connect( )替代传统的函数connect( )来完成握手过程:
int SSL_connect(SSL *ssl);
- 而对服务器来讲,则应使用函数SSL_ accept ( )替代传统的函数accept ( )来完成握手过程:
int SSL_accept(SSL *ssl);
- 在成功创建SSL套接字后,客户端应使用函数SSL_connect( )替代传统的函数connect( )来完成握手过程:
- 进行数据传输
- 结束SSL通信
- 关闭SSL套接字:
SSL_shutdown(SSL *ssl);
- 释放SSL套接字:
SSl_free(SSL *ssl);
- 释放SSL会话环境:
SSL_CTX_free(SSL_CTX *ctx);
- 关闭SSL套接字:
- 头文件
- 生成私钥和证书:
openssl genrsa -out privkey.pem 1024
openssl req -new -x509 -key privkey.pem -out CAcert.pem -days 1095
- 编译
gcc server.c -o server -lssl -lcrypto
gcc client.c -o client -lssl -lcrypto
或使用
gcc -o server server.c -I /usr/local/ssl/include -L/usr/local/ssl/lib -lssl -lcrypto -ldl -lpthread
和gcc -o client client.c -I /usr/local/ssl/include -L/usr/local/ssl/lib -lssl -lcrypto -ldl -lpthread
也可 - 运行
./server 5302 1 CAcert.pem privkey.pem
./client 127.0.0.1 5330
码云链接
截图
实验过程中遇到的问题及解决办法
- 在对测试代码进行编译时,出现错误
解决办法:进入到
/usr/local/ssl/
目录下用sudo mkdir lib
新建lib
目录,在进行编译即可
- 在对AES进行编译运行时出错
解决办法:参考解决:error while loading shared libraries发现是因为找不到库的位置造成的,可输入命令
sudo ln -s /usr/local/lib/libssl.so.1.1 /usr/lib/libssl.so.3
和sudo ln -s /usr/local/lib/libcrypto.so.1.1 /usr/lib/libcrypto.so.3
后,在进行编译和运行即可