📄 ca.cpp
字号:
//////////////////////////////////////////////////////////////////////
///////////////////////// begin //////////////////////////////////////
int Add_ExtCrl(X509_CRL *crl/*正被添加的证书*/,X509 * pRoot/*根证书(从中得到信息)*/,
const int iNid, const char *lpszValue)
{
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, pRoot, NULL, NULL, crl, 0);
// issuerAltName authorityKeyIdentifier
ex = X509V3_EXT_conf_nid(NULL, &ctx, iNid, (char *)lpszValue);
if (!ex)
return 0;
X509_CRL_add_ext(crl,ex,-1);
X509_EXTENSION_free(ex);
return 1;
}
BOOL MakeCrl(const stuCertPair & RootPair/*根证书对*/,
const stuREVOKE * Head/*作废链表*/,
const 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 *px509 = 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();
if(!CertPair2XE(RootPair,px509,pkey,outMsg))
{
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(px509->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)//遍历链表
{
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));//序号 - leak BN_free
ASN1_INTEGER *tmpser = BN_to_ASN1_INTEGER(serial_bn, r->serialNumber);
BN_free(serial_bn);
sk_X509_REVOKED_push(ci->revoked,r);
Head=Head->Link;
}
// 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,px509,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,px509,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,px509,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
OBJ_cleanup();
err:
if(out)
BIO_free_all(out);
if(memcrl)
BIO_free_all(memcrl);
if(in)
BIO_free(in);
if(pkey)
EVP_PKEY_free(pkey);
if(px509)
X509_free(px509);
if(crl)
X509_CRL_free(crl);
// EVP_cleanup();//frees all three stacks and sets their pointers to NULL ---- EVP_CIPHER
// CRYPTO_cleanup_all_ex_data();
if(ret==1)
strcpy(outMsg,"CRL制作成功");
return ret;
}
BOOL CertFormatConver(const char * buf/*文件内容或文件名称*/,
const int len/*内存长度为0则buf为文件名*/,
const char * pwd/*p12文件密码,或者解密私钥密码*/,
char * pem/*输出内存*/,
UINT * pOutLen,/*输入内存长度,输出实际输出的长度*/
char * keyPwd,/*加密私钥密码,只在私钥时候起作用*/
const int outformat,char * outMsg/*操作结果*/)
{
BOOL bRet = TRUE;
EVP_PKEY *key=NULL;
X509 *pCert=NULL;
BIO * biout=NULL;
int i=0;
//输出文件
if(pOutLen == 0) //表示输出为文件
{
if ((biout=BIO_new_file(pem, "w")) == NULL)
{
return FALSE;
}
}
//输出
else
{
biout = BIO_new(BIO_s_mem());
BIO_set_close(biout, BIO_CLOSE);
}
pCert = LoadCert(buf,len,pwd,outMsg);//首先尝试公钥,pBioKey被改写
if(pCert)//输入文件为公钥文件
{
if (outformat == DER)
i=i2d_X509_bio(biout,pCert);
else if (outformat == PEM)
{
// if (trustout) i=PEM_write_bio_X509_AUX(biout,x);
i=PEM_write_bio_X509(biout,pCert);
}
if(!i)//失败
strcpy(outMsg,"保存公钥失败");
else
strcpy(outMsg,"公钥证书格式转换成功");
}
else//输入文件为私钥文件
{
key=LoadKey(buf,len,pwd,outMsg);
if(!key)
{
strcpy(outMsg,"不能识别的文件格式");
return FALSE;
}
if(outformat==PEM)
{
if(keyPwd == NULL || strlen(keyPwd) == 0)
PEM_write_bio_PrivateKey(biout, key, NULL, NULL, 0, 0, NULL); //私钥不加密
else
PEM_write_bio_PrivateKey(biout,key,EVP_des_ede3_cbc(),NULL,0,NULL, (void *)keyPwd); //私钥加密
}
if(outformat==DER)
{
if(NULL == keyPwd || strlen(keyPwd) == 0) //写入私钥
i2d_PrivateKey_bio(biout,key);//私钥未加密
else
{
//添加加密链
unsigned char keyl[EVP_MAX_KEY_LENGTH]="";//算法最长的KEY长度
unsigned char iv[EVP_MAX_IV_LENGTH]="";//算法最长的IV长度
BIO * bEnc = NULL;
if((bEnc = BIO_new(BIO_f_cipher())) != NULL)
{
const EVP_CIPHER * cipher = NULL;
cipher = EVP_des_ede3_cbc(); // 3DES-EDE-CBC
if(EVP_BytesToKey(cipher,EVP_sha1(),NULL,(unsigned char *)keyPwd,
strlen(keyPwd),1,keyl,iv))
{
BIO_set_cipher(bEnc,cipher,keyl,iv, 1);//1-加密、0-解密
biout = BIO_push(bEnc, biout);
i2d_PrivateKey_bio(biout,key);//私钥加密
BIO_flush(biout);
biout = BIO_pop(biout);
BIO_free(bEnc);
}
else
strcpy(outMsg,"初始化key or iv 失败,");
}
}
}
strcpy(outMsg,"私钥证书格式转换成功");
}
if(*pOutLen != 0) //表示输出为文件
{
Bio2Mem(biout, pem, pOutLen);
}
if (biout != NULL)
BIO_free_all(biout);
if(pCert)
X509_free(pCert);
if(key)
EVP_PKEY_free(key);
return TRUE;
}
//分解p12包
BOOL ParsePfx(const char * strP12/*包文件或内存*/,
const UINT iP12Len/* 如果包为文件,则为0,否则为内存长度*/,
const char * strPwdP12/*P12密码*/,
const char * strCert/*公钥存放*/,
const char * strkey/*私钥存放*/,
const char * keyPwd/*私钥密码*/,
const int outformat/*输出格式*/,
char * outMsg/*返回结果*/)
{
BOOL bRet = TRUE;
EVP_PKEY * key = NULL;
X509 * pCert = NULL;
// STACK_OF(X509) *ca = NULL;
BIO * bio = NULL,
* bioCert = NULL,
* bioKey = NULL;
PKCS12 * p12 = NULL;
int i = 0,
j = 0;
if(iP12Len == 0)//输入为磁盘文件
{
if((bio = BIO_new_file(strP12, "r")) == NULL)
{
strcpy(outMsg,"加载PFX文件错误");
bRet = FALSE;
goto err;
}
}
else//输入为内存中文件
{
if((bio = BIO_new_mem_buf((void *)strP12,iP12Len)) == NULL)//只读类型
{
sprintf(outMsg,"Make Mem Bio Error");
bRet = FALSE;
goto err;
}
}
OpenSSL_add_all_algorithms(); //不能去掉
p12 = d2i_PKCS12_bio(bio, NULL);
if (!PKCS12_parse(p12, strPwdP12, &key, &pCert/*PEM*/, /*&ca*/NULL))
{
strcpy(outMsg,"解析文件失败");
bRet = FALSE;
goto err;
}
//输出文件 - 可能不输出公钥
if (strCert != NULL && strlen(strCert) >0)
{
if((bioCert = BIO_new_file(strCert, "w")) == NULL)
{
bRet = FALSE;
goto err;
}
}
if (strkey!= NULL && strlen(strkey) >0 )
{
if((bioKey = BIO_new_file(strkey, "w")) == NULL)
{
bRet = FALSE;
goto err;
}
}
if(outformat == DER)
{
if(bioCert)
i = i2d_X509_bio(bioCert,pCert); //写入公钥
if(bioKey)
{
if(NULL == keyPwd || strlen(keyPwd) == 0) //写入私钥
i2d_PrivateKey_bio(bioKey,key);//私钥未加密
else
{
//添加加密链
unsigned char keyl[EVP_MAX_KEY_LENGTH]="";//算法最长的KEY长度
unsigned char iv[EVP_MAX_IV_LENGTH]="";//算法最长的IV长度
BIO * bEnc = NULL;
bEnc = BIO_new(BIO_f_cipher());
const EVP_CIPHER * cipher = NULL;
cipher = EVP_des_ede3_cbc(); // 3DES-EDE-CBC
if(EVP_BytesToKey(cipher,EVP_sha1(),NULL,(unsigned char *)keyPwd,
strlen(keyPwd),1,keyl,iv))
{
BIO_set_cipher(bEnc,cipher,keyl,iv, 1);//1-加密、0-解密
bioKey = BIO_push(bEnc, bioKey);
i2d_PrivateKey_bio(bioKey,key);//私钥加密
BIO_flush(bioKey);
bioKey = BIO_pop(bioKey);
BIO_free(bEnc);
}
else
{
strcpy(outMsg,"初始化key or iv 失败,");
bRet = FALSE;
goto err;
}
}
}
}
else if (outformat == PEM)
{
if(bioCert)
i=PEM_write_bio_X509(bioCert,pCert);
if(bioKey)
{
if(NULL == keyPwd || strlen(keyPwd) == 0)
j=PEM_write_bio_PrivateKey(bioKey, key, NULL, NULL, 0, 0, NULL);//私钥不加密
else
j=PEM_write_bio_PrivateKey(bioKey,key,EVP_des_ede3_cbc(),NULL,0,NULL, (void *)keyPwd); //私钥加密
}
}
err:
if (bio != NULL)
BIO_free(bio);
if (bioCert != NULL)
BIO_free(bioCert);
if (bioKey != NULL)
BIO_free_all(bioKey);
if(pCert)
X509_free(pCert);
if(key)
EVP_PKEY_free(key);
if(p12)
PKCS12_free(p12);
// EVP_cleanup();//frees all three stacks and sets their pointers to NULL ---- EVP_CIPHER
// CRYPTO_cleanup_all_ex_data();
if(bRet && i !=0 || j != 0)
{
return TRUE;
}
return FALSE;
}
//组合p12包
BOOL CreatePfx(char * StreamP12/*OUT包文件路径或内存区域*/,
UINT & uP12Len,/*输入时候为用于保存结果的内存区域长度, 输出为实际P12内存的长度*/
const char * P12EncPwd/*IN 用于加密P12的密码*/,
const char * FriendName,/*IN 好记名称*/
const char * StreamCert/*IN公钥*/,
const UINT uCertLen,/*IN,公钥内存区域长度, 0 - 标示输入为磁盘文件*/
const char * Streamkey/*IN私钥*/,
const UINT uKeyLen,/*IN,私钥内存区域长度, 0 - 标示输入为磁盘文件*/
const char * KeyDecPwd/*解密私钥密码*/,
char * outMsg/*返回结果*/)
{
BOOL bRet = TRUE;
EVP_PKEY *key = NULL;
X509 *pCert = NULL;
PKCS12 * p12 = NULL;
int i=0;
//输出文件
BIO * biout = BIO_new(BIO_s_mem());
BIO_set_close(biout, BIO_CLOSE);
pCert = LoadCert(StreamCert, uCertLen, "", outMsg);
if(!pCert)
{
strcpy(outMsg,"加载公钥文件失败");
bRet = FALSE;
goto err;
}
key = LoadKey(Streamkey, uKeyLen, KeyDecPwd, outMsg);//私钥
if(!key)
{
strcpy(outMsg,"加载私钥文件失败");
bRet = FALSE;
goto err;
}
OpenSSL_add_all_algorithms();
p12 = PKCS12_create(const_cast<char *>(P12EncPwd), const_cast<char *>(FriendName), key, pCert, NULL, 0,0,0,0,0);
if(!p12)
{
strcpy(outMsg,"创建p12结构失败");
bRet = FALSE;
goto err;
}
i2d_PKCS12_bio(biout, p12);
bRet = Bio2Mem(biout, StreamP12, &uP12Len);
err:
if(pCert)
X509_free(pCert);
if(key)
EVP_PKEY_free(key);
if (biout != NULL)
BIO_free(biout);
if(p12)
PKCS12_free(p12);
// EVP_cleanup();
return bRet;
}
//修改p12包密码
BOOL ChangePfxPwd(const char * strP12/*in老包文件*/,
const char * strPwd/*IN原密码*/,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -