• 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/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
    ",one->name);
            printf("sutdent age : %d
    ",one->age);
            printf("student otherinfo : %s
    
    
    ",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

    运行

    image

    程序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
    ",a->name);
        printf("age  :%d
    ",a->age);
        printf("otherInfo : %s
    ",a->otherInfo);
    }
    
    static void PrintValue_arg(Student *a,void *b)
    {
        int flag=0;
    
        flag=*(int *)b;
        printf("用户输入参数为:%d
    ",flag);
        printf("name :%s
    ",a->name);
        printf("age  :%d
    ",a->age);
        printf("otherInfo : %s
    ",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.
    ");
            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!
    ");
            lh_free(h);
            return -1;
        }
        else
        {
            s5=data;
            printf("
    
    student name : %s
    ",s5->name);
            printf("sutdent age  : %d
    ",s5->age);
            printf("student otherinfo : %s
    ",s5->otherInfo);
            lh_free(h);
        }
        
        getchar();
        return 0;
    }

    编译

    gcc example2.c -o example2 -L/usr/lib -lssl -lcrypto

    运行

    image

    程序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

    运行

    image

    程序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
    ",loaded_name);
    
        }
        flags=DSO_flags(d);
        printf("current falgs is %d
    ",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
    
    ");
        BIO_free(test);
        DSO_free(d);
        printf("handle in dso number is : %d
    ",d->meth_data->num);
        DSO_free(d);
        printf("handle in dso number is : %d
    ",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
    ", out);
    
        /*释放资源*/
        OPENSSL_free(out);
        BIO_free(b);
        return 0;
    }

    编译

    gcc example5.1.c -o example5.1 -L/usr/lib -lssl -lcrypto

    运行

    image

    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
    ",out);
        
        /*释放资源*/
        BIO_free(b);
        free(out);
        return 0;
    }

    编译

    gcc example5.2.c -o example5.2 -L/usr/lib -lssl -lcrypto

    运行

    image

    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
    ",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
    ");
        }
        
        /*发送消息*/
        BIO_puts(cbio, "GET / HTTP/1.0
    
    ");
        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

    运行

    image

    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

    运行

    image

    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
    ");
            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,"链接中….
    ");
        if(BIO_do_connect(sbio) <= 0)
        {
            fprintf(stderr, "Error connecting to server
    ");
            return 0;
        }
        if(BIO_do_handshake(sbio) <= 0)
        {
            fprintf(stderr, "Error establishing SSL connection
    ");
            return 0;
        }
        BIO_puts(sbio, "GET / HTTP/1.0
    
    ");
        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

    运行

    image

    程序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!
    ");
            return -1;
        }
    #endif
    
        /*读取配置并打印*/
        p=NCONF_get_string(conf,NULL,"certs");
        if(p==NULL)
            printf("no global certs info
    ");
        p=NCONF_get_string(conf,"CA_default","certs");
        printf("%s
    ",p);
        
        p=NCONF_get_string(conf,"CA_default","default_days");
        printf("%s
    ",p);
        
        ret=NCONF_get_number_e(conf,"CA_default","default_days",&result);
        printf("%d
    ",result);
        
        ret=NCONF_get_number(conf,"CA_default","default_days",&result);
        printf("%d
    ",result);
        
        /*释放资源*/
        NCONF_free(conf);
        
        return 0;
    }

    编译

    gcc example6.1.c -o example6.1 -L/usr/lib -lssl -lcrypto

    运行

    image

    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!
    ");
            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 :
    ");
        for(i=0; i<num; i++)
        {
            one=sk_CONF_VALUE_value(v,i);
            printf("%s = %s
    ",one->name,one->value);
        }
        
        /*释放资源*/
        BIO_free(bp);
        
        return 0;
    }

    编译

    gcc example6.2.c -o example6.2 -L/usr/lib -lssl -lcrypto

    运行

    image

    程序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!
    ");
                break;
            }
            else
            {
                printf("not enough sedded!
    ");
                RAND_poll();
            }
        }
        
        p=RAND_file_name(filename,50);
        if(p==NULL)
        {
            printf("can not get rand file
    ");
            return -1;
        }
        
        ret=RAND_write_file(p);
        len=RAND_load_file(p,1024);
        ret=RAND_bytes(out, 20);
        if(ret!=1)
        {
            printf("err.
    ");
            return -1;
        }
        print=BIO_new(BIO_s_file());
        BIO_set_fp(print,stdout,BIO_NOCLOSE);
        BIO_write(print,out,20);
        BIO_write(print,"
    ",2);
        
        /*释放资源*/
        BIO_free(print);
        RAND_cleanup();
        
        return 0;
    }

    编译

    gcc example7.c -o example7 -L/usr/lib -lssl -lcrypto

    运行

    image

    程序9:openssl错误处理

    #include <openssl/err.h>
    #include <openssl/bn.h>
    
    int mycb(const char *a,size_t b,void *c)
    {
        printf("my print : %s
    ",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
    ",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
    ",err,file,line,data);
        err=ERR_peek_error();
        printf("ERR_peek_error err: %ld
    ",err);
        err=ERR_peek_error_line(&file,&line);
        printf("ERR_peek_error_line err : %ld,file : %s,line: %d
    ",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
    ",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
    ",err,file,line,data);
        if(err!=0)
        {
            p=ERR_lib_error_string(err);
            printf("ERR_lib_error_string : %s
    ",p);
        }
        
        err=ERR_get_error();
        if(err!=0)
        {
            printf("ERR_get_error err : %ld
    ",err);
            efunc=ERR_func_error_string(err);
            printf("err func : %s
    ",efunc);
            elib=ERR_lib_error_string(err);
            printf("err lib : %s
    ",efunc);
            ereason=ERR_reason_error_string(err);
            printf("err reason : %s
    ",efunc);
            efunc=ERR_func_error_string(err);
            printf("err func : %s
    ",efunc);
            elib=ERR_lib_error_string(err);
            printf("err lib : %s
    ",efunc);
            ereason=ERR_reason_error_string(err);
            printf("err reason : %s
    ",efunc);
            ERR_error_string(err,estring);
            printf("ERR_error_string : %s
    ",estring);
            ERR_error_string_n(err,estring,sizeof(estring));
            printf("ERR_error_string_n : %s
    ",estring);
        }
        err=ERR_get_error_line(&file,&line);
        printf("err file :%s , err line : %d
    ",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!
    ",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

    运行

    image

    程序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!
    ");
            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.
    ");
        }
        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

    运行

    image

    //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解码错误!
    ");
        }
        else
        {
            printf("DER解码成功!
    ");
        }
        
        /*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解码错误!
    ");
        }
        else
        {
            printf("DER解码成功!
    ");
        }
        X509_REQ_free(*req2);
        free(req2);
        return 0;
    }

    编译

    gcc -g example10.1b.c -o example10.1b -L/usr/lib -lssl -lcrypto

    运行

    image

    程序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!
    ");
            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

    运行

    image

    程序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
    ");
            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
    ");
    
            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
    ", 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
    ", 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
    ",
                    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
  • 相关阅读:
    一个Winform下DataGridView控件外观的自定义类
    从以往子类化跟踪MouseLeave深入讨论VB6的自定义Hook类
    使用VB6写一个自定义的进度信息框窗口
    C#研究OpenXML之路(4-使用第三方库)
    Access SQL实现连续及不连续Rank排名
    C#研究OpenXML之路(3-OpenXMLSDKToolV25.msi)
    C#研究OpenXML之路(2-DocumentFormat.OpenXml命名空间)
    C#研究OpenXML之路(1-新建工作簿文件)
    统一我的博客文章的CSS样式代码
    C#图片灰度处理(位深度24→位深度8)
  • 原文地址:https://www.cnblogs.com/274914765qq/p/4398969.html
Copyright © 2020-2023  润新知