程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> OpenSSL編程,openssl編程趙春平

OpenSSL編程,openssl編程趙春平

編輯:關於C語言

OpenSSL編程,openssl編程趙春平


一、簡介

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved