日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《openssl编程》之BIO

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

第七章???抽象IO

7.1??? openssl抽象IO

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

7.2????數據結構

?????? BIO數據結構主要有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;

該結構定義了IO操作的各種回調函數,根據需要,具體的bio類型必須實現其中的一種或多種回調函數,各項意義如下:

type:具體BIO類型;

name:具體BIO的名字;

bwrite:具體BIO寫操作回調函數;

bread:具體BIO讀操作回調函數;

bputs:具體BIO中寫入字符串回調函數;

bgets:具體BIO中讀取字符串函數;

ctrl:具體BIO的控制回調函數;

create:生成具體BIO回調函數;

destroy:銷毀具體BIO回調函數;

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

?????? 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關聯一個文件指針時,該標記則置1;socket BIO中通過BIO_set_fd關聯一個鏈接時設置該標記為1。

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

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

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

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

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

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

references:被引用數量。

num_read:BIO中已讀取的字節數。

num_write:BIO中已寫入的字節數。

ex_data:用于存放額外數據。

7.3??? BIO?函數

BIO各個函數定義在crypto/bio.h中。所有的函數都由BIO_METHOD中的回調函數來實現。函數主要分為幾類:

1)? 具體BIO相關函數

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

2)? 通用抽象函數

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

另外,有很多函數是由宏定義通過控制函數BIO_ctrl實現,比如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);得到緩沖區中待讀取大小。

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

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發送數據。

??? len = BIO_read(cbio, tmpbuf, 1024);將web服務響應的數據寫入緩存,此函數循環調用

??? 直到無數據。

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

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);構造BIO 鏈,md5 BIO在頂部。

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

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

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為初始化向量。

?????? 加/解密結果通過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;

}

本函數用ssl bio來鏈接mybank.icbc.com.cn的https服務,并請求首頁文件。其中SSLeay_add_ssl_algorithms和OpenSSL_add_all_algorithms函數必不可少,否則不能找到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;

}

?

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。