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\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

运行

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\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

运行

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\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

运行

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\n",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\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

运行

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\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

运行

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!\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

运行

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!\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

运行

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!\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

运行

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\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

运行

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!\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

运行

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解码错误!\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

运行

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!\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

运行

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\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
第一章 基础知识 81.1 对称算法 81.2摘要算法 81.3 公钥算法 91.4 回调函数 11第二章 openssl简介 132.1 openssl简介 132.2 openssl安装 132.2.1 linux下的安装 132.2.2 windows编译与安装 132.3 openssl源代码 142.4 openssl学习方法 16第三章openssl堆栈 173.1 openssl堆栈 173.2 数据结构 173.3 源码 173.4 定义用户自己的堆栈函数 183.5 编程示例 19第四章 openssl哈希表 214.1 哈希表 214.2 哈希表数据结构 214.3 函数说明 224.4 编程示例 24第五章 openssl内存分配 275.1 openssl内存分配 275.2 内存数据结构 275.3 主要函数 285.4 编程示例 28第六章 Openssl动态模块加载 316.1 动态库加载 316.2 DSO概述 316.3 数据结构 316.4 编程示例 32第七章 openssl抽象IO 357.1 openssl抽象IO 357.2 数据结构 357.3 BIO 函数 367.4 编程示例 377.4.1 mem bio 377.4.2 file bio 377.4.3 socket bio 387.4.4 md BIO 407.4.5 cipher BIO 407.4.6 ssl BIO 417.4.7 其他示例 43第八章 Openssl配置文件 448.1 概述 448.2 openssl配置文件读取 448.3 主要函数 448.4 编程示例 45第九章 Openssl随机数 479.1 随机数 479.2 openssl随机数数据结构与源码 479.3 主要函数 489.4 编程示例 49第十章 Openssl文本数据库 5110.1 概述 5110.2 数据结构 5110.3 函数说明 5210.4 编程示例 52第十一章 Openssl大数 5511.1 介绍 5511.2 openssl大数表示 5511.3 大数函数 5511.4 使用示例 58第十二章 Openssl base64编解码 6512.1 BASE64编码介绍 6512.2 BASE64编解码原理 6512.3 主要函数 6612.4 编程示例 66第十三章 Openssl ASN1库 6913.1 ASN1简介 6913.2 DER编码 7013.3 ASN1基本类型示例 7113.4 openssl 的ASN.1库 7313.5 用openssl的ASN.1库DER编码 7413.6 Openssl的ASN.1宏 7513.7 ASN1常用函数 7613.8 属性证书编码 90第十四章 Openssl错误处理 9414.1 概述 9414.2 数据结构 9414.3 主要函数 9614.4 编程示例 98第十五章 Openssl摘要与HMAC 10115.1 概述 10115.2 openssl摘要实现 10115.3 函数说明 10115.4 编程示例 10215.5 HMAC 103第十六章 Openssl数据压缩 10516.1 简介 10516.2 数据结构 10516.3 函数说明 10616.4 openssl中压缩算法协商 10616.5 编程示例 107第十七章 Openssl RSA 10817.1 RSA介绍 10817.2 openssl的RSA实现 10817.3 RSA签名与验证过程 10917.4 数据结构 10917.4.1 RSA_METHOD 10917.4.2 RSA 11017.5 主要函数 11117.6编程示例 11217.6.1密钥生成
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值