?? linux網絡編程一步一步學-利用openssl提供的ssl操作函數進行加密通訊原始例子(18).txt
字號:
Linux網絡編程一步一步學-利用OpenSSL提供的SSL操作函數進行加密通訊原始例子
關鍵詞: Linux socket OpenSSL 加密 安全
首先,大家知道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
【作者: 周立發】【訪問統計:1658】【2007年01月28日 星期日 18:47】【注冊】【打印】
Google Adsense
Sql Dev
PL/SQL development tool for Pro's Free Trial including all features!
www.conquestsoftwaresolutions.com
搜索
Trackback
你可以使用這個鏈接引用該篇文章 http://publishblog.blogchina.com/blog/tb.b?diaryID=6074014
回復
- 評論人:反對撒反對撒 2007-07-04 17:17:52
代碼可以編譯成功,但根本測試不了
- 評論人:周立發 2007-03-26 18:24:50
先啟動服務端程序,再啟動客戶端程序。客戶端以SSL方式連接客戶端,服務端程序就處理客戶端請求,用點工夫讀懂上面兩個源代碼就知道了。
- 評論人:Linux初學者 2007-03-15 16:17:11
周大俠 編譯完以后 怎么測試呢?
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -