openssl demo1

#define sprintf_s sprintf       

#include "stdafx.h"      

#include <LOCALE.H>      

#include "ca.h"      

#include <OPENSSL pem.h>      

#include <OPENSSL x509.h>      

#include <OPENSSL x509v3.h>      

#include <OPENSSL pkcs12.h>      

#include <OPENSSL rand.h>      

#include <STDLIB.H>      

#include <STDIO.H>      

#include <OPENSSL engine.h>      

#define EXT_COPY_NONE   0      

#define EXT_COPY_ADD    1      

#define EXT_COPY_ALL    2      

     

     

BOOL APIENTRY DllMain( HANDLE hModule,      

                       DWORD  ul_reason_for_call,      

                       LPVOID lpReserved     

                     )     

{     

    return TRUE;     

}     

     

/*此函数可以将DER、PEM、P12文件公钥读出来*/     

X509 *load_cert(BIO *cert/*输入BIO*/, int format/*格式*/,char * pwd,/*P12密码*/     

                char * outMsg) //从DER、PEM、P12格式中读取公钥证书      

{     

    X509 * x=NULL;     

    if  (format == DER)     

        x=d2i_X509_bio(cert,NULL);     

    else if (format == PEM)     

        x=PEM_read_bio_X509(cert,NULL,NULL,NULL);//PEM_read_bio_X509_AUX      

    else if (format == P12)     

    {     

        PKCS12 *p12 = d2i_PKCS12_bio(cert, NULL);     

        PKCS12_parse(p12, pwd, NULL, &x, NULL);     

        PKCS12_free(p12);     

        p12 = NULL;     

    }     

    else     

    {     

             

sprintf_s(outMsg,"bad input format specified for input cert\n");     

        goto end;     

    }     

end:     

    if (x == NULL)     

    {     

        sprintf(outMsg,"unable to load certificate\n");     

    }     

    return(x);     

}     

     

X509 * LoadCert(char * cert,int certlen,char * outMsg)//枚举DER/PEM格式      

{     

    BIO * in=NULL;     

    X509 * x509=NULL;     

     

    if(certlen==0)//输入为磁盘文件      

    {     

        if((in=BIO_new_file(cert, "r")) == NULL)     

        {     

            sprintf(outMsg,"open CA certificate file error");     

            return NULL;     

        }     

    }     

    else//输入为内存中文件      

    {     

        if((in=BIO_new_mem_buf(cert,certlen))== NULL)//只读类型      

        {     

            sprintf(outMsg,"Make Mem Bio Error");     

            return NULL;     

        }     

    }     

    if((x509=load_cert(in,DER,NULL,outMsg))==NULL)//尝试DER      

    {     

        BIO_reset(in);//恢复bio      

        x509=load_cert(in,PEM,NULL,outMsg);//尝试PEM      

    }     

    if (in != NULL) BIO_free(in);     

    return x509;     

}     

     

EVP_PKEY *load_key(BIO *bio, int format, char *pass,char * outMsg)//枚举DER/PEM格式      

{     

    EVP_PKEY *pkey=NULL;     

     

    if (format == DER)     

    {     

        pkey=d2i_PrivateKey_bio(bio, NULL);     

    }     

    else if (format == PEM)     

    {     

        pkey=PEM_read_bio_PrivateKey(bio,NULL,NULL,pass);     

    }     

    else if (format == P12)     

    {     

        PKCS12 *p12 = d2i_PKCS12_bio(bio, NULL);     

        PKCS12_parse(p12, pass, &pkey, NULL, NULL);     

        PKCS12_free(p12);     

        p12 = NULL;     

    }     

    else     

    {     

        sprintf(outMsg,"bad input format specified for key\n");     

        goto end;     

    }     

end:     

    if (pkey == NULL)     

        sprintf(outMsg,"unable to load Private Key\n");     

    return(pkey);     

}     

     

EVP_PKEY * LoadKey(char * key,int keylen,char * pass,char * outMsg)     

{     

    EVP_PKEY *pkey=NULL;     

    BIO * in=NULL;     

     

    if(keylen==0)//输入为磁盘文件      

    {     

        if((in=BIO_new_file(key, "r")) == NULL)     

        {     

            sprintf(outMsg,"open CA certificate file error");     

            return NULL;     

        }     

    }     

    else//输入为内存中文件      

    {     

        if((in=BIO_new_mem_buf(key,keylen))== NULL)//只读类型      

        {     

            sprintf(outMsg,"Make Mem Bio Error");     

            return NULL;     

        }     

    }     

     

    if((pkey=load_key(in,DER,pass,outMsg))==NULL)//尝试DER      

    {     

        BIO_reset(in);//BIO是可读写的,那么该BIO所有数据都会被清空;      

                        //如果该BIO是只读的,那么该操作只会简单将指      

                        //针指向原始位置,里面的数据可以再读.      

        pkey=load_key(in,PEM,pass,outMsg);//尝试PEM      

    }     

    if (in != NULL) BIO_free(in);     

    return pkey;     

}     

int Rand(const char *file,int dont_warn,char * outMsg)//产生随机数,return 0 ---成功      

{     

    int consider_randfile = (file == NULL);     

    char buffer[200];     

         

    RAND_screen();     

    if (file == NULL)     

        file = RAND_file_name(buffer, sizeof buffer);     

    else if (RAND_egd(file) > 0)     

    {     

    /* we try if the given filename is an EGD socket.   

        if it is, we don't write anything back to the file. */     

        return 1;     

    }     

    if (file == NULL || !RAND_load_file(file, -1))     

    {     

        if (RAND_status() == 0 && !dont_warn)     

        {     

            sprintf(outMsg,"unable to load 'random state'\n");     

            sprintf(outMsg,"This means that the random number generator has not been seeded\n");     

            if (consider_randfile) /* explanation does not apply when a file is explicitly named */     

            {     

                sprintf(outMsg,"Consider setting the RANDFILE environment variable to point at a file that\n");     

                sprintf(outMsg,"'random' data can be kept in (the file will be overwritten).\n");     

            }     

        }     

        return 0;     

    }     

    return 1;     

}     

     

     

/ end      

//      

/ begin //      

     

/* Add extension using V3 code: we can set the config file as NULL   

* because we wont reference any other sections.   

*/     

int Add_ExtCert(X509 *cert/*正被添加的证书*/,X509 * root/*根证书(从中得到信息)*/, int nid, char *value)     

{     

    X509_EXTENSION *ex;     

    X509V3_CTX ctx;     

    /* This sets the 'context' of the extensions. */     

    /* No configuration database */     

    //  X509V3_set_ctx_nodb(&ctx);      

    /* Issuer and subject certs: both the target since it is self signed,   

    * no request and no CRL   

    */     

    X509V3_set_ctx(&ctx,root, cert, NULL, NULL, 0);     

    ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);     

    if (!ex)     

        return 0;     

         

    X509_add_ext(cert,ex,-1);     

    X509_EXTENSION_free(ex);     

    return 1;     

}     

     

bool Add_Name(X509_NAME * x509name,int type/*c\cn*/,char * iput/*中国*/,     

              int ilen/*输入长度*/,char * outMsg)//支持中文名称      

{     

    wchar_t * ws,wc;     

    ASN1_STRING stmp, *str = &stmp;     

    UCHAR cbuf[256]={0};     

    int wslen, wcnt,i;     

    char input[256]={0};     

    strncpy(input, iput, ilen);     

    wslen = strlen(input) + 1;     

    if(wslen==1)     

        return true;     

  ws =new unsigned short[sizeof(wchar_t) * wslen];       

    if ((wcnt = mbstowcs(ws, input, wslen)) == -1)     

    {     

        sprintf(outMsg,"mbstowcs convert error");     

        delete ws;     

        return false;                    

    }     

    for(i=0;i<(int)wcslen(ws);i++)     

    {      

        wc=ws[i];     

        cbuf[2*i]=wc/256;     

        cbuf[2*i+1]=wc%256;     

    }     

     

    ASN1_mbstring_copy(&str, cbuf, 2*wslen, MBSTRING_BMP, B_ASN1_UTF8STRING);     

    X509_NAME_add_entry_by_NID(x509name,type,V_ASN1_UTF8STRING,stmp.data,stmp.length, -1, 0);     

    delete ws;     

    return true;     

}     

bool mkRoot(stuSUBJECT * rootInfo,X509 **x509p/*out公钥*/, EVP_PKEY **pkeyp/*out私钥*/,      

           int bits/*位数*/, int serial/*序列号*/, int days/*有效期*/,char * out/*操作结果*/)     

{     

    X509 *x;     

    EVP_PKEY *pk;     

    RSA *rsa;     

    X509_NAME *name=NULL;     

    int i=0,len=0;     

    if ((pkeyp == NULL) || (*pkeyp == NULL))     

    {     

        if ((pk=EVP_PKEY_new()) == NULL)     

        {     

            abort();      

            return false;     

        }     

    }     

    else     

        pk= *pkeyp;     

         

    if ((x509p == NULL) || (*x509p == NULL))     

    {     

        if ((x=X509_new()) == NULL)     

            goto err;     

    }     

    else     

        x= *x509p;     

     

    Rand(NULL,1,out);//产生随机数种子      

    rsa=RSA_generate_key(bits,RSA_F4,0/*回调函数callback*/,NULL);//产生密钥对,//RSA存储了公钥私钥      

    if (!EVP_PKEY_assign_RSA(pk,rsa))//完成RSA密钥的pkey结构初始工作,当pk不为NULL的时候,返回1,否则返回0      

    {     

        abort();     

        goto err;     

    }     

    rsa=NULL;     

         

    X509_set_version(x,2);//版本号,显示+1      

    ASN1_INTEGER_set(X509_get_serialNumber(x),serial);//序列号      

    X509_gmtime_adj(X509_get_notBefore(x),0);//起始时间      

    X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);//结束时间      

    X509_set_pubkey(x,pk);//公钥      

         

    name=X509_get_subject_name(x);     

         

    /* This function creates and adds the entry, working out the   

    * correct string type and performing checks on its length.   

    * Normally we'd check the return value for errors   

    */     

     

    //C-国家,ST-省,L-城市,O-组织,OU-部门,CN-个体,T-title,D-description,G-givenName,I-initials,      

    //Email-emailAddress,S-surname,SN-serialNumber,dnQualifier-dnQualifier,unstructuredName,challengePassword,unstructuredAddress,      

     

    setlocale(LC_CTYPE, "");     

     

    Add_Name(name,NID_countryName,(char *)rootInfo->C,sizeof(rootInfo->C),out);     

    Add_Name(name,NID_stateOrProvinceName,(char *)rootInfo->ST,sizeof(rootInfo->ST),out);     

    Add_Name(name,NID_localityName,(char *)rootInfo->L,sizeof(rootInfo->L),out);     

    Add_Name(name,NID_organizationName,(char *)rootInfo->O,sizeof(rootInfo->O),out);     

    Add_Name(name,NID_organizationalUnitName,(char *)rootInfo->OU,sizeof(rootInfo->OU),out);     

    Add_Name(name,NID_commonName,(char *)rootInfo->CN,sizeof(rootInfo->CN),out);     

    Add_Name(name,NID_pkcs9_emailAddress,(char *)rootInfo->MAIL,sizeof(rootInfo->MAIL),out);     

    Add_Name(name,NID_email_protect,(char *)rootInfo->PMAIL,sizeof(rootInfo->PMAIL),out);     

     

         

    Add_Name(name,NID_title,(char *)rootInfo->T,sizeof(rootInfo->T),out);     

    Add_Name(name,NID_description,(char *)rootInfo->D,sizeof(rootInfo->D),out);     

    Add_Name(name,NID_givenName,(char *)rootInfo->G,sizeof(rootInfo->G),out);      

    Add_Name(name,NID_initials,(char *)rootInfo->I,sizeof(rootInfo->I),out);     

    Add_Name(name,NID_name,(char *)rootInfo->NAME,sizeof(rootInfo->NAME),out);         

    Add_Name(name,NID_surname,(char *)rootInfo->S,sizeof(rootInfo->S),out);     

    Add_Name(name,NID_dnQualifier,(char *)rootInfo->QUAL,sizeof(rootInfo->QUAL),out);     

    Add_Name(name,NID_pkcs9_unstructuredName,(char *)rootInfo->STN,sizeof(rootInfo->STN),out);     

    Add_Name(name,NID_pkcs9_challengePassword,(char *)rootInfo->PW,sizeof(rootInfo->PW),out);     

    Add_Name(name,NID_pkcs9_unstructuredAddress,(char *)rootInfo->ADD,sizeof(rootInfo->ADD),out);     

     

    /* Its self signed so set the issuer name to be the same as the   

    * subject.   

    */     

         

    X509_set_issuer_name(x,name);//设置发行者名称等同于上面的      

     

    //加入扩展信息      

    /* Add various extensions: standard extensions */     

    Add_ExtCert(x,x,NID_basic_constraints, "critical,CA:TRUE");     

    //主题密钥标示符---当发行者有多个签名密钥时      

    Add_ExtCert(x,x,NID_subject_key_identifier, "hash");     

    //颁发机构密钥标示符      

    Add_ExtCert(x,x,NID_authority_key_identifier, "keyid:always");     

    //密钥用法      

    Add_ExtCert(x,x,NID_key_usage, "nonRepudiation,digitalSignature,keyEncipherment");     

    Add_ExtCert(x,x,NID_domainComponent, "no");      

    Add_ExtCert(x,x,NID_Domain, "no");     

    /* Some Netscape specific extensions */     

//  Add_ExtCert(x, NID_netscape_cert_type, "sslCA");      

//  Add_ExtCert(x, NID_netscape_comment, "example comment extension");//netscape_comment      

         

         

    /* Maybe even add our own extension based on existing */     

    //加入自定义信息begin      

//  int nid;      

//  nid = OBJ_create("1.2.3.4.9", "Hpxs", "I love you!");      

//  X509V3_EXT_add_alias(nid, NID_netscape_comment);      

//  Add_ExtCert(x, nid, "I love you");      

    //加入自定义信息end      

    X509V3_EXT_cleanup();//cleanup the extension code if any custom extensions have been added      

    if (!X509_sign(x,pk,EVP_sha1()))//签名算法EVP_sha1,EVP_md5,用私钥签名公钥      

    {     

        strcpy(out,"证书签名失败");     

        goto err;     

    }     

    *x509p=x;     

    *pkeyp=pk;     

    return true;     

err:     

    return false;     

}     

     

     

BOOL MakeRoot(stuSUBJECT * rootInfo,/*信息*/int bits/*位数*/, int serial/*序列号*/,      

              int days/*有效期*/,char * certFile/*证书文件*/,char * priFile/*私钥文件*/,     

              char * outMsg/*操作结果*/,int type/*类型pem-der*/)     

{     

         

    X509 *x509=NULL;     

    EVP_PKEY *pkey=NULL;     

    BIO * bcert=NULL,* bkey=NULL;     

    bool ret=true;     

    int i=0,j=0;     

     

    if(((bcert=BIO_new_file(certFile, "w"))== NULL)||((bkey=BIO_new_file(priFile, "w")) == NULL))     

    {     

        strcpy(outMsg,"Create File Error");     

        return false;     

    }     

    if(mkRoot(rootInfo,&x509,&pkey,bits,serial,days,outMsg))     

    {     

        if (type==DER)     

        {     

            i=i2d_X509_bio(bcert,x509);//returns 1 for success       

            j=i2d_PrivateKey_bio(bkey,pkey);     

        }     

        else if(type==PEM)     

        {     

            i=PEM_write_bio_X509(bcert,x509);     

            j=PEM_write_bio_PrivateKey(bkey,pkey,NULL,NULL,0,NULL, NULL);     

        }     

        if(!i||!j)     

        {     

            ret=false;     

            strcpy(outMsg,"Save Cert or Key File Error");     

        }     

    }     

    else     

        ret=false;     

    BIO_free(bcert);     

    BIO_free(bkey);     

    X509_free(x509);     

    EVP_PKEY_free(pkey);     

    return ret;     

     

}     

     

/ end      

//      

/ begin //      

     

/* Add extension using V3 code: we can set the config file as NULL   

 * because we wont reference any other sections.   

 */     

int Add_ExtReq(STACK_OF(X509_REQUEST) *sk, int nid, char *value)     

{     

    X509_EXTENSION *ex;     

    ex = X509V3_EXT_conf_nid(NULL, NULL, nid, value);     

    if (!ex)     

        return 0;     

    sk_X509_EXTENSION_push(sk, ex);     

         

    return 1;     

}     

         

int mkReq(stuSUBJECT * reqInfo,X509_REQ **req, EVP_PKEY **pkeyp, int bits,char * out)     

{     

    X509_REQ *x;     

    EVP_PKEY *pk;     

    RSA *rsa;     

    X509_NAME *name=NULL;     

    ASN1_STRING stmp, *str = &stmp;     

         

    STACK_OF(X509_EXTENSION) *exts = NULL;     

         

    if ((pk=EVP_PKEY_new()) == NULL)     

        goto err;     

         

    if ((x=X509_REQ_new()) == NULL)     

        goto err;     

    Rand(NULL,1,out);//产生随机数种子      

    rsa=RSA_generate_key(bits,RSA_F4,0/*回调函数callback*/,NULL);//产生密钥对      

    //PEM_write_bio_RSAPrivateKey      

    if (!EVP_PKEY_assign_RSA(pk,rsa))     

        goto err;     

         

    rsa=NULL;     

         

    X509_REQ_set_pubkey(x,pk);     

         

    name=X509_REQ_get_subject_name(x);     

         

    /* This function creates and adds the entry, working out the   

    * correct string type and performing checks on its length.   

    * Normally we'd check the return value for errors   

    */     

     

    setlocale(LC_CTYPE, "");     

     

    Add_Name(name,NID_countryName,(char *)reqInfo->C,sizeof(reqInfo->C),out);     

    Add_Name(name,NID_stateOrProvinceName,(char *)reqInfo->ST,sizeof(reqInfo->ST),out);     

    Add_Name(name,NID_localityName,(char *)reqInfo->L,sizeof(reqInfo->L),out);     

    Add_Name(name,NID_organizationName,(char *)reqInfo->O,sizeof(reqInfo->O),out);     

    Add_Name(name,NID_organizationalUnitName,(char *)reqInfo->OU,sizeof(reqInfo->OU),out);     

    Add_Name(name,NID_commonName,(char *)reqInfo->CN,sizeof(reqInfo->CN),out);     

    Add_Name(name,NID_pkcs9_emailAddress,(char *)reqInfo->MAIL,sizeof(reqInfo->MAIL),out);     

    Add_Name(name,NID_email_protect,(char *)reqInfo->PMAIL,sizeof(reqInfo->PMAIL),out);     

     

    Add_Name(name,NID_title,(char *)reqInfo->T,sizeof(reqInfo->T),out);     

    Add_Name(name,NID_description,(char *)reqInfo->D,sizeof(reqInfo->D),out);     

    Add_Name(name,NID_givenName,(char *)reqInfo->G,sizeof(reqInfo->G),out);     

    Add_Name(name,NID_initials,(char *)reqInfo->I,sizeof(reqInfo->I),out);     

    Add_Name(name,NID_name,(char *)reqInfo->NAME,sizeof(reqInfo->NAME),out);       

    Add_Name(name,NID_surname,(char *)reqInfo->S,sizeof(reqInfo->S),out);     

    Add_Name(name,NID_dnQualifier,(char *)reqInfo->QUAL,sizeof(reqInfo->QUAL),out);     

    Add_Name(name,NID_pkcs9_unstructuredName,(char *)reqInfo->STN,sizeof(reqInfo->STN),out);     

    Add_Name(name,NID_pkcs9_challengePassword,(char *)reqInfo->PW,sizeof(reqInfo->PW),out);     

    Add_Name(name,NID_pkcs9_unstructuredAddress,(char *)reqInfo->ADD,sizeof(reqInfo->ADD),out);     

     

     

    /* Certificate requests can contain extensions, which can be used   

        * to indicate the extensions the requestor would like added to    

        * their certificate. CAs might ignore them however or even choke   

        * if they are present.   

    */     

         

    /* For request extensions they are all packed in a single attribute.   

    * We save them in a STACK and add them all at once later   

    */     

         

    exts = sk_X509_EXTENSION_new_null();     

    /* Standard extenions */     

    //主题备用名称,URL:http://my.url.here/、支持email  copy      

    Add_ExtReq(exts, NID_subject_alt_name, "DNS:localhost,email:hpxs@hotmail.com,RID:1.2.3.4,URI:192.168.2.22,IP:C0A80216");     

     

    //加入自定义扩展      

    int nid;     

    nid = OBJ_create("1.3.6.1.4.1.5315.100.2.5", "UserID", "User ID Number");     

    X509V3_EXT_add_alias(nid, NID_netscape_comment);     

    Add_ExtReq(exts, nid, "ID130203197703060618");     

    /* Now we've created the extensions we add them to the request */     

     

    X509_REQ_add_extensions(x, exts);     

    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);       

    X509V3_EXT_cleanup();//cleanup the extension code if any custom extensions have been added      

         

    if (!X509_REQ_sign(x,pk,EVP_sha1()))//用自己的公钥签名私钥      

        goto err;     

         

    *req=x;     

    *pkeyp=pk;     

    return(1);     

err:     

    return(0);     

}     

     

BOOL MakeReq(stuSUBJECT * reqInfo,/*请求信息*/int bits/*位数*/,char * reqFile/*证书请求文件*/,     

             char * priFile/*私钥文件*/,char * outMsg/*操作结果*/,int type)     

{     

    X509_REQ *req=NULL;     

    EVP_PKEY *pkey=NULL;     

    BIO * breq=NULL,* bkey=NULL;     

    int i=0,j=0;     

    if(((breq=BIO_new_file(reqFile, "w"))== NULL)||((bkey=BIO_new_file(priFile, "w")) == NULL))     

    {     

        strcpy(outMsg,"Create File Error");     

        return false;     

    }     

    if(!mkReq(reqInfo,&req,&pkey,bits,outMsg))     

    {     

        strcpy(outMsg,"Make CertReq Error");     

        return false;     

    }     

     

    if(type==PEM)     

    {     

        i=PEM_write_bio_X509_REQ(breq,req);          

        j=PEM_write_bio_PrivateKey(bkey,pkey,NULL,NULL,0,NULL, NULL);     

    }     

    else if(type==DER)     

    {     

        i=i2d_X509_REQ_bio(breq,req);     

        j=i2d_PrivateKey_bio(bkey,pkey);     

    }     

    BIO_free(breq);     

    BIO_free(bkey);     

    X509_REQ_free(req);     

    EVP_PKEY_free(pkey);     

    if(!i||!j)     

    {     

        strcpy(outMsg,"Save Cert or Key File Error");     

        return false;     

    }     

    return true;     

}     

// end //      

     

/// begin      

int copy_extensions(X509 *x, X509_REQ *req, int copy_type)//在证书中加入req自带扩展信息      

{     

    STACK_OF(X509_EXTENSION) *exts = NULL;     

    X509_EXTENSION *ext, *tmpext;     

    ASN1_OBJECT *obj;     

    int i, idx, ret = 0;     

    if (!x || !req || (copy_type == EXT_COPY_NONE))     

        return 1;     

    exts = X509_REQ_get_extensions(req);     

         

    for(i = 0; i < sk_X509_EXTENSION_num(exts); i++)     

    {     

        ext = sk_X509_EXTENSION_value(exts, i);     

        obj = X509_EXTENSION_get_object(ext);     

        idx = X509_get_ext_by_OBJ(x, obj, -1);     

        /* Does extension exist? */     

        if (idx != -1)      

        {     

            /* If normal copy don't override existing extension */     

            if (copy_type == EXT_COPY_ADD)     

                continue;     

            /* Delete all extensions of same type */     

            do     

            {     

                tmpext = X509_get_ext(x, idx);     

                X509_delete_ext(x, idx);     

                X509_EXTENSION_free(tmpext);     

                idx = X509_get_ext_by_OBJ(x, obj, -1);     

            } while (idx != -1);     

        }     

        if (!X509_add_ext(x, ext, -1))     

            goto end;     

    }     

         

    ret = 1;     

         

end:     

         

    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);     

         

    return ret;     

}     

     

     

int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,int serial,     

            char *startdate, char *enddate, int days,X509_REQ * req,stuKEYUSAGE * KUSAGE,     

            stuEKEYUSAGE * EKUSAGE,char * outMsg)     

{     

    X509_NAME *name=NULL,*CAname=NULL;     

    X509 *ret=NULL;     

    X509_CINF *ci;     

    EVP_PKEY *pktmp;     

    int ok= -1,i=0;     

//  STACK_OF (X509_EXTENSION) * req_exts;//如何释放??      

    char kusage[160]={0};     

    char ekusage[360]={0};     

    name=X509_REQ_get_subject_name(req);     

    if ((ret=X509_new()) == NULL)      

    {     

        ok=0;     

        goto err;     

    }     

    ci=ret->cert_info;     

     

    /* Make it an X509 v3 certificate. 版本1扩展*/     

    if (!X509_set_version(ret,2L)) //版本      

    {     

        ok=0;     

        goto err;     

    }     

         

    ASN1_INTEGER_set(X509_get_serialNumber(ret),serial);//序列号      

     

    if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))//发行者      

    {     

        ok=0;     

        goto err;     

    }     

         

    if (strcmp(startdate,"today") == 0)     

        X509_gmtime_adj(X509_get_notBefore(ret),0);//开始日期      

    else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);     

         

    if (enddate == NULL)     

        X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);//结束日期      

    else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);     

         

    if (!X509_set_subject_name(ret,name)) //主体 ---所有者      

    {     

        ok=0;     

        goto err;     

    }     

         

    pktmp=X509_REQ_get_pubkey(req);     

    i = X509_set_pubkey(ret,pktmp);//公钥      

    EVP_PKEY_free(pktmp);     

    if (!i)      

    {     

        ok=0;     

        goto err;     

    }     

         

    //加入req自带扩展信息,生成REQ文件时候加入的      

    if (!copy_extensions(ret, req, EXT_COPY_ALL))     

    {     

        strcpy("加入自带扩展信息失败",outMsg);     

        goto err;     

    }     

     

    /* Lets add the extensions, if there are any 加入标准扩展*/     

     

    //基本限制Note if the CA option is false the pathlen option should be omitted.       

    Add_ExtCert(ret,ret,NID_basic_constraints, "critical,CA:FALSE,pathlen:1");     

     

    //主题密钥标示符--------区分拥有者多对密钥      

    Add_ExtCert(ret,ret,NID_subject_key_identifier, "hash");     

     

    //Authority密钥标示符----区分发行者有多个签名密钥时      

    Add_ExtCert(ret,x509, NID_authority_key_identifier, "keyid,issuer:always");     

         

     

    //密钥用法 ----数字签名、不可否认性、密钥加密、数据加密、密钥协商、证书签名、      

    //CRL签名、仅仅加密、仅仅解密      

             

    if(KUSAGE->DS)     

        strcpy(kusage,"digitalSignature");     

    if(KUSAGE->NR)     

        if(strlen(kusage))//添加      

            strcat(kusage, ",nonRepudiation");     

        else     

            strcpy(kusage,"nonRepudiation");     

    if(KUSAGE->KE)     

        if(strlen(kusage))//添加      

            strcat(kusage, ",keyEncipherment");     

        else     

            strcpy(kusage,"keyEncipherment");     

    if(KUSAGE->DE)     

        if(strlen(kusage))//添加      

            strcat(kusage, ",dataEncipherment");     

        else     

            strcpy(kusage,"dataEncipherment");     

    if(KUSAGE->KA)     

        if(strlen(kusage))//添加      

            strcat(kusage, ",keyAgreement");     

        else     

            strcpy(kusage,"keyAgreement");     

    if(KUSAGE->KC)     

        if(strlen(kusage))//添加      

            strcat(kusage, ",keyCertSign");     

        else     

            strcpy(kusage,"keyCertSign");     

    if(KUSAGE->CS)     

        if(strlen(kusage))//添加      

            strcat(kusage, ",cRLSign");     

        else     

            strcpy(kusage,"cRLSign");     

    if(KUSAGE->EO)     

        if(strlen(kusage))//添加      

            strcat(kusage, ",encipherOnly");     

        else     

            strcpy(kusage,"encipherOnly");     

    if(KUSAGE->DO)     

        if(strlen(kusage))//添加      

            strcat(kusage, ",decipherOnly");     

        else     

            strcpy(kusage,"decipherOnly");     

    if(strlen(kusage))     

        Add_ExtCert(ret,ret, NID_key_usage, kusage);     

     

    //增强型密钥用法--一般只用于末端证书RFC3280      

    //增强用法     证书目的      

    //--------------------------------------------------------------------------------------------------------------      

    //服务器验证          保证远程计算机的身份           

    //客户端验证      向远程计算机证明您的身份       

    //代码签名           确保软件来自软件发行商         

    //安全电子邮件         保护软件在发行后不被改动       

    //时间戳            保护电子邮件消息          

    //--------------------------------------------------------------------------------------------------------------      

    //                  保证软件来自一个软件发行商      

    //                  保护软件在发行后不被改动。      

    //                  保证软件来自商业软件发行商      

    //                  允许您用数字签名证书信任列表      

    //                  允许联机事务处理/通讯的严格加密      

    //                  允许加密磁盘上的数据      

    //                  智能卡登录      

    //IP安全终端系统           允许 Internet 上的安全通讯           

    //IP安全隧道终止             

    //IP 安全用户                 

    //--------------------------------------------------------------------------------------------------------------      

     

    if(EKUSAGE->SA)     

        strcpy(ekusage,"serverAuth");     

    if(EKUSAGE->CA)     

        if(strlen(ekusage))//添加      

            strcat(ekusage,",clientAuth");     

        else     

            strcpy(ekusage,"clientAuth");     

    if(EKUSAGE->CS)     

        if(strlen(ekusage))//添加      

            strcat(ekusage,",codeSigning");     

        else     

            strcpy(ekusage,"codeSigning");     

    if(EKUSAGE->EP)     

        if(strlen(ekusage))//添加      

            strcat(ekusage,",emailProtection");     

        else     

            strcpy(ekusage,"emailProtection");     

    if(EKUSAGE->TS)     

        if(strlen(ekusage))//添加      

            strcat(ekusage,",timeStamping");     

        else     

            strcpy(ekusage,"timeStamping");     

    if(EKUSAGE->msCC)     

        if(strlen(ekusage))//添加      

            strcat(ekusage,",msCodeCom");     

        else     

            strcpy(ekusage,"msCodeCom");     

    if(EKUSAGE->msCTLS)     

        if(strlen(ekusage))//添加      

            strcat(ekusage,",msCTLSign");     

        else     

            strcpy(ekusage,"msCTLSign");     

    if(EKUSAGE->msSGC)     

        if(strlen(ekusage))//添加      

            strcat(ekusage,",msSGC");     

        else     

            strcpy(ekusage,"msSGC");     

    if(EKUSAGE->msEFS)     

        if(strlen(ekusage))//添加      

            strcat(ekusage,",msEFS");     

        else     

            strcpy(ekusage,"msEFS");     

    if(EKUSAGE->msSC)     

        if(strlen(ekusage))//添加      

            strcat(ekusage,",msSmartcardLogin");     

        else     

            strcpy(ekusage,"msSmartcardLogin");     

    if(EKUSAGE->IP)     

        if(strlen(ekusage))//添加      

            strcat(ekusage,",ipsecEndSystem,ipsecTunnel,ipsecUser");     

        else     

            strcpy(ekusage,"ipsecEndSystem,ipsecTunnel,ipsecUser");     

    if(strlen(ekusage))     

    Add_ExtCert(ret,ret,NID_ext_key_usage,ekusage);     

     

    /*   

    Application         keyUsage  Values    

    SSL Client          digitalSignature    

    SSL Server          keyEncipherment    

    S/MIME Signing      digitalSignature    

    S/MIME Encryption   keyEncipherment    

    Certificate         Signing keyCertSign    

    Object Signing      digitalSignature */     

     

    //颁发者备用名称,URL:http://my.url.here/、不支持email  copy      

    Add_ExtCert(ret,ret, NID_issuer_alt_name, "DNS:hpxs,email:hpxs@hotmail.com,RID:1.2.3.4,URI:https://hpxs,IP:192.168.0.22");     

     

    //证书策略      

    Add_ExtCert(ret,ret,NID_certificate_policies,"OK");     

    //颁发机构信息访问      

    Add_ExtCert(ret,ret,NID_info_access,"OCSP;URI:https://hpxs");//或者caIssuers;URI:http://my.ca/ca.html     

    //CRL分发点      

    Add_ExtCert(ret,x509, NID_crl_distribution_points, "URI:https://hpxs/hpxs.crl");     

     

    /* Some Netscape specific extensions */     

//  Add_ExtCert(ret,ret, NID_crl_number, "sslCA");      

     

//  Add_ExtCert(ret,x509, NID_netscape_comment, "See http://cert.umd.edu/root for details.");      

    /* In each case the 'value' of the extension is placed directly in the   

    extension. Currently supported extensions in this category are: nsBaseUrl,   

    nsRevocationUrl, nsCaRevocationUrl, nsRenewalUrl, nsCaPolicyUrl,   

    nsSslServerName and nsComment   */     

     

//  Add_ExtCert(ret,x509, NID_netscape_cert_type, "client, server, email,objsign, reserved, sslCA,emailCA, objCA");      

    /*nsCertType (netscape certificate type) takes the flags: client, server, email,   

    objsign, reserved, sslCA, emailCA, objCA.*/     

    /* Maybe even add our own extension based on existing */     

    //加入自定义信息begin      

    int nid;     

    nid = OBJ_create("1.2.3.4.9", "Hpxs", "I love OpenSSL!");     

    X509V3_EXT_add_alias(nid, NID_netscape_comment);     

    Add_ExtCert(ret,ret, nid, "I love OpenSSL");     

    //加入自定义信息end      

    X509V3_EXT_cleanup();//cleanup the extension code if any custom extensions have been added      

     

    if (!X509_sign(ret,pkey,dgst))//加入签名,签名算法      

    {     

        ok=0;     

        goto err;     

    }     

    ok=1;     

err:     

    if (CAname != NULL)     

        X509_NAME_free(CAname);     

    if (ok <= 0)     

    {     

        if (ret != NULL) X509_free(ret);     

        ret=NULL;     

    }     

    else     

        *xret=ret;     

    return(ok);     

}     

     

int certify(X509 **xret, X509_REQ *req, EVP_PKEY *pkey, X509 *x509,const EVP_MD *dgst,     

                   int serial, char *startdate, char *enddate, int days,stuKEYUSAGE * KUSAGE,     

                   stuEKEYUSAGE * EKUSAGE,char * outMsg)     

{//返回公钥证书,请求文件,根私钥,根公钥,      

    EVP_PKEY *pktmp=NULL;     

    int ok= -1,i=0;      

    if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)//得到公钥      

    {     

        sprintf(outMsg,"error unpacking public key\n");     

        ok=0;     

        goto err;     

    }     

    i=X509_REQ_verify(req,pktmp);//证书请求里面有私要签名,这里验证一下,看此公钥主人是否持有私钥      

    EVP_PKEY_free(pktmp);     

    if (i < 0)     

    {     

        ok=0;     

        sprintf(outMsg,"Signature verification problems.\n");     

        goto err;     

    }     

    if (i == 0)     

    {     

        ok=0;     

        sprintf(outMsg,"Signature did not match the certificate request\n");     

        goto err;     

    }     

         

    ok=do_body(xret,pkey,x509,dgst,serial,startdate, enddate,     

        days,req,KUSAGE,EKUSAGE,outMsg);     

         

err:     

    return(ok);     

}     

     

     

BOOL MakeCert(char *certfile/*根证书公钥*/,int certlen,/*为0则certfile为磁盘文件,否则为内存区域*/     

              char *keyfile/*根证书私钥*/,int keylen,int serial/*序列号*/,char *enddate/*作废日期*/,     

              int days/*有效期*/, char *reqfile/*请求文件*/,stuKEYUSAGE * KUSAGE/*密钥用法*/,     

              stuEKEYUSAGE * EKUSAGE/*增强密钥用法*/,char *outfile/*结果文件*/,     

              char * outMsg/*操作结果*/,int type/*结果类型DER,PEM*/)//通过证书请求,得到证书      

{     

    int ret=1;     

    char * md=NULL;     

    EVP_PKEY *pkey=NULL;     

    X509 * x509=NULL;     

    X509_REQ *req=NULL;     

    X509 * x=NULL;     

    BIO * bcert=NULL,* reqbio=NULL;     

    int j;     

    const EVP_MD *dgst=NULL;     

     

    OpenSSL_add_all_digests();//加入签名算法      

     

    if((reqbio=BIO_new_file(reqfile, "r")) == NULL)     

    {     

        ret=0;     

        goto err;     

    }     

         

    if ((req=PEM_read_bio_X509_REQ(reqbio,NULL,NULL,NULL)) == NULL)//PEM_read_X509_REQ       

    {     

        BIO_reset(reqbio);     

        if ((req=d2i_X509_REQ_bio(reqbio,NULL)) == NULL)     

        {     

            sprintf(outMsg,"Error get certificate request");     

            ret=0;     

            goto err;     

        }     

    }     

     

    pkey=LoadKey(keyfile,keylen,NULL,outMsg);     

    if (pkey == NULL)     

    {     

        ret = 0;     

        goto err;     

    }     

     

    x509=LoadCert(certfile,certlen,outMsg);     

    if (x509 == NULL)     

    {     

        ret = 0;     

        goto err;     

    }     

         

    if (!X509_check_private_key(x509,pkey))     

    {     

        sprintf(outMsg,"CA certificate and CA private key do not match\n");     

        ret = 0;     

        goto err;     

    }     

    md="sha1";//!!!!!!!!!!!!!!!!!      

    if ((dgst=EVP_get_digestbyname(md)) == NULL)//return an EVP_MD structure when passed a digest name      

    {     

        sprintf(outMsg,"%s is an unsupported message digest type\n",md);     

        ret = 0;     

        goto err;     

    }     

    j=certify(&x,req,pkey,x509,dgst,//公钥证书out,请求文件,根私钥,根公钥,      

        serial,"today",enddate,days,KUSAGE,EKUSAGE,outMsg);     

    if (j <= 0)      

    {     

        ret=0;     

        goto err;     

    }     

     

    if(((bcert=BIO_new_file(outfile, "w"))== NULL))     

    {     

        strcpy(outMsg,"Create File Error");     

        goto err;     

    }     

    if (type==DER)     

    {     

        i2d_X509_bio(bcert,x);     

    }     

    else if(type==PEM)     

    {     

        PEM_write_bio_X509(bcert,x);     

    }     

err:     

    if (reqbio != NULL) BIO_free(reqbio);     

    BIO_free_all(bcert);     

    EVP_PKEY_free(pkey);     

    X509_free(x509);     

    X509_free(x);     

    if (req != NULL) X509_REQ_free(req);     

    EVP_cleanup();//frees all three stacks and sets their pointers to NULL ---- EVP_CIPHER      

    return ret;     

     

}     

/ end      

BOOL DirectCert(char *certfile/*根证书公钥*/,int certlen,/*为0则certfile为磁盘文件,否则为内存区域*/     

             char *keyfile/*根证书私钥*/,int keylen,int serial/*序列号*/,char *enddate/*作废日期*/,     

             int days/*有效期*/,stuCERT * sCERT/*用户信息与密钥用法*/,int bits,char * cert/*输出证书公钥*/,int * certl/*长度*/,     

             char * key/*输出证书私钥*/,int * keyl/*长度*/,char * outMsg/*,int type结果类型DER,PEM*/)//直接生成公私钥      

{     

    X509_REQ * req=NULL;     

    EVP_PKEY * pkey=NULL, * prkey=NULL;//证书私钥,//根私钥      

    X509 * x509=NULL,* x=NULL;//根公钥,证书公钥      

    BIO * memcert=NULL, * memkey=NULL;//输出证书公私钥      

    BUF_MEM *bptrcert=NULL,*bptrkey=NULL;     

    int ret=1;     

    char * md=NULL;     

    int i=0,j=0,ok=0;     

    const EVP_MD *dgst=NULL;     

     

    OpenSSL_add_all_digests();//加入签名算法      

    memcert= BIO_new(BIO_s_mem());     

    memkey= BIO_new(BIO_s_mem());     

    BIO_set_close(memcert, BIO_CLOSE); /*  BIO_free() free BUF_MEM  */     

    BIO_set_close(memkey, BIO_CLOSE); /*  BIO_free() free BUF_MEM  */     

     

    prkey=LoadKey(keyfile,keylen,NULL,outMsg);//RAND_bytes      

    if (prkey == NULL)     

    {     

        ret = 0;     

        goto err;     

    }     

     

    x509=LoadCert(certfile,certlen,outMsg);     

    if (x509 == NULL)     

    {     

        ret = 0;     

        goto err;     

    }     

         

    if (!X509_check_private_key(x509,prkey))     

    {     

        sprintf(outMsg,"CA certificate and CA private key do not match\n");     

        ret = 0;     

        goto err;     

    }     

     

    if(!mkReq(&(sCERT->SUBJECT),&req,&pkey, bits,outMsg))     

    {     

        sprintf(outMsg,"Make CertReq error");     

        ret = 0;     

        goto err;     

    }     

     

    md="sha1";//!!!!!!!!!!!!!!!!!      

    if ((dgst=EVP_get_digestbyname(md)) == NULL)//return an EVP_MD structure when passed a digest name      

    {     

        sprintf(outMsg,"%s is an unsupported message digest type\n",md);     

        ret = 0;     

        goto err;     

    }     

    ok=certify(&x,req,prkey,x509,dgst,//公钥证书out,请求,根私钥,根公钥,      

        serial,"today",enddate,days,&(sCERT->KUSAGE),&(sCERT->EKUSAGE),outMsg);     

    if (ok <= 0)      

    {     

        ret=0;     

        goto err;     

    }     

/*  if (type==DER)   

    {   

        i=i2d_X509_bio(memcert,x);   

        j=i2d_PrivateKey_bio(memkey,pkey);//生成的结果错误!?????????????   

    }   

    else if(type==PEM)   

*/  {     

        i=PEM_write_bio_X509(memcert,x);     

        j=PEM_write_bio_PrivateKey(memkey,pkey,NULL,NULL,0,NULL, NULL);     

    }     

     

    if(!i||!j)     

    {     

        strcpy(outMsg,"Get Mem Cert or Key File Error");     

        ret=0;     

        goto err;     

    }     

     

    BIO_get_mem_ptr(memcert, &bptrcert);     

    *certl=bptrcert->length;     

    memcpy(cert,bptrcert->data,*certl);     

     

    BIO_get_mem_ptr(memkey, &bptrkey);     

    *keyl=bptrkey->length;     

    memcpy(key,bptrkey->data,*keyl);     

     

err:     

    BIO_free_all(memcert);     

    BIO_free_all(memkey);     

    EVP_PKEY_free(pkey);     

    EVP_PKEY_free(prkey);     

    X509_free(x509);     

    X509_free(x);     

    if (req != NULL) X509_REQ_free(req);     

    EVP_cleanup();//frees all three stacks and sets their pointers to NULL ---- EVP_CIPHER      

    return ret;     

}     

//      

/ begin //      

/*添加链表节点*/     

void AddRevoke(stuREVOKE *& Head,int index,time_t time)     

{     

    stuREVOKE * End=new stuREVOKE(index,time);//钥增加的节点      

    if(Head==NULL)     

    {     

        Head=End;     

    }     

    else      

    {     

        stuREVOKE * p=Head;     

        while(p->Link!=NULL)       

            p=p->Link;     

        p->Link=End;      

    }     

     

    return;     

}     

     

int Add_ExtCrl(X509_CRL *crl/*正被添加的证书*/,X509 * root/*根证书(从中得到信息)*/,      

               int nid, char *value)     

{     

    X509V3_CTX ctx;     

    X509_EXTENSION *ex;     

     

    /* This sets the 'context' of the extensions. */     

    /* No configuration database */     

//  X509V3_set_ctx_nodb(&ctx);      

    X509V3_set_ctx(&ctx, root, NULL, NULL, crl, 0);     

//  issuerAltName  authorityKeyIdentifier      

    ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);     

    if (!ex)     

        return 0;     

    X509_CRL_add_ext(crl,ex,-1);     

    X509_EXTENSION_free(ex);     

    return 1;     

}     

     

     

BOOL MakeCrl(char *certfile/*根证书公钥*/,int certlen,/*为0则certfile为磁盘文件,否则为内存区域*/     

              char *keyfile/*根证书私钥*/,int keylen,     

              stuREVOKE * Head/*作废链表*/,PNewCrlMem NewCrlMem/*回调函数*/,char *& outCrl,int * crll,char * outfile/*crl文件*/,     

              char * outMsg/*操作结果*/)     

{     

    X509_CRL_INFO *ci = NULL;     

    X509_CRL *crl = NULL;     

    int ret=1,i=0;     

    char *key=NULL;     

    char *md=NULL;     

    EVP_PKEY *pkey=NULL;     

    X509 *x509=NULL;     

    BIO *in=NULL,*out=NULL;     

    const EVP_MD *dgst=NULL;     

    X509_REVOKED *r=NULL;     

    long crldays=30;     

    long crlhours=0;     

    stuREVOKE * temp =NULL;     

    BIO * memcrl=NULL;     

    BUF_MEM *bptrcrl=NULL;     

     

    OpenSSL_add_all_algorithms();     

     

    pkey=LoadKey(keyfile,keylen,NULL,outMsg);     

    if (pkey == NULL)     

    {     

        ret = 0;     

        goto err;     

    }     

    x509=LoadCert(certfile,certlen,outMsg);     

    if (x509 == NULL)     

    {     

        ret = 0;     

        goto err;     

    }     

         

    if (!X509_check_private_key(x509,pkey))     

    {     

        sprintf(outMsg,"CA certificate and CA private key do not match\n");     

        ret = 0;     

        goto err;     

    }     

    md="md5";//!!!!!!!!!!!!!!!!!      

    if ((dgst=EVP_get_digestbyname(md)) == NULL)//return an EVP_MD structure when passed a digest name      

    {     

        sprintf(outMsg,"%s is an unsupported message digest type\n",md);     

        ret = 0;     

        goto err;     

    }     

         

    if ((crl=X509_CRL_new()) == NULL)     

    {     

        ret = 0;     

        goto err;     

    }     

    ci=crl->crl;     

    X509_NAME_free(ci->issuer);     

    ci->issuer=X509_NAME_dup(x509->cert_info->subject);     

    if (ci->issuer == NULL)     

    {     

        ret = 0;     

        goto err;     

    }     

    X509_gmtime_adj(ci->lastUpdate,0);     

    if (ci->nextUpdate == NULL)     

        ci->nextUpdate=ASN1_UTCTIME_new();     

    X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);     

     

    if(!ci->revoked)     

        ci->revoked = sk_X509_REVOKED_new_null();     

     

         

    while(Head!=NULL)//遍历链表      

    {     

        temp=Head;     

        X509_REVOKED *r = NULL;     

        BIGNUM *serial_bn = NULL;     

        r = X509_REVOKED_new();     

        ASN1_TIME_set(r->revocationDate,Head->time);//时间      

        char index[100];     

        BN_hex2bn(&serial_bn,itoa(Head->Index,index,10));//序号      

        BN_to_ASN1_INTEGER(serial_bn,r->serialNumber);     

        sk_X509_REVOKED_push(ci->revoked,r);     

        Head=Head->Link;     

        delete temp;     

    }     

//  sk_X509_REVOKED_sort(ci->revoked);      

    for (i=0; i<SK_X509_REVOKED_NUM(CI->revoked); i++)     

    {     

        r=sk_X509_REVOKED_value(ci->revoked,i);     

        r->sequence=i;     

    }     

     

    if (ci->version == NULL)     

    if ((ci->version=ASN1_INTEGER_new()) == NULL)     

    {     

        ret = 0;     

        goto err;     

    }     

    ASN1_INTEGER_set(ci->version,1);     

    //  issuerAltName  authorityKeyIdentifier      

//  Add_ExtCrl(crl,x509,NID_subject_alt_name,"DNS:hpxs,email:hpxs@hotmail.com,RID:1.2.3.4,URI:https://hpxs,IP:192.168.0.22");      

    Add_ExtCrl(crl,x509,NID_issuer_alt_name, "DNS:hpxs,email:hpxs@hotmail.com,RID:1.2.3.4,URI:https://hpxs,IP:192.168.0.22");     

    Add_ExtCrl(crl,x509,NID_authority_key_identifier, "keyid,issuer:always");     

    if (!X509_CRL_sign(crl,pkey,dgst))     

    {     

        ret = 0;     

        goto err;     

    }     

    if(NewCrlMem)//输出内存      

    {     

        memcrl= BIO_new(BIO_s_mem());     

        BIO_set_close(memcrl, BIO_CLOSE); /*  BIO_free() free BUF_MEM  */     

        PEM_write_bio_X509_CRL(memcrl,crl);     

        BIO_get_mem_ptr(memcrl, &bptrcrl);     

        *crll=bptrcrl->length;     

        outCrl=NewCrlMem(*crll);     

        memcpy(outCrl,bptrcrl->data,*crll);     

    }     

    if(outfile)//输出文件      

    {     

        out=BIO_new_file(outfile, "w");     

        if(out==NULL)     

        {     

            sprintf(outMsg,"%s is error",outfile);     

            ret = 0;     

            goto err;     

        }     

        PEM_write_bio_X509_CRL(out,crl);     

    }     

     

    X509V3_EXT_cleanup();//cleanup the extension code if any custom extensions have been added      

err:     

    if(out)     

        BIO_free_all(out);     

    if(memcrl)     

        BIO_free_all(memcrl);     

    BIO_free(in);     

    EVP_PKEY_free(pkey);     

    X509_CRL_free(crl);     

    X509_free(x509);     

    EVP_cleanup();//frees all three stacks and sets their pointers to NULL ---- EVP_CIPHER      

    if(ret==1)     

        strcpy(outMsg,"CRL制作成功");     

    return ret;     

         

}     

     

BOOL CertFormatConver(char * buf/*文件内容或文件名称*/,int len/*内存长度为0则buf为文件名*/,     

              char * pwd/*p12文件密码*/,char * pem/*输出文件*/,     

              int outformat,char * out/*操作结果*/)     

{     

    EVP_PKEY *key=NULL;     

    X509 *cert=NULL;     

    BIO *biout=NULL;     

    int i=0;     

    //输出文件      

    if ((biout=BIO_new_file(pem, "w")) == NULL)     

    {     

        return false;     

    }            

    cert = LoadCert(buf,len,out);//首先尝试公钥,bio被改写      

    if(cert)//输入文件为公钥文件      

    {     

     

        if  (outformat == DER)     

            i=i2d_X509_bio(biout,cert);     

        else if (outformat == PEM)     

        {     

        //  if (trustout) i=PEM_write_bio_X509_AUX(biout,x);      

            i=PEM_write_bio_X509(biout,cert);     

        }     

        if(!i)//失败      

            strcpy(out,"保存公钥失败");     

        else     

            strcpy(out,"公钥证书格式转换成功");     

             

    }     

     

    else//输入文件为私钥文件      

    {     

        key=LoadKey(buf,len,pwd,out);     

        if(!key)      

        {     

            strcpy(out,"不能识别的文件格式");     

            return false;     

        }     

        if(outformat==PEM)     

        {        

            PEM_write_bio_PrivateKey(biout, key, NULL, NULL, 0, 0, NULL);     

        }     

        if(outformat==DER)     

        {     

            i2d_PrivateKey_bio(biout,key);//得到解密后的私钥      

        }     

             

        strcpy(out,"私钥证书格式转换成功");     

    }     

         

    if (biout != NULL) BIO_free(biout);     

    X509_free(cert);     

    EVP_PKEY_free(key);     

     

    return true;     

}     

     

//分解p12包      

BOOL ParseDB(char * strP12/*包文件*/,char * strPwd/*私钥密码*/,char * strCert/*公钥存放*/,     

             char * strkey/*私钥存放*/,int outformat/*输出格式*/,char * out/*返回结果*/)     

{     

    EVP_PKEY *key=NULL;     

    X509 *cert=NULL;     

    STACK_OF(X509) *ca = NULL;     

    BIO * bio=NULL,*bioCert=NULL,*bioKey=NULL;     

    PKCS12 *p12=NULL;     

    int i=0,j=0;     

         

    if((bio=BIO_new_file(strP12, "r")) == NULL)     

    {     

        strcpy(out,"打开文件错误");     

        return false;     

    }     

    SSLeay_add_all_algorithms();     

    p12 = d2i_PKCS12_bio(bio, NULL);     

    if (!PKCS12_parse(p12, strPwd, &key, &cert/*PEM*/, &ca))      

    {     

        strcpy(out,"解包失败");     

        return false;     

    }     

    PKCS12_free(p12);     

     

    //输出文件      

    if ((bioCert=BIO_new_file(strCert, "w")) == NULL)     

    {     

        return false;     

    }     

    if ((bioKey=BIO_new_file(strkey, "w")) == NULL)     

    {     

        return false;     

    }     

         

    if(outformat == DER)     

    {     

        i=i2d_X509_bio(bioCert,cert);     

        j=i2d_PrivateKey_bio(bioKey,key);     

    }     

    else if (outformat == PEM)     

    {     

        i=PEM_write_bio_X509(bioCert,cert);     

        j=PEM_write_bio_PrivateKey(bioKey, key, NULL, NULL, 0, 0, NULL);     

    }     

     

    if (bio != NULL) BIO_free(bio);     

    if (bioCert != NULL) BIO_free(bioCert);     

    if (bioKey != NULL) BIO_free(bioKey);     

    X509_free(cert);     

    EVP_PKEY_free(key);     

     

    EVP_cleanup();//frees all three stacks and sets their pointers to NULL ---- EVP_CIPHER      

    if(i!=0&&j!=0)     

    {     

        strcpy(out,"分解P12成功");     

        return true;     

    }     

    return false;     

}     

     

//组合p12包      

BOOL CreateDB(char * strP12/*OUT包文件*/,char * strPwd/*IN密码*/,char * strCert/*IN公钥*/,     

              char * strkey/*IN私钥*/,char * out/*返回结果*/)     

{     

    FILE *fp=NULL;     

    EVP_PKEY *key=NULL;     

    X509 *cert=NULL;     

    PKCS12 *p12;     

    cert =LoadCert(strCert,0,out);     

    if(!cert)      

    {     

        strcpy(out,"读取公钥文件失败");     

        return false;     

    }     

    key=LoadKey(strkey,0,NULL,out);//解密后私钥      

    if(!key)      

    {     

        strcpy(out,"读取私钥文件失败");     

        return false;     

    }     

    SSLeay_add_all_algorithms();     

    p12 = PKCS12_create(strPwd,"(hpxs)", key, cert, NULL, 0,0,0,0,0);     

    if(!p12)     

    {     

        strcpy(out,"创建p12结构失败");     

        return false;     

    }     

    if (!(fp = fopen(strP12, "wb")))      

    {     

        strcpy(out,"保存p12文件失败");     

    }     

    i2d_PKCS12_fp(fp, p12);     

    PKCS12_free(p12);     

    fclose(fp);     

    strcpy(out,"合并P12成功");     

    X509_free(cert);     

    EVP_PKEY_free(key);     

    EVP_cleanup();//frees all three stacks and sets their pointers to NULL ---- EVP_CIPHER      

    return true;     

}     

     

//修改p12包密码      

BOOL ChangePB(char * strP12/*in包文件*/,char * strPwd/*IN原密码*/,char * strPwd2/*IN新密码*/,     

              char * strOutP12/*in包文件*/,char * out/*返回结果*/)     

{     

    FILE *fp=NULL;     

    EVP_PKEY *key=NULL;     

    X509 *cert=NULL;     

    STACK_OF(X509) *ca = NULL;     

    PKCS12 *p12=NULL;     

    int len=0,wlen=0;     

     

    SSLeay_add_all_algorithms();     

    if (!(fp = fopen(strP12, "rb")))     

    {     

        strcpy(out,"打开文件错误");     

        return false;     

    }     

    p12 = d2i_PKCS12_fp(fp, NULL);     

    fclose (fp);     

    if (!p12)      

    {     

        strcpy(out,"读取包文件错误");     

        return false;     

    }     

    if (!PKCS12_parse(p12, strPwd, &key, &cert, &ca))      

    {     

        strcpy(out,"解包失败");     

        return false;     

    }     

    PKCS12_free(p12);     

    fclose(fp);     

    p12=NULL;     

    ///      

    p12 = PKCS12_create(strPwd2,"(null)", key, cert, NULL, 0,0,0,0,0);     

    if(!p12)     

    {     

        strcpy(out,"创建p12结构失败");     

        return false;     

    }     

    if (!(fp = fopen(strOutP12, "wb")))      

    {     

        strcpy(out,"保存p12文件失败");     

    }     

    i2d_PKCS12_fp(fp, p12);     

    PKCS12_free(p12);     

    fclose(fp);     

    strcpy(out,"转换P12密码成功");     

    X509_free(cert);     

    EVP_PKEY_free(key);     

    return true;     

}     

     

BOOL CertPairCheck(char * cert,char * key,char * out)//检验公钥、私钥是否配对      

{     

    EVP_PKEY *pkey=NULL;     

    X509 *x509=NULL;     

    x509=LoadCert(cert,0,out);     

    if(x509==NULL)     

    {     

        strcpy(out,"不能打开公钥文件");     

        return FALSE;     

    }     

    pkey=LoadKey(key,0,NULL,out);     

    if(pkey==NULL)     

    {     

        strcpy(out,"不能打开私钥文件");     

        X509_free(x509);     

        return FALSE;     

    }     

    if(X509_check_private_key(x509,pkey))//匹配      

    {     

        X509_free(x509);     

        EVP_PKEY_free(pkey);     

        return TRUE;     

    }     

    else     

    {     

        strcpy(out,"公私钥对不匹配");     

        X509_free(x509);     

        EVP_PKEY_free(pkey);     

        return FALSE;     

    }     

     

}     

     

#include    

#define DER                1 //FORMAT_ASN1   

#define PEM                3    /*定义格式*/   

#define NET                4   

#define P12                5   

   

typedef char * (* PNewCrlMem)(UINT len);   

   

struct stuSUBJECT//个体信息   

{   

    UCHAR C[4];//国家   

    UCHAR ST[4];//省份   

    UCHAR L[12];//城市   

    UCHAR O[48];//组织   

    UCHAR OU[24];//组织部门   

    UCHAR CN[12];//个人信息   

    UCHAR MAIL[24];//电子邮件   

    UCHAR PMAIL[24];//安全电子邮件   

    UCHAR T[12];//头衔   

    UCHAR D[12];//描述   

    UCHAR G[12];//曾用名   

    UCHAR I[12];//描述   

    UCHAR NAME[12];//描述   

    UCHAR S[12];//描述   

    UCHAR QUAL[12];//描述   

    UCHAR STN[12];//没有结构的名称   

    UCHAR PW[12];//挑战密码   

    UCHAR ADD[12];//无结构地址   

   

    stuSUBJECT()   

    {   

        memset(this,0,sizeof(stuSUBJECT));   

    }   

};   

   

struct stuKEYUSAGE//密钥用途   

{   

    BOOL DS;//Digital Signature   

    BOOL NR;//Non-Repudiation   

    BOOL KE;//Key Encipherment   

    BOOL DE;//Data Encipherment   

    BOOL KA;//keyAgreement   

    BOOL KC;//keyCertSign    

    BOOL CS;//cRLSign   

    BOOL EO;//Encipher Only   

    BOOL DO;//Decipher Only   

    stuKEYUSAGE()   

    {   

        memset(this,0,sizeof(stuKEYUSAGE));   

    }   

   

};   

   

struct stuEKEYUSAGE//增强型密钥用途   

{   

    BOOL SA;//服务器验证   

    BOOL CA;//客户端验证   

    BOOL CS;//代码签名   

    BOOL EP;//安全电子邮件   

    BOOL TS;//时间戳   

    BOOL msCC;//代码完整   

    BOOL msCTLS;//可签名信任列表   

    BOOL msSGC;//联机事务处理   

    BOOL msEFS;//加密磁盘上的数据   

    BOOL msSC;//智能卡登录   

    BOOL IP;//Internet   

    stuEKEYUSAGE()   

    {   

        memset(this,0,sizeof(stuEKEYUSAGE));   

    }   

   

};   

   

struct stuCERT//三者之和   

{   

    stuSUBJECT SUBJECT;   

    stuKEYUSAGE KUSAGE;   

    stuEKEYUSAGE EKUSAGE;   

    stuCERT()   

    {   

        memset(this,0,sizeof(stuCERT));   

    }   

};   

   

struct stuREVOKE//证书作废结构链表   

{   

    int Index;//证书序号   

    time_t time;//吊销时间   

    stuREVOKE * Link;   

    stuREVOKE()   

    {   

        memset(this,0,sizeof(stuREVOKE));   

    }   

    stuREVOKE(int index,time_t t)   

    {   

        Index=index;   

        time=t;;   

        Link=NULL;   

    }   

};   

   

/*添加链表节点*/   

void AddRevoke(stuREVOKE *& Head,int index,time_t time);   

   

/*证书格式转换函数*/   

BOOL CertFormatConver(char * buf/*内存区域,存储文件内容或文件名称*/,int len/*内存长度==0则buf为文件名*/,   

              char * pwd/*p12文件密码*/,char * pem/*输出文件*/,int outformat,char * out/*操作结果*/);   

   

/*根证书生成函数,根据rootInfo信息,生成根证书公、私钥文件*/   

BOOL MakeRoot(stuSUBJECT * rootInfo,/*请求信息IN*/int bits/*位数IN*/, int serial/*序列号IN*/,    

              int days/*有效期IN*/,char * certFile/*证书请求文件OUT*/,char * priFile/*私钥文件OUT*/,   

              char * out/*操作结果OUT*/,int type=PEM/*类型pem-der*/);   

   

/*证书请求生成函数,根据reqInfo信息,生成用户证书私钥文件、证书请求文件*/   

BOOL MakeReq(stuSUBJECT * reqInfo,/*请求信息IN*/int bits/*位数IN*/, char * reqFile/*证书请求文件OUT*/,   

             char * priFile/*私钥文件OUT*/,char * out/*操作结果OUT*/,int type=PEM/*类型pem-der*/);   

   

/*证书生成函数,通过证书请求,生成用户证书公钥文件*/   

BOOL MakeCert(char *certfile/*根证书公钥*/,int certlen,/*为0则certfile为磁盘文件,否则为内存区域*/   

              char *keyfile/*根证书私钥*/,int keylen,int serial/*序列号*/,char *enddate/*作废日期*/,   

              int days/*有效期*/, char *reqfile/*请求文件*/,stuKEYUSAGE * KUSAGE/*密钥用法*/,   

              stuEKEYUSAGE * EKUSAGE/*增强密钥用法*/,char *outfile/*结果文件*/,   

              char * outMsg/*操作结果*/,int type/*结果类型DER,PEM*/);//通过证书请求,得到证书   

   

//直接生成公私钥   

BOOL DirectCert(char *certfile/*根证书公钥*/,int certlen,/*为0则certfile为磁盘文件,否则为内存区域*/   

             char *keyfile/*根证书私钥*/,int keylen,int serial/*序列号*/,char *enddate/*作废日期*/,   

             int days/*有效期*/,stuCERT * sCERT/*用户信息与密钥用法*/,int bits,char * cert/*输出证书公钥*/,int * certl/*长度*/,   

             char * key/*输出证书私钥*/,int * keyl/*长度*/,char * outMsg/*,int type结果类型DER,PEM*/);//直接生成公私钥   

   

/*黑名单生成函数*/   

BOOL MakeCrl(char *certfile/*根证书公钥*/,int certlen,/*为0则certfile为磁盘文件,否则为内存区域*/   

              char *keyfile/*根证书私钥*/,int keylen,   

              stuREVOKE * Head/*作废链表*/,PNewCrlMem NewCrlMem/*回调函数*/,char *& outCrl,int * crll,char * outfile/*crl文件*/,   

              char * outMsg/*操作结果*/);   

   

/*分解p12包*/   

BOOL ParseDB(char * strP12/*包文件*/,char * strPwd/*解包密码*/,char * strCert/*公钥存放*/,   

             char * strkey/*私钥存放*/,int outformat/*输出格式*/,char * out/*返回结果*/);   

   

/*组合p12包*/   

BOOL CreateDB(char * strP12/*包文件IN*/,char * strPwd/*密码IN*/,char * strCert/*公钥存放IN*/,   

              char * strkey/*私钥存放IN*/,char * out/*返回结果OUT*/);   

   

BOOL ChangePB(char * strP12/*IN包文件*/,char * strPwd/*IN原密码*/,char * strPwd2/*IN新密码*/,   

              char * strOutP12/*OUT包文件*/,char * out/*返回结果OUT*/);   

   

//检验公钥、私钥是否配对   

BOOL CertPairCheck(char * cert,char * key,char * out);//检验公钥、私钥是否配对 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值