一、簡介
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/old/1.0.1/openssl-1.0.1l.tar.gz
2、編譯安裝
http://www.cnblogs.com/274914765qq/p/4548980.html
三、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