📄 ca.cpp
字号:
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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -