日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

《openssl编程》之BIO

發(fā)布時間:2024/4/11 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《openssl编程》之BIO 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

第七章???抽象IO

7.1??? openssl抽象IO

openssl抽象IO(I/O abstraction,即BIO)是openssl對于io類型的抽象封裝,包括:內(nèi)存、文件、日志、標準輸入輸出、socket(TCP/UDP)、加/解密、摘要和ssl通道等。Openssl BIO通過回調(diào)函數(shù)為用戶隱藏了底層實現(xiàn)細節(jié),所有類型的bio的調(diào)用大體上是類似的。Bio中的數(shù)據(jù)能從一個BIO傳送到另外一個BIO或者是應用程序。

7.2????數(shù)據(jù)結(jié)構(gòu)

?????? BIO數(shù)據(jù)結(jié)構(gòu)主要有2個,在crypto/bio.h中定義如下:

?????? 1)BIO_METHOD

????????????? typedef struct bio_method_st

?????? ?????? {

????????????? ?????? int type;

????????????? ?????? const char *name;

????????????? ?????? int (*bwrite)(BIO *, const char *, int);

????????????? ?????? int (*bread)(BIO *, char *, int);

????????????? ?????? int (*bputs)(BIO *, const char *);

????????????? ?????? int (*bgets)(BIO *, char *, int);

????????????? ?????? long (*ctrl)(BIO *, int, long, void *);

????????????? ?????? int (*create)(BIO *);

????????????? ?????? int (*destroy)(BIO *);

??????? long (*callback_ctrl)(BIO *, int, bio_info_cb *);

} BIO_METHOD;

該結(jié)構(gòu)定義了IO操作的各種回調(diào)函數(shù),根據(jù)需要,具體的bio類型必須實現(xiàn)其中的一種或多種回調(diào)函數(shù),各項意義如下:

type:具體BIO類型;

name:具體BIO的名字;

bwrite:具體BIO寫操作回調(diào)函數(shù);

bread:具體BIO讀操作回調(diào)函數(shù);

bputs:具體BIO中寫入字符串回調(diào)函數(shù);

bgets:具體BIO中讀取字符串函數(shù);

ctrl:具體BIO的控制回調(diào)函數(shù);

create:生成具體BIO回調(diào)函數(shù);

destroy:銷毀具體BIO回調(diào)函數(shù);

callback_ctrl:具體BIO控制回調(diào)函數(shù),與ctrl回調(diào)函數(shù)不一樣,該函數(shù)可由調(diào)用者(而不是實現(xiàn)者)來實現(xiàn),然后通過BIO_set_callback等函數(shù)來設置。

?????? 2)BIO

????????????? truct bio_st

?????? ?????? {

?????? BIO_METHOD *method;

?????? /* bio, mode, argp, argi, argl, ret */

?????? ????????????? long (*callback)(struct bio_st *,int,const char *,int, long,long);

?????? char *cb_arg; /* first argument for the callback */

?????? int init;

?????? int shutdown;

?????? int flags;? /* extra storage */

?????? int retry_reason;

?????? int num;

?????? void *ptr;

?????? struct bio_st *next_bio;? /* used by filter BIOs */

?????? struct bio_st *prev_bio; /* used by filter BIOs */

?????? int references;

???????????????????? nsigned long num_read;

?????? unsigned long num_write;

CRYPTO_EX_DATA ex_data;

?????? ?????? };

????????????? 主要項含義:

init:具體句柄初始化標記,初始化后為1。比如文件BIO中,通過BIO_set_fp關聯(lián)一個文件指針時,該標記則置1;socket BIO中通過BIO_set_fd關聯(lián)一個鏈接時設置該標記為1。

shutdown:BIO關閉標記,當該值不為0時,釋放資源;改值可以通過控制函數(shù)來設置。

flags:有些BIO實現(xiàn)需要它來控制各個函數(shù)的行為。比如文件BIO默認該值為BIO_FLAGS_UPLINK,這時文件讀操作調(diào)用UP_fread函數(shù)而不是調(diào)用fread函數(shù)。

retry_reason:重試原因,主要用在socket和ssl BIO 的異步阻塞。比如socket bio中,遇到WSAEWOULDBLOCK錯誤時,openssl告訴用戶的操作需要重試。

num:該值因具體BIO而異,比如socket BIO中num用來存放鏈接字。

ptr:指針,具體bio有不同含義。比如文件BIO中它用來存放文件句柄;mem bio中它用來存放內(nèi)存地址;connect bio中它用來存放BIO_CONNECT數(shù)據(jù),accept bio中它用來存放BIO_ACCEPT數(shù)據(jù)。

next_bio:下一個BIO地址,BIO數(shù)據(jù)可以從一個BIO傳送到另一個BIO,該值指明了下一個BIO的地址。

references:被引用數(shù)量。

num_read:BIO中已讀取的字節(jié)數(shù)。

num_write:BIO中已寫入的字節(jié)數(shù)。

ex_data:用于存放額外數(shù)據(jù)。

7.3??? BIO?函數(shù)

BIO各個函數(shù)定義在crypto/bio.h中。所有的函數(shù)都由BIO_METHOD中的回調(diào)函數(shù)來實現(xiàn)。函數(shù)主要分為幾類:

1)? 具體BIO相關函數(shù)

?????? 比如:BIO_new_file(生成新文件)和BIO_get_fd(設置網(wǎng)絡鏈接)等。

2)? 通用抽象函數(shù)

?????? 比如BIO_read和BIO_write等。

另外,有很多函數(shù)是由宏定義通過控制函數(shù)BIO_ctrl實現(xiàn),比如BIO_set_nbio、BIO_get_fd和BIO_eof等等。

7.4????編程示例

7.4.1?? mem bio

????????????? #include <stdio.h>

????????????? #include <openssl/bio.h>

????????????????????

????????????? int???? main()

????????????? {

?????? ???????? BIO???? *b=NULL;

????? ??? int???? len=0;

????? ??? ????? char??? *out=NULL;

?

??????? ?????? b=BIO_new(BIO_s_mem());

len=BIO_write(b,"openssl",4);

len=BIO_printf(b,"%s","zcp");

len=BIO_ctrl_pending(b);

out=(char *)OPENSSL_malloc(len);

len=BIO_read(b,out,len);

OPENSSL_free(out);

BIO_free(b);

return 0;

????????????? }

????????????? 說明:

????????????? b=BIO_new(BIO_s_mem());生成一個mem類型的BIO。

????????????? len=BIO_write(b,"openssl",7);將字符串"openssl"寫入bio。

????????????? len=BIO_printf(b,"bio test",8);將字符串"bio test"寫入bio。

????????????? len=BIO_ctrl_pending(b);得到緩沖區(qū)中待讀取大小。

????????????? len=BIO_read(b,out,50);將bio中的內(nèi)容寫入out緩沖區(qū)。

7.4.2?? file bio

????????????? #include <stdio.h>

????????????? #include <openssl/bio.h>

????????????????????

????????????? int???? main()

????????????? {

??????????????????????????? BIO???? *b=NULL;

????????????? ????????????? int???? len=0,outlen=0;

???????????????????? ??? char??? *out=NULL;

????????????????????

???????????????????? ??? b=BIO_new_file("bf.txt","w");

???????????????????? ??? len=BIO_write(b,"openssl",4);

len=BIO_printf(b,"%s","zcp");

??????????????????????????? BIO_free(b);??

??????????????????????????? b=BIO_new_file("bf.txt","r");

??????????????????????????? len=BIO_pending(b);

??????????????????????????? len=50;

??????????????????????????? out=(char *)OPENSSL_malloc(len);

??????????????????????????? len=1;

??????????????????????????? while(len>0)

??????????????????????????? {????

??????????????????????????? ?????? len=BIO_read(b,out+outlen,1);

?????????????????????????????????? outlen+=len;

??????????????????????????? }

??????????????????????????? BIO_free(b);

??????????????????????????? free(out);

???????????????????? ??? return 0;

???????????????????? }

7.4.3?? socket bio

服務端:

????????????? #include <stdio.h>

????????????? #include <openssl/bio.h>

????????????? #include <string.h>

?????????????

????????????? int???? main()

????????????? {

???????????????????? BIO????????????????????? *b=NULL,*c=NULL;

???????????????????? int???????????????????????? sock,ret,len;

???????????????????? char?????????????? *addr=NULL;

???????????????????? char?????????????? out[80];

?????????????

???????????????????? sock=BIO_get_accept_socket("2323",0);

???????????????????? b=BIO_new_socket(sock, BIO_NOCLOSE);

???????????????????? ret=BIO_accept(sock,&addr);

???????????????????? BIO_set_fd(b,ret,BIO_NOCLOSE);

???????????????????? while(1)

???????????????????? {

??????????????????????????? memset(out,0,80);

??????????????????????????? len=BIO_read(b,out,80);

??????????????????????????? if(out[0]=='q')

?????????????????????????????????? break;

??????????????????????????? printf("%s",out);

???????????????????? }

???????????????????? BIO_free(b);

???????????????????? return 0;

?????? }

?????? 客戶端telnet此端口成功后,輸入字符,服務端會顯示出來(linux下需要輸入回車)。

??????

?????? 客戶端:

#include <openssl/bio.h>

?????? int??? main()

?????? {

????????????? BIO *cbio, *out;

??????? int len;

??????? char tmpbuf[1024];

??????

??????? cbio = BIO_new_connect("localhost:http");

??????? out = BIO_new_fp(stdout, BIO_NOCLOSE);

??????? if(BIO_do_connect(cbio) <= 0)

??????? {

??????? ?????? fprintf(stderr, "Error connecting to server\n");

??????? }

??????? BIO_puts(cbio, "GET / HTTP/1.0\n\n");

??????? for(;;)

??????? {

?????????????? len = BIO_read(cbio, tmpbuf, 1024);

????????????? ?if(len <= 0) break;

?????????????? BIO_write(out, tmpbuf, len);

??????? }

??????? BIO_free(cbio);

??????? BIO_free(out);

??????? return 0;

??? }

??? 說明:本示例用來獲取本機的web服務信息。

??? cbio = BIO_new_connect("localhost:http");用來生成建立連接到本地web服務的BIO。

??? out = BIO_new_fp(stdout, BIO_NOCLOSE);生成一個輸出到屏幕的BIO。

??? BIO_puts(cbio, "GET / HTTP/1.0\n\n");通過BIO發(fā)送數(shù)據(jù)。

??? len = BIO_read(cbio, tmpbuf, 1024);將web服務響應的數(shù)據(jù)寫入緩存,此函數(shù)循環(huán)調(diào)用

??? 直到無數(shù)據(jù)。

?????? BIO_write(out, tmpbuf, len);通過BIO打印收到的數(shù)據(jù)。

7.4.4?? md BIO

?????? ?????? #include <openssl/bio.h>

????????????? #include <openssl/evp.h>

??????

????????????? int???? main()

????????????? {

???????????????????? BIO????????????????????? *bmd=NULL,*b=NULL;

???????????????????? const????? EVP_MD *md=EVP_md5();

???????????????????? int???????????????????????? len;

???????????????????? char?????????????? tmp[1024];

?

???????????????????? bmd=BIO_new(BIO_f_md());

???????????????????? BIO_set_md(bmd,md);

???????????????????? b= BIO_new(BIO_s_null());

???????????????????? b=BIO_push(bmd,b);

???????????????????? len=BIO_write(b,"openssl",7);

???????????????????? len=BIO_gets(b,tmp,1024);

???????????????????? BIO_free(b);

???????????????????? return 0;

?????? }

?????? 說明:本示例用md BIO對字符串"opessl"進行md5摘要。

?????? bmd=BIO_new(BIO_f_md());生成一個md BIO。

?????? BIO_set_md(bmd,md);設置md BIO 為md5 BIO。

?????? b= BIO_new(BIO_s_null());生成一個null BIO。

?????? b=BIO_push(bmd,b);構(gòu)造BIO 鏈,md5 BIO在頂部。

?????? len=BIO_write(b,"openssl",7);將字符串送入BIO做摘要。

?????? len=BIO_gets(b,tmp,1024);將摘要結(jié)果寫入tmp緩沖區(qū)。

7.4.5?? cipher BIO

?????? 加/解密示例:

?????? #include <string.h>

?????? #include <openssl/bio.h>

?????? #include <openssl/evp.h>

?

?????? int???? main()

?????? {

????????????? /* 加密 */

????????????? BIO????????????????????? *bc=NULL,*b=NULL;

????????????? const??????????????????? EVP_CIPHER *c=EVP_des_ecb();

????????????? int???????????????????????? len,i;

????????????? char?????????????? tmp[1024];

????????????? unsigned char key[8],iv[8];

?

????????????? for(i=0;i<8;i++)

????????????? {

???????????????????? memset(&key[i],i+1,1);

???????????????????? memset(&iv[i],i+1,1);

????????????? }

?

????????????? bc=BIO_new(BIO_f_cipher());

????????????? BIO_set_cipher(bc,c,key,iv,1);

????????????? b= BIO_new(BIO_s_null());

????????????? b=BIO_push(bc,b);

????????????? len=BIO_write(b,"openssl",7);

????????????? len=BIO_read(b,tmp,1024);

????????????? BIO_free(b);

?

????????????? /* 解密 */

????????????? BIO????????????????????? *bdec=NULL,*bd=NULL;

????????????? const??????????????????? EVP_CIPHER *cd=EVP_des_ecb();

?

????????????? bdec=BIO_new(BIO_f_cipher());

????????????? BIO_set_cipher(bdec,cd,key,iv,0);

????????????? bd= BIO_new(BIO_s_null());

????????????? bd=BIO_push(bdec,bd);

????????????? len=BIO_write(bdec,tmp,len);

????????????? len=BIO_read(bdec,tmp,1024);

????????????? BIO_free(bdec);

????????????? return 0;

?????? }

?????? 說明:本示例采用cipher BIO對字符串"openssl"進行加密和解密,本示例編譯需要用c++編譯器;

?????? 關鍵說明:

?????? BIO_set_cipher(bc,c,key,iv,1);設置加密BI。

?????? BIO_set_cipher(bdec,cd,key,iv,0);設置解密BIO。

?????? 其中key為對稱密鑰,iv為初始化向量。

?????? 加/解密結(jié)果通過BIO_read獲取。

7.4.6?? ssl BIO

?????? 編程示例:

#include <openssl/bio.h>

#include <openssl/ssl.h>

?

int???? main()

{

?????? ?????? BIO *sbio, *out;

??? int len;

??? ?????? char tmpbuf[1024];

??? SSL_CTX *ctx;

??? ?????? SSL *ssl;

??????

?????? ?????? SSLeay_add_ssl_algorithms();

?????? ?????? OpenSSL_add_all_algorithms();

?????? ?????? ctx = SSL_CTX_new(SSLv3_client_method());

?????? ?????? sbio = BIO_new_ssl_connect(ctx);

?????? ?????? BIO_get_ssl(sbio, &ssl);

?????? ?????? if(!ssl)

?????? ?????? {

??? ?????? ?????fprintf(stderr, "Can not locate SSL pointer\n");

????????????? ?????? ?return 0;

?????? ?????? }

?????? ?????? SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

?????? ?????? BIO_set_conn_hostname(sbio, "mybank.icbc.com.cn:https");

??? out = BIO_new_fp(stdout, BIO_NOCLOSE);

?????? BIO_printf(out,”鏈接中….\n”);

??? ?????? if(BIO_do_connect(sbio) <= 0)

?????? ?????? {

?????? ?????? ?????? fprintf(stderr, "Error connecting to server\n");

????????????? ?????? return 0;

?????? ?????? }

?????? ?????? if(BIO_do_handshake(sbio) <= 0)

?????? ?????? {

????????????? ?????? fprintf(stderr, "Error establishing SSL connection\n");

?????? ????????????? return 0;

??? ?????? }

?????? ?????? BIO_puts(sbio, "GET / HTTP/1.0\n\n");

??? ?????? for(;;)

?????? ?????? {

????????????? ?????? len = BIO_read(sbio, tmpbuf, 1024);

??????? if(len <= 0) break;

??? ?????? ????BIO_write(out, tmpbuf, len);

??? ?????? }

?????? ?????? BIO_free_all(sbio);

?????? ?????? BIO_free(out);

?????? ?????? return 0;

}

本函數(shù)用ssl bio來鏈接mybank.icbc.com.cn的https服務,并請求首頁文件。其中SSLeay_add_ssl_algorithms和OpenSSL_add_all_algorithms函數(shù)必不可少,否則不能找到ssl加密套件并且不能找到各種算法。

7.4.7?? 其他示例

?????? #include <openssl/bio.h>

#include <openssl/asn1.h>

int??? main()

{

?????? ?????? int?????????? ret,len,indent;

?????? ?????? BIO??????? *bp;

?????? ?????? char *pp,buf[5000];

?????? ?????? FILE?????? *fp;

?

?????? ?????? bp=BIO_new(BIO_s_file());

?????? ?????? BIO_set_fp(bp,stdout,BIO_NOCLOSE);

?????? ?????? fp=fopen("der.cer","rb");

?????? ?????? len=fread(buf,1,5000,fp);

?????? ?????? fclose(fp);

?????? ?????? pp=buf;

?????? ?????? indent=5;

?????? ?????? ret=BIO_dump_indent(bp,pp,len,indent);

?????? ?????? BIO_free(bp);

?????? ?????? return 0;

}

?

總結(jié)

以上是生活随笔為你收集整理的《openssl编程》之BIO的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。