《openssl编程》之BIO
第七章 抽象IO
BIO数据结构主要有2个,在crypto/bio.h中定义如下:
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 *);
long (*callback_ctrl)(BIO *, int, bio_info_cb *);
该结构定义了IO操作的各种回调函数,根据需要,具体的bio类型必须实现其中的一种或多种回调函数,各项意义如下:
callback_ctrl:具体BIO控制回调函数,与ctrl回调函数不一样,该函数可由调用者(而不是实现者)来实现,然后通过BIO_set_callback等函数来设置。
/* 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 flags; /* extra storage */
struct bio_st *next_bio; /* used by filter BIOs */
struct bio_st *prev_bio; /* used by filter BIOs */
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用来存放链接字。
next_bio:下一个BIO地址,BIO数据可以从一个BIO传送到另一个BIO,该值指明了下一个BIO的地址。
BIO各个函数定义在crypto/bio.h中。所有的函数都由BIO_METHOD中的回调函数来实现。函数主要分为几类:
比如:BIO_new_file(生成新文件)和BIO_get_fd(设置网络链接)等。
另外,有很多函数是由宏定义通过控制函数BIO_ctrl实现,比如BIO_set_nbio、BIO_get_fd和BIO_eof等等。
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缓冲区。
out=(char *)OPENSSL_malloc(len);
sock=BIO_get_accept_socket("2323",0);
b=BIO_new_socket(sock, BIO_NOCLOSE);
BIO_set_fd(b,ret,BIO_NOCLOSE);
客户端telnet此端口成功后,输入字符,服务端会显示出来(linux下需要输入回车)。
cbio = BIO_new_connect("localhost:http");
out = BIO_new_fp(stdout, BIO_NOCLOSE);
fprintf(stderr, "Error connecting to server\n");
BIO_puts(cbio, "GET / HTTP/1.0\n\n");
len = BIO_read(cbio, tmpbuf, 1024);
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相关推荐
- openssl 编程。 证书制作
首页 博客 学院 下载 GitChat TinyMind 论坛 问答 商城 VIP 活动 写博客 发Chat 登录注册 么刚的专栏 RSS订阅 原 openssl证书制作及编程 2010年07月29日 ...
- 网络编程中BIO和NIO的区别
网络编程中BIO和NIO的区别 先上结论 BIO中,每个请求因为要阻塞直到结果返回,所以比较好的解决是每个请求都需要一个线程来处理,但是线程又是他的制约条件. NIO中,每个请求进来都会绑定到一个ch ...
- 《openssl 编程》之 RSA(转)
17.1 RSA介绍 RSA算法是一个广泛使用的公钥算法.其密钥包括公钥和私钥.它能用于数字签名.身份认证以及密钥交换.RSA密钥长度一般使用1024位或者更高.RSA密钥信息主要包括[1]: Ø ...
- 《openssl 编程》之 DH
第十九章DH 19.1 DH算法介绍 DH算法是W.Diffie和M.Hellman提出的.此算法是最早的公钥算法.它实质是一个通信双方进行密钥协商的协议:两个实体中的任何一个使用自己的私钥和另一实 ...
- 《openssl 编程》之错误处理
第十四章 错误处理 14.1 概述 程序设计时,一般通过函数的返回值来判断是否调用成功.设计良好的函数以及好的错误处理能帮助调用者快速找到错误原因.错误处理应该尽可能多的包含各种信息,包括: Ø ...
- 《openssl 编程》之文本数据库
第十章 文本数据库 10.1 概述 Openss实现了一个简单的文本数据库,它可以从文件读取数据和将数据写到文件中,并且可以根据关键字段来查询数据.Openssl的文本数据库供apps/目录下的 ...
- 《openssl编程》之配置文件
第八章 配置文件 8.1 概述 Openssl采用自定义的配置文件来获取配置信息.Openssl的配置文件主要由如下内容组成: 注释信息,注释信息由#开头: 段信息,段信息由[xxx]来表示,其中xx ...
- OPENSSL编程 第二十章 椭圆曲线
20.1 ECC介绍 椭圆曲线算法可以看作是定义在特殊集合下数的运算,满足一定的规则.椭圆曲线在如下两个域中定义:Fp域和F2m域. Fp域,素数域,p为素数: F2m域:特征为2的有限域,称之为二 ...
- 笔记整理——使用openssl编程
error: openssl 的所有解决方案 (2013/6/22 17:39:00) error: openssl/crypto.h: No such file or directory 解决方案 ...
最新文章
- R语言数据结构之列表
- 如何上手深度学习中的图像处理?有这个代码资源库就够了
- [译]NGINX 和 ZooKeeper,动态负载平衡和部署(上)
- ROS探索总结(二)——ROS总体框架
- python 修改csv某一列_使用python更改CSV中的列值
- publiccms中,怎么修改默认的端口8080以及默认上下文名称
- 数据结构中基本查找算法总结
- 在windows文件系统中加右键执行程序
- 如何在Ubuntu中修改默认程序
- Android阅读手札:第一行代码(第一章)
- 在Apache中隐藏Php文件后缀
- 全屏显示一个图片文件
- Matlab分析dac模拟信号,[滤波器在音频DAC测试中的应用] 音频滤波器
- 对InputStream,OutputStream,Reader,Writer的详解
- 谷歌地球不能用了,我推荐个替代方案,免费软件
- 公司 | 四年狂奔,少儿编程准独角兽小码王的盈利逻辑是什么?
- 攻防世界逆向入门maze详解
- 财经365热点:当阿里巴巴不再讲“中台”
- 分别编写计算球的表面积和体积的函数area和volume。在主函数中输入球的半径,分别调用函数area和volume计算并输出球的表面积和体积。
- 2、yum和epel是什么