简介
OpenSSL是一个功能丰富且自包含的开源安全工具箱。它提供的主要功能有:SSL协议实现(包括SSLv2、SSLv3和TLSv1)、大量软算法(对称/非对称/摘要)、大数运算、非对称算法密钥生成、ASN.1编解码库、证书请求(PKCS10)编解码、数字证书编解码、CRL编解码、OCSP协议、数字证书验证、PKCS7标准实现和PKCS12个人数字证书格式实现等功能。
OpenSSL采用C语言作为开发语言,这使得它具有优秀的跨平台性能。OpenSSL支持Linux、UNIX、windows、Mac等平台。OpenSSL目前最新的版本是openssl-1.0.0e.
编译安装
1、资源下载
http://www.openssl.org/source/openssl-1.0.0e.tar.gz
2、编译安装
tar –zxvf openssl-1.0.0e.tar.gz
cd openssl-1.0.0e
./config
make
make install
API文档
http://www.openssl.org/docs/crypto/crypto.html
http://www.openssl.org/docs/ssl/ssl.html
编程示例
程序1:openssl堆栈示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/safestack.h>
#define sk_Student_new(st) SKM_sk_new(Student, (st))
#define sk_Student_new_null() SKM_sk_new_null(Student)
#define sk_Student_free(st) SKM_sk_free(Student, (st))
#define sk_Student_num(st) SKM_sk_num(Student, (st))
#define sk_Student_value(st, i) SKM_sk_value(Student, (st), (i))
#define sk_Student_set(st, i, val) SKM_sk_set(Student, (st), (i), (val))
#define sk_Student_zero(st) SKM_sk_zero(Student, (st))
#define sk_Student_push(st, val) SKM_sk_push(Student, (st), (val))
#define sk_Student_unshift(st, val) SKM_sk_unshift(Student, (st), (val))
#define sk_Student_find(st, val) SKM_sk_find(Student, (st), (val))
#define sk_Student_delete(st, i) SKM_sk_delete(Student, (st), (i))
#define sk_Student_delete_ptr(st, ptr) SKM_sk_delete_ptr(Student, (st), (ptr))
#define sk_Student_insert(st, val, i) SKM_sk_insert(Student, (st), (val), (i))
#define sk_Student_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(Student, (st), (cmp))
#define sk_Student_dup(st) SKM_sk_dup(Student, st)
#define sk_Student_pop_free(st, free_func) SKM_sk_pop_free(Student, (st), (free_func))
#define sk_Student_shift(st) SKM_sk_shift(Student, (st))
#define sk_Student_pop(st) SKM_sk_pop(Student, (st))
#define sk_Student_sort(st) SKM_sk_sort(Student, (st)) typedef struct Student_st
{
char *name;
int age;
char *otherInfo;
} Student; typedef STACK_OF(Student) Students; Student *Student_Malloc()
{
Student *a=malloc(sizeof(Student));
a->name=(char *)malloc(sizeof(char)*20);
strcpy(a->name,"zcp");
a->otherInfo=(char *)malloc(sizeof(char)*20);
strcpy(a->otherInfo,"no info");
return a;
} void Student_Free(Student *a)
{
free(a->name);
free(a->otherInfo);
free(a);
}
static int Student_cmp(Student *a,Student *b)
{
int ret;
ret=strcmp(a->name,b->name); /* 只比较关键字 */
return ret;
} int main()
{
Students *s,*snew;
Student *s1,*one,*s2;
int i,num;
s=sk_Student_new_null(); /* 新建一个堆栈对象 */
snew=sk_Student_new(Student_cmp); /* 新建一个堆栈对象 */
s2=Student_Malloc();
sk_Student_push(snew,s2);
i=sk_Student_find(snew,s2);
s1=Student_Malloc();
sk_Student_push(s,s1);
num=sk_Student_num(s);
for(i=0; i<num; i++)
{
one=sk_Student_value(s,i);
printf("student name : %s\n",one->name);
printf("sutdent age : %d\n",one->age);
printf("student otherinfo : %s\n\n\n",one->otherInfo);
}
sk_Student_pop_free(s,Student_Free);
sk_Student_pop_free(snew,Student_Free); return 0;
}
编译
gcc example1.c -o example1 -L/usr/lib -lssl -lcrypto
运行
程序2:openssl哈希表示例
#include <string.h>
#include <openssl/lhash.h> typedef struct Student_st
{
char name[20];
int age;
char otherInfo[200];
} Student; static int Student_cmp(const void *a, const void *b)
{
char *namea=((Student *)a)->name;
char *nameb=((Student *)b)->name;
return strcmp(namea,nameb);
} /* 打印每个值*/
static void PrintValue(Student *a)
{
printf("name :%s\n",a->name);
printf("age :%d\n",a->age);
printf("otherInfo : %s\n",a->otherInfo);
} static void PrintValue_arg(Student *a,void *b)
{
int flag=0; flag=*(int *)b;
printf("用户输入参数为:%d\n",flag);
printf("name :%s\n",a->name);
printf("age :%d\n",a->age);
printf("otherInfo : %s\n",a->otherInfo);
} int main()
{
int flag=11;
_LHASH *h;
Student s1= {"zcp",28,"hu bei"},
s2= {"forxy",28,"no info"},
s3= {"skp",24,"student"},
s4= {"zhao_zcp",28,"zcp's name"},
*s5;
void *data; /*创建哈希表*/
h=lh_new(NULL,Student_cmp);
if(h==NULL)
{
printf("err.\n");
return -1;
}
/*将数据插入哈希表*/
data=&s1;
lh_insert(h,data);
data=&s2;
lh_insert(h,data);
data=&s3;
lh_insert(h,data);
data=&s4;
lh_insert(h,data); /*遍历打印*/
lh_doall(h,PrintValue);
lh_doall_arg(h,PrintValue_arg,(void *)(&flag)); /*查找数据*/
data=lh_retrieve(h,(const void*)"skp");
if(data==NULL)
{
printf("can not find skp!\n");
lh_free(h);
return -1;
}
else
{
s5=data;
printf("\n\nstudent name : %s\n",s5->name);
printf("sutdent age : %d\n",s5->age);
printf("student otherinfo : %s\n",s5->otherInfo);
lh_free(h);
} getchar();
return 0;
}
编译
gcc example2.c -o example2 -L/usr/lib -lssl -lcrypto
运行
程序3:openssl内存管理示例
#include <openssl/crypto.h>
#include <openssl/bio.h> int main()
{
char *p;
BIO *b;
CRYPTO_malloc_debug_init();
CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); /*开户内存记录*/ p=OPENSSL_malloc(4);
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);/*关闭内存记录*/
b=BIO_new_file("leak.log","w");
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
CRYPTO_mem_leaks(b); /*将内存泄露输出到FILE中*/ OPENSSL_free(p);
BIO_free(b);
return 0;
}
编译
gcc example3.c -o example3 -L/usr/lib -lssl -lcrypto
运行
程序4:动态模块加载
#include <openssl/dso.h>
#include <openssl/bio.h>
#include <openssl/safestack.h> int main()
{
DSO *d;
void (*f)();
BIO *(*BIO_newx)(BIO_METHOD *a);
BIO *test;
char *load_name;
const char *loaded_name;
int flags; d=DSO_new();
#if 0
DSO_set_name_converter
DSO_ctrl(d,DSO_CTRL_SET_FLAGS,DSO_FLAG_NO_NAME_TRANSLATION,NULL);
DSO_ctrl(d,DSO_CTRL_SET_FLAGS,DSO_FLAG_NAME_TRANSLATION_EXT_ONLY,NULL);
DSO_ctrl(d,DSO_CTRL_SET_FLAGS,DSO_FLAG_GLOBAL_SYMBOLS,NULL);
/* 最好写成libeay32而不是libeay32.dll, 除非前面调用了DSO_ctrl(d,DSO_CTRL_SET_FLAGS,DSO_FLAG_NO_NAME_TRANSLATION,NULL)否则它会加载libeay32.dll.dll
*/
load_name=DSO_merge(d,"libeay32","D:\\zcp\\OpenSSL\\openssl-0.9.8b\\out32dll\\Debug");
#endif
d=DSO_load(d,"libeay32",NULL,0);
if(d==NULL)
{
printf("err");
return -1;
}
loaded_name=DSO_get_loaded_filename(d);
if(loaded_name!=NULL)
{
printf("loaded file is %s\n",loaded_name); }
flags=DSO_flags(d);
printf("current falgs is %d\n",flags);
DSO_up_ref(d);
f=(void (*)())DSO_bind_var(d,"BIO_new");
BIO_newx=(BIO *(*)(BIO_METHOD *))f;
test=BIO_newx(BIO_s_file());
BIO_set_fp(test,stdout,BIO_NOCLOSE);
BIO_puts(test,"abd\n\n");
BIO_free(test);
DSO_free(d);
printf("handle in dso number is : %d\n",d->meth_data->num);
DSO_free(d);
printf("handle in dso number is : %d\n",d->meth_data->num);
return 0;
}
编译
gcc example4.c -o example4 -L/usr/lib -lssl -lcrypto
程序5:openssl BIO示例
5.1 mem bio
#include <stdio.h>
#include <openssl/bio.h> int main()
{
BIO *b=NULL;
int len=0;
char *out=NULL; /*mem类型的BIO*/
b=BIO_new(BIO_s_mem()); /*写入内容*/
len=BIO_write(b,"openssl",7);
len=BIO_printf(b,"%s","bio test"); /*得到缓冲区中待读取大小*/
len=BIO_ctrl_pending(b);
out=(char *)OPENSSL_malloc(len); /*读取内容并打印*/
len=BIO_read(b,out,len);
printf("%s\n", out); /*释放资源*/
OPENSSL_free(out);
BIO_free(b);
return 0;
}
编译
gcc example5.1.c -o example5.1 -L/usr/lib -lssl -lcrypto
运行
5.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,"hello",5);
len=BIO_printf(b,"%s"," world");
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;
} /*打印读取内容*/
printf("%s\n",out); /*释放资源*/
BIO_free(b);
free(out);
return 0;
}
编译
gcc example5.2.c -o example5.2 -L/usr/lib -lssl -lcrypto
运行
5.3 socket bio
//服务器端
//example5.3s.c
#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); /*建立服务器的BIO*/
b=BIO_new_socket(sock, BIO_NOCLOSE);
ret=BIO_accept(sock,&addr); /*建立输出到屏幕的BIO*/
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\n",out);
} /*释放资源*/
BIO_free(b);
return 0;
}
编译
gcc example5.3s.c -o example5.3s -L/usr/lib -lssl -lcrypto
//客户端
//example5.3c.c
#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
int main()
{
BIO *cbio, *out;
int len;
char tmpbuf[1024]; /*建立连接到本地web服务的BIO*/
cbio = BIO_new_connect("localhost:2323");
out = BIO_new_fp(stdin, BIO_NOCLOSE); /*发出连接请求*/
if(BIO_do_connect(cbio) <= 0)
{
fprintf(stderr, "Error connecting to server\n");
} /*发送消息*/
BIO_puts(cbio, "GET / HTTP/1.0\n\n");
while(1)
{
/*接收输入*/
memset(tmpbuf,0,1024);
scanf("%s",&tmpbuf);
len=strlen(tmpbuf);
BIO_write(out, tmpbuf, len); /*发送*/
len = BIO_write(cbio, tmpbuf, len);
if(len <= 0 || tmpbuf[0]=='q')
break;
} /*释放资源*/
BIO_free(cbio);
BIO_free(out);
return 0;
}
编译
gcc example5.3c.c -o example5.3c -L/usr/lib -lssl -lcrypto
运行
5.4 md BIO
/*本示例用md BIO对字符串"opessl"进行md5摘要*/
#include <stdio.h>
#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]; /*创建一个md BIO*/
bmd=BIO_new(BIO_f_md()); /*设置md BIO 为md5 BIO*/
BIO_set_md(bmd,md); /*创建一个null BIO*/
b= BIO_new(BIO_s_null()); /*构造BIO链,md5 BIO在顶部*/
b=BIO_push(bmd,b); /*将字符串送入BIO做摘要*/
len=BIO_write(b,"openssl",7); /*将摘要结果写入tmp缓冲区并输出*/
len=BIO_gets(b,tmp,1024);
puts(tmp); BIO_free(b);
return 0;
}
编译
gcc example5.4.c -o example5.4 -L/usr/lib -lssl -lcrypto
运行
5.5 ssl BIO
#include <stdio.h>
#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;
}
编译
gcc example5.5.c -o example5.5 -L/usr/lib -lssl -lcrypto
运行
程序6:openssl配置文件示例
6.1
#include <stdio.h>
#include <openssl/conf.h> int main()
{
CONF *conf;
long eline,result;
int ret;
char *p;
BIO *bp;
conf=NCONF_new(NULL); /*打开配置文件*/
#if 0
bp=BIO_new_file("openssl.cnf","r");
NCONF_load_bio(conf,bp,&eline);
#else
ret=NCONF_load(conf,"openssl.cnf",&eline);
if(ret!=1)
{
printf("err!\n");
return -1;
}
#endif /*读取配置并打印*/
p=NCONF_get_string(conf,NULL,"certs");
if(p==NULL)
printf("no global certs info\n");
p=NCONF_get_string(conf,"CA_default","certs");
printf("%s\n",p); p=NCONF_get_string(conf,"CA_default","default_days");
printf("%s\n",p); ret=NCONF_get_number_e(conf,"CA_default","default_days",&result);
printf("%d\n",result); ret=NCONF_get_number(conf,"CA_default","default_days",&result);
printf("%d\n",result); /*释放资源*/
NCONF_free(conf); return 0;
}
编译
gcc example6.1.c -o example6.1 -L/usr/lib -lssl -lcrypto
运行
6.2
#include <stdio.h>
#include <openssl/conf.h> int main()
{
CONF *conf;
BIO *bp;
STACK_OF(CONF_VALUE) *v;
CONF_VALUE *one;
int i,num;
long eline; /*打开并加载配置文件*/
conf=NCONF_new(NULL);
bp=BIO_new_file("openssl.cnf","r");
if(bp==NULL)
{
printf("err!\n");
return -1;
}
NCONF_load_bio(conf,bp,&eline); /*读取配置信息并打印*/
v=NCONF_get_section(conf,"CA_default");
num=sk_CONF_VALUE_num(v);
printf("section CA_default :\n");
for(i=0; i<num; i++)
{
one=sk_CONF_VALUE_value(v,i);
printf("%s = %s\n",one->name,one->value);
} /*释放资源*/
BIO_free(bp); return 0;
}
编译
gcc example6.2.c -o example6.2 -L/usr/lib -lssl -lcrypto
运行
程序7:openssl随机数示例
#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/rand.h> int main()
{
char buf[20];
const char *p;
char out[20],filename[50];
int ret,len;
BIO *print; strcpy(buf,"我的随机数");
RAND_add(buf,20,strlen(buf));
strcpy(buf,"23424d");
RAND_seed(buf,20); while(1)
{
ret=RAND_status(); /*检测熵值*/
if(ret==1)
{
printf("seeded enough!\n");
break;
}
else
{
printf("not enough sedded!\n");
RAND_poll();
}
} p=RAND_file_name(filename,50);
if(p==NULL)
{
printf("can not get rand file\n");
return -1;
} ret=RAND_write_file(p);
len=RAND_load_file(p,1024);
ret=RAND_bytes(out, 20);
if(ret!=1)
{
printf("err.\n");
return -1;
}
print=BIO_new(BIO_s_file());
BIO_set_fp(print,stdout,BIO_NOCLOSE);
BIO_write(print,out,20);
BIO_write(print,"\n",2); /*释放资源*/
BIO_free(print);
RAND_cleanup(); return 0;
}
编译
gcc example7.c -o example7 -L/usr/lib -lssl -lcrypto
运行
程序9:openssl错误处理
#include <openssl/err.h>
#include <openssl/bn.h> int mycb(const char *a,size_t b,void *c)
{
printf("my print : %s\n",a);
return 0;
} int main()
{
BIO *berr;
unsigned long err;
const char *file,*data,*efunc,*elib,*ereason,*p;
int line,flags;
char estring[500];
FILE *fp;
/*
ERR_load_crypto_strings();
*/
ERR_load_BIO_strings();
ERR_clear_error();
berr=BIO_new(BIO_s_file());
BIO_set_fp(berr,stdout,BIO_NOCLOSE);
BIO_new_file("no.exist","r");
err=ERR_peek_last_error();
err=ERR_peek_last_error_line(&file,&line);
printf("ERR_peek_last_error_line err : %ld,file : %s,line: %d\n",err,file,line);
err=ERR_peek_last_error_line_data(&file,&line,&data,&flags);
printf("ERR_peek_last_error_line_data err: %ld,file :%s,line :%d,data :%s\n",err,file,line,data);
err=ERR_peek_error();
printf("ERR_peek_error err: %ld\n",err);
err=ERR_peek_error_line(&file,&line);
printf("ERR_peek_error_line err : %ld,file : %s,line: %d\n",err,file,line);
err=ERR_peek_error_line_data(&file,&line,&data,&flags);
printf("ERR_peek_error_line_data err : %ld,file :%s,line :%d,data :%s\n",err,file,line,data);
err = ERR_get_error_line_data(&file,&line,&data,&flags);
printf("ERR_get_error_line_data err : %ld,file :%s,line :%d,data :%s\n",err,file,line,data);
if(err!=0)
{
p=ERR_lib_error_string(err);
printf("ERR_lib_error_string : %s\n",p);
} err=ERR_get_error();
if(err!=0)
{
printf("ERR_get_error err : %ld\n",err);
efunc=ERR_func_error_string(err);
printf("err func : %s\n",efunc);
elib=ERR_lib_error_string(err);
printf("err lib : %s\n",efunc);
ereason=ERR_reason_error_string(err);
printf("err reason : %s\n",efunc);
efunc=ERR_func_error_string(err);
printf("err func : %s\n",efunc);
elib=ERR_lib_error_string(err);
printf("err lib : %s\n",efunc);
ereason=ERR_reason_error_string(err);
printf("err reason : %s\n",efunc);
ERR_error_string(err,estring);
printf("ERR_error_string : %s\n",estring);
ERR_error_string_n(err,estring,sizeof(estring));
printf("ERR_error_string_n : %s\n",estring);
}
err=ERR_get_error_line(&file,&line);
printf("err file :%s , err line : %d\n",file,line);
ERR_print_errors(berr);
BIO_new_file("no.exist2","r");
fp=fopen("err.log","w");
ERR_print_errors_fp(fp);
fclose(fp);
BIO_new_file("no.exist3","r");
ERR_print_errors_cb(mycb,NULL);
ERR_put_error(ERR_LIB_BN,BN_F_BNRAND,BN_R_BIGNUM_TOO_LONG,__FILE__,
line);
ERR_print_errors(berr);
ERR_load_BN_strings();
ERR_put_error(ERR_LIB_BN,BN_F_BNRAND,BN_R_BIGNUM_TOO_LONG,__FILE__,line);
ERR_print_errors(berr);
ERR_put_error(ERR_LIB_BN,BN_F_BNRAND,BN_R_BIGNUM_TOO_LONG,__FILE__,line);
ERR_set_error_data("set date test!\n",ERR_TXT_STRING); err=ERR_set_mark();
ERR_print_errors(berr);
ERR_free_strings();
BIO_free(berr);
return 0;
}
编译
gcc -g example9.c -o example9 -L/usr/lib -lssl -lcrypto
运行
程序10:openssl证书申请
//example10.1a.c
#include <stdio.h>
#include <string.h>
#include <openssl/x509.h>
#include <openssl/rsa.h> int main()
{
X509_REQ *req;
int ret;
long version;
X509_NAME *name;
EVP_PKEY *pkey;
RSA *rsa;
X509_NAME_ENTRY *entry=NULL;
char bytes[100],mdout[20];
int len,mdlen;
int bits=512;
unsigned long e=RSA_3;
unsigned char *der,*p;
FILE *fp;
const EVP_MD *md;
X509 *x509;
BIO *b;
STACK_OF(X509_EXTENSION) *exts; req=X509_REQ_new();
version=1;
ret=X509_REQ_set_version(req,version);
name=X509_NAME_new();
strcpy(bytes,"openssl");
len=strlen(bytes); entry=X509_NAME_ENTRY_create_by_txt(&entry,"commonName",V_ASN1_UTF8STRING,(unsigned char *)bytes,len);
X509_NAME_add_entry(name,entry,0,-1); strcpy(bytes,"bj");
len=strlen(bytes); entry=X509_NAME_ENTRY_create_by_txt(&entry,"countryName",V_ASN1_UTF8STRING,bytes,len);
X509_NAME_add_entry(name,entry,1,-1); /* subject name */
ret=X509_REQ_set_subject_name(req,name);
/* pub key */
pkey=EVP_PKEY_new();
rsa=RSA_generate_key(bits,e,NULL,NULL);
EVP_PKEY_assign_RSA(pkey,rsa);
ret=X509_REQ_set_pubkey(req,pkey);
/* attribute */
strcpy(bytes,"test");
len=strlen(bytes); ret=X509_REQ_add1_attr_by_txt(req,"organizationName",V_ASN1_UTF8STRING,bytes,len);
strcpy(bytes,"ttt");
len=strlen(bytes); ret=X509_REQ_add1_attr_by_txt(req,"organizationalUnitName",V_ASN1_UTF8STRING,bytes,len);
md=EVP_sha1();
ret=X509_REQ_digest(req,md,mdout,&mdlen);
ret=X509_REQ_sign(req,pkey,md);
if(!ret)
{
printf("sign err!\n");
X509_REQ_free(req);
return -1;
}
/* 写入文件PEM 格式 */
b=BIO_new_file("certreq.txt","w");
PEM_write_bio_X509_REQ(b,req,NULL,NULL);
BIO_free(b); /* DER 编码 */
len=i2d_X509_REQ(req,NULL);
der=malloc(len);
p=der;
len=i2d_X509_REQ(req,&p);
OpenSSL_add_all_algorithms(); ret=X509_REQ_verify(req,pkey);
if(ret<0)
{
printf("verify err.\n");
}
fp=fopen("certreq2.txt","wb");
fwrite(der,1,len,fp);
fclose(fp);
free(der);
X509_REQ_free(req);
return 0;
}
编译
gcc -g example10.1a.c -o example10.1a -L/usr/lib -lssl -lcrypto
运行
//example10.1b.c
#include <stdio.h>
#include <string.h>
#include <openssl/pem.h> int main()
{
BIO *in;
X509_REQ *req=NULL,**req2=NULL;
FILE *fp;
unsigned char buf[1024];
char *p;
int len; /*PEM 格式解码*/
in=BIO_new_file("certreq.txt","r");
req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
if(req==NULL)
{
printf("DER解码错误!\n");
}
else
{
printf("DER解码成功!\n");
} /*DER 格式解码*/
fp=fopen("certreq2.txt","r");
fread(buf,1,1024,fp);
fclose(fp);
p=buf;
len=strlen(buf);
req2=(X509_REQ **)malloc(sizeof(X509_REQ *));
d2i_X509_REQ(req2,&p,len);
if(*req2==NULL)
{
printf("DER解码错误!\n");
}
else
{
printf("DER解码成功!\n");
}
X509_REQ_free(*req2);
free(req2);
return 0;
}
编译
gcc -g example10.1b.c -o example10.1b -L/usr/lib -lssl -lcrypto
运行
程序11:openssl CRL(证书撤销列表)示例
#include <stdio.h>
#include <openssl/x509.h> int main()
{
int ret,len;
unsigned char *buf,*p;
unsigned long e=RSA_3;
FILE *fp;
time_t t;
X509_NAME *issuer;
ASN1_TIME *lastUpdate,*nextUpdate,*rvTime;
X509_CRL *crl=NULL;
X509_REVOKED *revoked;
EVP_PKEY *pkey;
ASN1_INTEGER *serial;
RSA *r;
BIGNUM *bne;
BIO *bp; /* 生成密钥*/
bne=BN_new();
ret=BN_set_word(bne,e);
r=RSA_new();
ret=RSA_generate_key_ex(r,1024,bne,NULL);
if(ret!=1)
{
printf("RSA_generate_key_ex err!\n");
return -1;
}
pkey=EVP_PKEY_new();
EVP_PKEY_assign_RSA(pkey,r); /* 设置版本*/
crl=X509_CRL_new();
ret=X509_CRL_set_version(crl,3); /* 设置颁发者*/
issuer=X509_NAME_new();
ret=X509_NAME_add_entry_by_NID(issuer,NID_commonName,V_ASN1_PRINTABLESTRING, "CRL issuer",10,-1,0);
ret=X509_CRL_set_issuer_name(crl,issuer); /* 设置上次发布时间*/
lastUpdate=ASN1_TIME_new();
t=time(NULL);
ASN1_TIME_set(lastUpdate,t);
ret=X509_CRL_set_lastUpdate(crl,lastUpdate); /* 设置下次发布时间*/
nextUpdate=ASN1_TIME_new();
t=time(NULL);
ASN1_TIME_set(nextUpdate,t+1000);
ret=X509_CRL_set_nextUpdate(crl,nextUpdate); /* 添加被撤销证书序列号*/
revoked=X509_REVOKED_new();
serial=ASN1_INTEGER_new();
ret=ASN1_INTEGER_set(serial,1000);
ret=X509_REVOKED_set_serialNumber(revoked,serial); /* 设置吊销日期*/
rvTime=ASN1_TIME_new();
t=time(NULL);
ASN1_TIME_set(rvTime,t+2000);
ret=X509_CRL_set_nextUpdate(crl,rvTime);
ret=X509_REVOKED_set_revocationDate(revoked,rvTime);
ret=X509_CRL_add0_revoked(crl,revoked); /* 排序*/
ret=X509_CRL_sort(crl); /* 签名*/
ret=X509_CRL_sign(crl,pkey,EVP_md5()); /* 写入文件*/
bp=BIO_new(BIO_s_file());
BIO_set_fp(bp,stdout,BIO_NOCLOSE);
X509_CRL_print(bp,crl);
len=i2d_X509_CRL(crl,NULL);
buf=malloc(len+10);
p=buf;
len=i2d_X509_CRL(crl,&p); fp=fopen("crl.crl","wb");
fwrite(buf,1,len,fp);
fclose(fp); BIO_free(bp);
X509_CRL_free(crl);
free(buf);
getchar(); return 0;
}
编译
gcc -g example11.c -o example11 -L/usr/lib -lssl -lcrypto
运行
程序12:openssl 证书校验示例
/**
* 步骤:
* 1)初始化环境
* a.新建证书存储区X509_STORE_new()
* b.新建证书校验上下文X509_STORE_CTX_new()
*
* 2)导入根证书
* a.读取CA证书,从DER编码格式化为X509结构d2i_X509()
* b.将CA证书导入证书存储区X509_STORE_add_cert()
*
* 3)导入要校验的证书test
* a.读取证书test,从DER编码格式化为X509结构d2i_X509()
* b.在证书校验上下文初始化证书test,X509_STORE_CTX_init()
* c.校验X509_verify_cert
*/ #include <stdio.h>
#include <string.h>
#include <stdlib.h> #include <openssl/evp.h>
#include <openssl/x509.h> #define CERT_PATH "/root/workspace/caroot"
#define ROOT_CERT "ca.crt"
#define WIN71H "client.crt"
#define WIN71Y "win71y.cer" #define GET_DEFAULT_CA_CERT(str) sprintf(str, "%s/%s", CERT_PATH, ROOT_CERT)
#define GET_CUSTOM_CERT(str, path, name) sprintf(str, "%s/%s", path, name) #define MAX_LEGTH 4096 int my_load_cert(unsigned char *str, unsigned long *str_len,
const char *verify_cert, const unsigned int cert_len)
{
FILE *fp;
fp = fopen(verify_cert, "rb");
if ( NULL == fp)
{
fprintf(stderr, "fopen fail\n");
return -1;
} *str_len = fread(str, 1, cert_len, fp);
fclose(fp);
return 0;
} X509 *der_to_x509(const unsigned char *der_str, unsigned int der_str_len)
{
X509 *x509;
x509 = d2i_X509(NULL, &der_str, der_str_len);
if ( NULL == x509 )
{
fprintf(stderr, "d2i_X509 fail\n"); return NULL;
}
return x509;
}
int x509_verify()
{
int ret;
char cert[MAX_LEGTH]; unsigned char user_der[MAX_LEGTH];
unsigned long user_der_len;
X509 *user = NULL; unsigned char ca_der[MAX_LEGTH];
unsigned long ca_der_len;
X509 *ca = NULL; X509_STORE *ca_store = NULL;
X509_STORE_CTX *ctx = NULL;
STACK_OF(X509) *ca_stack = NULL; /* x509初始化 */
ca_store = X509_STORE_new();
ctx = X509_STORE_CTX_new(); /* root ca*/
GET_DEFAULT_CA_CERT(cert);
/* 从文件中读取 */
my_load_cert(ca_der, &ca_der_len, cert, MAX_LEGTH);
/* DER编码转X509结构 */
ca = der_to_x509(ca_der, ca_der_len);
/* 加入证书存储区 */
ret = X509_STORE_add_cert(ca_store, ca);
if ( ret != 1 )
{
fprintf(stderr, "X509_STORE_add_cert fail, ret = %d\n", ret);
goto EXIT;
} /* 需要校验的证书 */
GET_CUSTOM_CERT(cert, CERT_PATH, WIN71H);
my_load_cert(user_der, &user_der_len, cert, MAX_LEGTH);
user = der_to_x509(user_der, user_der_len); ret = X509_STORE_CTX_init(ctx, ca_store, user, ca_stack);
if ( ret != 1 )
{
fprintf(stderr, "X509_STORE_CTX_init fail, ret = %d\n", ret);
goto EXIT;
} //openssl-1.0.1c/crypto/x509/x509_vfy.h
ret = X509_verify_cert(ctx);
if ( ret != 1 )
{
fprintf(stderr, "X509_verify_cert fail, ret = %d, error id = %d, %s\n",
ret, ctx->error, X509_verify_cert_error_string(ctx->error));
goto EXIT;
}
EXIT:
X509_free(user);
X509_free(ca); X509_STORE_CTX_cleanup(ctx);
X509_STORE_CTX_free(ctx); X509_STORE_free(ca_store); return ret == 1 ? 0 : -1;
} int main()
{
OpenSSL_add_all_algorithms();
x509_verify();
return 0;
}
编译
gcc -g example12.c -o example12 -L/usr/local/ssl/lib -lssl -lcrypto -I/usr/local/ssl/include