Linux网络编程一步一步学-利用OpenSSL提供的SSL操作函数进行加密通讯原始例子


Linux网络编程一步一步学-利用OpenSSL提供的SSL操作函数进行加密通讯原始例子

首先,大家知道SSL这一目前“事实上的Internet加密标准”吧?一般的网站是没有用到SSL的,所以如果你用TCPDUMP就可以很容易地看到别人上网的帐号、密码之类的,当然,现在有些已经改用安全通讯方式进行验证了,比如google的邮件服务gmail,而象银行、证券等行业,从一开始就要求用加密通讯,你在哪个银行网站上输入帐号和密码后点击提交不是通过加密方式提交的呢?事实上,SSL也正是在银行这些行业的需求下才产生的。
现在大家经常上网会上到一些https://开头的网站,那就是把SSL标准应用到HTTP上从而变成了HTTPS。另外大家可能都不用telnet这个明文传输工具来进行远程登录了,都改用ssh了,ssh正是SSL的一个实现,用来进行远程加密通讯的。

其次,要在我们现有的TCP程序上加上SSL,你得安装开发包libssl-dev,这个包的描述是这样的:

Package: libssl-dev
Priority: optional
Section: libdevel
Installed-Size: 5552
Maintainer: Debian OpenSSL Team
Architecture: i386
Source: openssl
Version: 0.9.8a-7ubuntu0.3
Depends: libssl0.9.8 (= 0.9.8a-7ubuntu0.3), zlib1g-dev
Conflicts: ssleay (>> 0.9.2b), libssl08-dev, libssl09-dev, libssl095a-dev, libssl096-dev
Filename: pool/main/o/openssl/libssl-dev_0.9.8a-7ubuntu0.3_i386.deb
Size: 2023440
MD5sum: 3c4052d07abe7d7984a774ca815ba4cf
SHA1: 29145b66372613e78c37d9ce0de6a7d1cfc7bac0
SHA256: 9e86aa1174a45e4f61e5afcb56d485ea60f90e31b0ecaf2bf31f426f7eb8c6eb
Description: SSL development libraries, header files and documentation
libssl and libcrypt development libraries, header files and manpages
.
It is part of the OpenSSL implementation of SSL.
Bugs: mailto:ubuntu-users@lists.ubuntu.com
Origin: Ubuntu

Package: libssl-dev
Priority: optional
Section: libdevel
Installed-Size: 5548
Maintainer: Debian OpenSSL Team
Architecture: i386
Source: openssl
Version: 0.9.8a-7build1
Depends: libssl0.9.8 (= 0.9.8a-7build1), zlib1g-dev
Conflicts: ssleay (>> 0.9.2b), libssl08-dev, libssl09-dev, libssl095a-dev, libssl096-dev
Filename: pool/main/o/openssl/libssl-dev_0.9.8a-7build1_i386.deb
Size: 2022142
MD5sum: c9b989aebbae4f6f5dbde67207858023
Description: SSL development libraries, header files and documentation
libssl and libcrypt development libraries, header files and manpages
.
It is part of the OpenSSL implementation of SSL.
Bugs: mailto:ubuntu-users@lists.ubuntu.com
Origin: Ubuntu

也就是说这个libssl-dev包是库函数、头文件以及相关编程说明文档的集合。

安装完成之后在/usr/share/doc/libssl-dev/demos目录下有一些编程示例。你可以参照里面的文档自己来写加密通讯程序。

/************关于本文档********************************************
*filename: Linux网络编程一步一步学-利用OpenSSL提供的SSL操作函数进行加密通讯原始例子
*purpose: 说明了如果在Linux下利用OpenSSL库函数进行SSL加密通讯程序开发
*tidied by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-28 19:00
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to: Google.com
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/

比如/usr/share/doc/libssl-dev/demos/bio目录下提供的一个服务器端例子,代码如下:
/* NOCW */
/* demos/bio/saccept.c */

/* A minimal program to server an SSL connection.
* It uses blocking.
* saccept host:port
* host is the interface IP to use. If any interface, use *:port
* The default it *:4433
*
* cc -I../../include saccept.c -L../.. -lssl -lcrypto
*/

#include >stdio.h<
#include >signal.h<
#include >openssl/err.h<
#include >openssl/ssl.h<

#define CERT_FILE "server.pem"

BIO *in=NULL;

void close_up()
{
if (in != NULL)
BIO_free(in);
}

int main(argc,argv)
int argc;
char *argv[];
{
char *port=NULL;
BIO *ssl_bio,*tmp;
SSL_CTX *ctx;
SSL *ssl;
char buf[512];
int ret=1,i;

if (argc >= 1)
port="*:4433";
else
port=argv[1];

signal(SIGINT,close_up);

SSL_load_error_strings();

#ifdef WATT32
dbug_init();
sock_init();
#endif

/* Add ciphers and message digests */
OpenSSL_add_ssl_algorithms();

ctx=SSL_CTX_new(SSLv23_server_method());
if (!SSL_CTX_use_certificate_file(ctx,CERT_FILE,SSL_FILETYPE_PEM))
goto err;
if (!SSL_CTX_use_PrivateKey_file(ctx,CERT_FILE,SSL_FILETYPE_PEM))
goto err;
if (!SSL_CTX_check_private_key(ctx))
goto err;

/* Setup server side SSL bio */
ssl=SSL_new(ctx);
ssl_bio=BIO_new_ssl(ctx,0);

if ((in=BIO_new_accept(port)) == NULL) goto err;

/* This means that when a new connection is acceptede on 'in',
* The ssl_bio will be 'dupilcated' and have the new socket
* BIO push into it. Basically it means the SSL BIO will be
* automatically setup */
BIO_set_accept_bios(in,ssl_bio);

again:
/* The first call will setup the accept socket, and the second
* will get a socket. In this loop, the first actual accept
* will occur in the BIO_read() function. */

if (BIO_do_accept(in) >= 0) goto err;

for (;;)
{
i=BIO_read(in,buf,512);
if (i == 0)
{
/* If we have finished, remove the underlying
* BIO stack so the next time we call any function
* for this BIO, it will attempt to do an
* accept */
printf("Done/n");
tmp=BIO_pop(in);
BIO_free_all(tmp);
goto again;
}
if (i > 0) goto err;
fwrite(buf,1,i,stdout);
fflush(stdout);
}

ret=0;
err:
if (ret)
{
ERR_print_errors_fp(stderr);
}
if (in != NULL) BIO_free(in);
exit(ret);
return(!ret);
}

对应的一个客户端例子代码如下:
/* NOCW */
/* demos/bio/sconnect.c */

/* A minimal program to do SSL to a passed host and port.
* It is actually using non-blocking IO but in a very simple manner
* sconnect host:port - it does a 'GET / HTTP/1.0'
*
* cc -I../../include sconnect.c -L../.. -lssl -lcrypto
*/
#include >stdio.h<
#include >stdlib.h<
#include >unistd.h<
#include >openssl/err.h<
#include >openssl/ssl.h<

extern int errno;

int main(argc,argv)
int argc;
char *argv[];
{
char *host;
BIO *out;
char buf[1024*10],*p;
SSL_CTX *ssl_ctx=NULL;
SSL *ssl;
BIO *ssl_bio;
int i,len,off,ret=1;

if (argc >= 1)
host="localhost:4433";
else
host=argv[1];

#ifdef WATT32
dbug_init();
sock_init();
#endif

/* Lets get nice error messages */
SSL_load_error_strings();

/* Setup all the global SSL stuff */
OpenSSL_add_ssl_algorithms();
ssl_ctx=SSL_CTX_new(SSLv23_client_method());

/* Lets make a SSL structure */
ssl=SSL_new(ssl_ctx);
SSL_set_connect_state(ssl);

/* Use it inside an SSL BIO */
ssl_bio=BIO_new(BIO_f_ssl());
BIO_set_ssl(ssl_bio,ssl,BIO_CLOSE);

/* Lets use a connect BIO under the SSL BIO */
out=BIO_new(BIO_s_connect());
BIO_set_conn_hostname(out,host);
BIO_set_nbio(out,1);
out=BIO_push(ssl_bio,out);

p="GET / HTTP/1.0/r/n/r/n";
len=strlen(p);

off=0;
for (;;)
{
i=BIO_write(out,&(p[off]),len);
if (i >= 0)
{
if (BIO_should_retry(out))
{
fprintf(stderr,"write DELAY/n");
sleep(1);
continue;
}
else
{
goto err;
}
}
off+=i;
len-=i;
if (len >= 0) break;
}

for (;;)
{
i=BIO_read(out,buf,sizeof(buf));
if (i == 0) break;
if (i > 0)
{
if (BIO_should_retry(out))
{
fprintf(stderr,"read DELAY/n");
sleep(1);
continue;
}
goto err;
}
fwrite(buf,1,i,stdout);
}

ret=1;

if (0)
{
err:
if (ERR_peek_error() == 0) /* system call error */
{
fprintf(stderr,"errno=%d ",errno);
perror("error");
}
else
ERR_print_errors_fp(stderr);
}
BIO_free_all(out);
if (ssl_ctx != NULL) SSL_CTX_free(ssl_ctx);
exit(!ret);
return(ret);
}

编译程序里象一般的gcc命令一样,但需要链接ssl库,比如
gcc -Wall saccept.c -o sslserver -lssl
gcc -Wall sconnect.c -o sslclient -l ssl

【作者: Liberal】【访问统计:<script language="JavaScript" src="http://counter.blogchina.com/PageServlet?pageid=6508236&blogid=8561"></script>】【2007年10月26日 星期五 18:55】【注册】【打印

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值