您的位置:首页 > 理论基础 > 计算机网络

用OpenSSL结合ACE 做安全网络通信

2009-05-31 14:33 537 查看
1 SSL X509证书工作原理参考




1.1 公钥密码系统


在公钥密码系统中,加密与解密使用不同的密钥。其中一个密钥为个人私有掌管,称之为私钥,另一个密钥是对外公开的,大家都可以获取到。公钥密码系统的一大特点:用公钥加密的报文只有私钥才能解密。同样,用私钥加密的报文只有公钥才能解密。

SSL证书由两部分组成:私钥、证书。证书中包含了公钥、证书的摘要、CA的签名以及其他扩展信息。其中CA的签名只有CA的公钥才能解开。



1.2 SSL证书的校验




证书的签名


由认证中心CA用私钥对各证书进行签名。认证中心CA是个自签名的X509证书。



证书的校验


当一个网络连接创建时,连接者双方互换证书。可以要求SSL对对方的证书进行校验。



图表 1 1

如图,当A连上B时,B可以要求对A的证书进行校验:B用认证中心CA的证书(公钥)对A的证书进行校验(看是否有CA的签名,每个不同的CA,签名都不
一样),如果校验结果不成立,则断开网络连接。同样,A也可以要求对B的证书进行校验。这一步双方都可以确认对方身份。



1.3 SSL在通信过程中的加解密


因为公钥加解密运算量很大,对于比较大的数据用公钥系统加解密是不够现实的。事实上SSL在通信过程中,首先约定一种对称加解密方案,并设定密码,这些操
作的通信采用的是公钥系统加解密;随后的通信则采用约定好的对称加解密,并在一段时间后,又重新约定过新的对称加解密方案。这样既保证了安全,又有足够的
性能在现实环境下应用。



约定对称算法


A发给B的约定报文用B的公钥加密,这样,只有B用B的私钥才能解密,同样,B发给A的约定报文用A的公钥加密。



图表 1 2


正常的报文通信


A用约定的对称算法加密,B用约定的对称算法解密。同样B用约定的对称算法加密,A用约定的对称算法解密。



图表 1 3


2 用OpenSSL 制作X509证书


2.1 建立自己的CA

在openssl 安装目录的bin 目录下,运行脚本:./CA.sh -newca(Windows 环境下运行:perl ca.pl –newca),出现提示符时,直接回车。 运行完毕后会生成一个demonCA 的目录,里面包含了ca 证书及其私钥。

2.2 生成客户端和服务端证书申请

openssl req -newkey rsa:1024 -out req1.pem -keyout sslclientkey.pem

openssl req -newkey rsa:1024 -out req2.pem -keyout sslserverkey.pem

2.3 签发客户端和服务端证书


openssl ca -in req1.pem -out sslclientcert.pem

openssl ca -in req2.pem -out sslservercert.pem

2.4 运行ssl 服务端和客户端

openssl s_server -cert sslservercert.pem -key sslserverkey.pem -CAfile demoCA/cacert.pem -ssl3 -Verify 1

openssl s_client -ssl3 -CAfile demoCA/cacert.pem -cert sslclientcert.pem -key sslclientkey.pem -Verify 1

不出错的话,应该可以正常通信了。



3 用ACE_SSL做安全的网络通信


ACE_SSL的通信使用ACE_SSL_SOCK_Stream流。服务方接收器使用ACE_SSL_SOCK_Acceptor,客户端连接器使用ACE_SSL_SOCK_Connector。具体参考下面的代码:

服务端:

#include<iostream>

#include<string>

#include<ace/Acceptor.h>

#include<ace/SOCK_Acceptor.h>

#include<ace/SOCK_Stream.h>

#include<ace/SSL/SSL_SOCK_Stream.h>

#include<ace/SSL/SSL_SOCK_Acceptor.h>

using namespace std;

int main(int argc, char* argv[])

{

//SSL环境初始化

ACE_SSL_Context* ssl=ACE_SSL_Context::instance();

ssl->certificate("sslservercert.pem");

ssl->load_trusted_ca("cacert.pem");

ssl->context()->default_passwd_callback_userdata = (void*)"私钥的保护密码";

ssl->private_key("sslserverkey.pem");

ssl->set_verify_peer(1); // 启用证书交验

int a = ssl->verify_private_key(); // a == 0 表示成功

//通信

char buf[1024];

ACE_SSL_SOCK_Stream stream;

ACE_INET_Addr addr (9999);

ACE_INET_Addr remote_addr;

ACE_SSL_SOCK_Acceptor acceptor(addr);

if (-1 == acceptor.accept(stream,&remote_addr))

return -1;

remote_addr.addr_to_string(buf,1024);

std::cout << "有客户端连接:" << buf << std::endl;

std::string str("TCP 服务端测试发送数据!");

stream.send(str.c_str(),str.length());

int size = stream.recv(buf,1024);

buf[size] = 0;

std::cout << "接收到数据:" << buf << std::endl;

system("pause");

return 0;

}

客户端:

#include<iostream>

#include<string>

#include<ace/Connector.h>

#include<ace/SOCK_Connector.h>

#include<ace/SOCK_Stream.h>

#include<ace/SSL/SSL_SOCK_Stream.h>

#include<ace/SSL/SSL_SOCK_Connector.h>

using namespace std;

int main(int argc, char* argv[])

{

//SSL环境初始化

ACE_SSL_Context* ssl=ACE_SSL_Context::instance();

ssl->certificate("sslclientcert.pem");

ssl->load_trusted_ca("cacert.pem");

ssl->context()->default_passwd_callback_userdata = (void*)"私钥的保护密码";

ssl->private_key("sslclientkey.pem");

ssl->set_verify_peer(1); // 启用证书交验

int a = ssl->verify_private_key(); // a == 0 表示成功

//通信

char buf[1024];

ACE_INET_Addr server_addr(9999,"localhost");

ACE_SSL_SOCK_Stream stream;

ACE_SSL_SOCK_Connector connector;

if (-1 == connector.connect(stream,server_addr))

return -1;

server_addr.addr_to_string(buf,1024);

std::cout << "连接上服务器:" << buf << std::endl;

int size = stream.recv(buf,1024);

buf[size] = 0;

std::cout << "接收到数据:" << buf << std::endl;

std::string str = "客户端测试发送数据!";

stream.send(str.c_str(),str.length());

system("pause");

return 0;

}



图表 3 1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: