📄 ca.cpp
字号:
Add_Name(px509Name,NID_commonName,V_ASN1_UTF8STRING,(char *)pSubJect->CN,strlen((char *)pSubJect->CN));
Add_Name(px509Name,NID_pkcs9_emailAddress,V_ASN1_IA5STRING,(char *)pSubJect->MAIL,strlen((char *)pSubJect->MAIL));
Add_Name(px509Name,NID_title,V_ASN1_UTF8STRING,(char *)pSubJect->T,strlen((char *)pSubJect->T));
// Add_Name(px509Name,NID_description,(char *)pSubJect->D,strlen((char *)pSubJect->D));
Add_Name(px509Name,NID_givenName,V_ASN1_UTF8STRING,(char *)pSubJect->G,strlen((char *)pSubJect->G));
// Add_Name(px509Name,NID_initials,(char *)pSubJect->I,strlen((char *)pSubJect->I));
// Add_Name(px509Name,NID_name,(char *)pSubJect->NAME,strlen((char *)pSubJect->NAME));
Add_Name(px509Name,NID_surname,V_ASN1_UTF8STRING,(char *)pSubJect->S,strlen((char *)pSubJect->S));
// Add_Name(px509Name,NID_dnQualifier,(char *)pSubJect->QUAL,strlen((char *)pSubJect->QUAL));
// Add_Name(px509Name,NID_pkcs9_unstructuredName,(char *)pSubJect->STN,strlen((char *)pSubJect->STN));
// Add_Name(px509Name,NID_pkcs9_challengePassword,(char *)pSubJect->PW,strlen((char *)pSubJect->PW));
// Add_Name(px509Name,NID_pkcs9_unstructuredAddress,(char *)pSubJect->ADD,strlen((char *)pSubJect->ADD));
Add_Name(px509Name,NID_streetAddress,V_ASN1_UTF8STRING,(char *)pSubJect->CN,strlen((char *)pSubJect->CN));
Add_Name(px509Name,NID_postalCode,V_ASN1_UTF8STRING,(char *)pSubJect->CN,strlen((char *)pSubJect->CN));
Add_Name(px509Name,NID_homePostalAddress,V_ASN1_UTF8STRING,(char *)pSubJect->CN,strlen((char *)pSubJect->CN));
Add_Name(px509Name,"2.5.4.20",V_ASN1_UTF8STRING,(char *)pSubJect->CN,strlen((char *)pSubJect->CN));
*/
}
//BOOL MakeRootPub(stuSUBJECT * rootInfo,/*信息*/ char * certMem/*证书文件*/,int * certLen,char * outMsg/*操作结果*/)
/*{
//所以证书预览序号0,位数384,有限期1,格式DER
BIO * memcert = NULL;//输出证书公私钥
BUF_MEM *bptrcert = NULL;
X509 *x509=NULL;
EVP_PKEY *pkey=NULL;
memcert= BIO_new(BIO_s_mem());
BOOL bRet = FALSE;
if(mkRoot(rootInfo,&x509,&pkey,384,1,1,outMsg))
{
if(i2d_X509_bio(memcert,x509))//returns 1 for success 写入公钥
{
BIO_get_mem_ptr(memcert, &bptrcert);
*certLen=bptrcert->length;
memcpy(certMem,bptrcert->data,*certLen);
bRet = TRUE;
goto end;
}
else
{
strcpy(outMsg,"存储证书发生异常");
}
}
end:
BIO_free_all(memcert);
memcert = NULL;
EVP_PKEY_free(pkey);
pkey = NULL;
X509_free(x509);
x509 = NULL;
EVP_cleanup();//frees all three stacks and sets their pointers to NULL ---- EVP_CIPHER
CRYPTO_cleanup_all_ex_data();
return bRet;
}*/
/*将BIO转换未内存,和长度*/
BOOL Bio2Mem(BIO * memBio/*[IN]*/,char * lpszMem/*[OUT]*/,
UINT * memLen/*[IN,OUT],输入为mem长度,输出为实际长度*/)
{
if(memBio == NULL || memLen == NULL || (*memLen !=0 && lpszMem == NULL))
return FALSE;
//if(BIO_method_type(memBio))//判断是否内存类型BIO
UINT uCopy = 0;//拷贝实际长度
BUF_MEM * bptrBio = NULL;
BIO_get_mem_ptr(memBio, &bptrBio);
(*memLen >(UINT)bptrBio->length)?(uCopy = bptrBio->length):(uCopy = *memLen);
memcpy(lpszMem,bptrBio->data,uCopy);//拷贝输入长度,输入为0时候,测定长度
*memLen = bptrBio->length;//返回实际长度
return TRUE;
}
/*X509转换为Mem*/
BOOL X5092Mem(X509 * px509/*[IN]*/,const int iType/*[in]类型pem-der*/,
char * x509Mem/*[OUT]*/,UINT * x509Len/*[OUT]*/)
{
if(px509 == NULL || x509Len == NULL)
return FALSE;
BIO * memcert = NULL;
memcert = BIO_new(BIO_s_mem());
BIO_set_close(memcert, BIO_CLOSE); /* BIO_free() free BUF_MEM */
BOOL ret = FALSE;
if (iType == DER)
{
ret = i2d_X509_bio(memcert,px509);//returns 1 for success
}
else if(iType == PEM)
{
ret = PEM_write_bio_X509(memcert,px509);
}
else
{
// strcpy(outMsg,"指定证书格式错误");
// ret = 0;
goto err;
}
if(ret)
{
ret = Bio2Mem(memcert,x509Mem,x509Len);
}
err:
BIO_free_all(memcert);
return ret;
}
/*EVP_PKEY转换为BIO*/
BOOL Key2Mem(EVP_PKEY * pkey/*[IN]*/,const int iType/*[in]类型pem-der*/,
const char * priPwd/*[in]私钥密码*/,
char * keyMem/*[OUT]*/,UINT * keyLen/*[OUT]*/)
{
if(pkey == NULL || keyLen == NULL)
return FALSE;
BIO * memkey = NULL;
BIO * bEnc = NULL;
memkey = BIO_new(BIO_s_mem());
BIO_set_close(memkey, BIO_CLOSE); /* BIO_free() free BUF_MEM */
BOOL ret = FALSE;
if (iType==DER)
{
if(NULL == priPwd || strlen(priPwd) == 0) //写入私钥
ret=i2d_PrivateKey_bio(memkey,pkey);//私钥未加密
else
{
//添加加密链
unsigned char key[EVP_MAX_KEY_LENGTH]="";//算法最长的KEY长度
unsigned char iv[EVP_MAX_IV_LENGTH]="";//算法最长的IV长度
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 *)priPwd,
strlen(priPwd),1,key,iv))
{
BIO_set_cipher(bEnc,cipher,key,iv, 1);//1-加密、0-解密
memkey = BIO_push(bEnc, memkey);
ret = i2d_PrivateKey_bio(memkey,pkey);//私钥加密
BIO_flush(memkey);
memkey = BIO_pop(memkey);
BIO_free(bEnc);
}
else
{
ret = FALSE;
}
}
}
else if(iType == PEM)
{
if(NULL == priPwd || strlen(priPwd) == 0)
ret = PEM_write_bio_PrivateKey(memkey,pkey,NULL,NULL,0,NULL, NULL); //私钥不加密
else
ret = PEM_write_bio_PrivateKey(memkey,pkey,EVP_des_ede3_cbc(),NULL,0,NULL, (void *)priPwd); //私钥加密
}
else
{
ret = 0;
goto err;
}
if(ret)
{
ret = Bio2Mem(memkey,keyMem,keyLen);
}
err:
BIO_free_all(memkey);
return ret;
}
/*将stuCertPair结构转换为X509,EVP_PKEY,并验证密钥对*/
BOOL CertPair2XE(const stuCertPair & RootPair/*[IN]*/,X509 *& pCert, EVP_PKEY *& pKey ,char * outMsg)
{
pCert = NULL;
pKey = NULL;
//检测stuCertPair结构合法性
//检测公钥
if(RootPair.memCert == NULL || strlen(RootPair.memCert) == 0 )//没有公钥信息
{
sprintf(outMsg,"结构中缺少公钥信息");
return FALSE;
}
else if(RootPair.lenCert > MAX_CERT_LEN)//检测公钥长度,限定为8192
{
sprintf(outMsg,"公钥长度超过系统限制");
return FALSE;
}
//检测私钥
else if(RootPair.memKey == NULL || strlen(RootPair.memKey)==0 )//没有私钥信息
{
sprintf(outMsg,"结构中缺少私钥信息");
return FALSE;
}
else if(RootPair.lenKey > MAX_KEY_LEN)//检测私钥长度,限定为4096
{
sprintf(outMsg,"私钥长度超过系统限制");
return FALSE;
}
if(RootPair.pwdKey != NULL && strlen(RootPair.pwdKey))//私钥代密码
{
// OpenSSL_add_all_algorithms();
}
pKey = LoadKey(RootPair.memKey,RootPair.lenKey,RootPair.pwdKey,outMsg);
if (pKey == NULL)
{
// EVP_cleanup();
// CRYPTO_cleanup_all_ex_data();
return FALSE;
}
pCert = LoadCert(RootPair.memCert,RootPair.lenCert,RootPair.pwdKey,outMsg);
if (pCert == NULL)
{
// EVP_cleanup();
// CRYPTO_cleanup_all_ex_data();
return FALSE;
}
if (!X509_check_private_key(pCert,pKey))
{
sprintf(outMsg,"公私钥对不匹配");
// EVP_cleanup();
// CRYPTO_cleanup_all_ex_data();
return FALSE;
}
return TRUE;
}
//在内存中创建PFX
BOOL CreateMemPfx(X509 * pCert, EVP_PKEY * key, const char * p12Pwd, const char * friendlyName,
char * memP12/*OUT*/, UINT * p12Len/*OUT*/) //
{
BIO * memBio = NULL;
BUF_MEM * bptrP12 = NULL;
memBio = BIO_new(BIO_s_mem());
OpenSSL_add_all_algorithms();
PKCS12 * p12 = PKCS12_create((char *)p12Pwd,(char *)friendlyName, key, pCert, NULL, 0,0,0,0,0);
if(!p12)
{
BIO_free_all(memBio);
return FALSE;
}
i2d_PKCS12_bio(memBio, p12);
BIO_get_mem_ptr(memBio, &bptrP12);
*p12Len = bptrP12->length;
memcpy(memP12,bptrP12->data,*p12Len);
PKCS12_free(p12);
BIO_free_all(memBio);
// EVP_cleanup();//frees all three stacks and sets their pointers to NULL ---- EVP_CIPHER
// CRYPTO_cleanup_all_ex_data();
return TRUE;
}
BOOL mkRoot(const stuSUBJECT * rootInfo,
X509 ** x509p/*out公钥*/,
EVP_PKEY ** pkeyp/*out私钥*/,
int bits/*位数*/,
const long serial/*序列号*/,
const int days/*有效期*/,
const char * kusage,
const char * ekusage,
const stuCERTEXT * pCertExt,/*扩展*/
char * outMsg/*操作结果*/)
{
if(bits < 384)
bits = 384;
X509 * x = NULL;
EVP_PKEY * pk = NULL;
RSA * rsa = NULL;
X509_NAME * name = NULL;
int i = 0,
len = 0;
char altname[255] = {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,outMsg);//产生随机数种子
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,
AddName(name,rootInfo);
/* Its self signed so set the issuer name to be the same as the
* subject.
*/
X509_set_issuer_name(x,name);//设置发行者名称等同于上面的
if(kusage && strlen(kusage))
Add_ExtCert(x,x, NID_key_usage, kusage);
AddExtCert(x,x,pCertExt);//扩展
if(ekusage && strlen(ekusage))
Add_ExtCert(x,x,NID_ext_key_usage,ekusage);
X509V3_EXT_cleanup();//cleanup the extension code if any custom extensions have been added
OBJ_cleanup();
if (!X509_sign(x,pk,EVP_sha1()))//签名算法EVP_sha1,EVP_md5,用私钥签名公钥
{
strcpy(outMsg,"证书签名失败");
goto err;
}
*x509p = x;
*pkeyp = pk;
return TRUE;
err:
return FALSE;
}
/*输出标志,如果输出某项(certMem,或certLen == NULL),则不输出本项*/
BOOL MakeRoot(const stuSUBJECT * rootInfo,/*[in]信息*/
const char * friendlyName/*好记的名称*/,
const int bits/*[in]位数*/,
const long serial/*[in]序列号*/,
const int days/*[in]有效期*/,
const char * priPwd/*[in]私钥密码*/,
const char * cKusage,/*密钥用法*/
const char * cEkusage,/*扩展密钥用法*/
const stuCERTEXT * pCertExt,/*证书扩展*/
char * certMem/*[OUT]证书*/,
UINT * certLen/*[OUT]*/,
char * keyMem/*[OUT]私钥*/,
UINT * keyLen/*[OUT]*/,
char * p12Mem/*[OUT]pkcs#12*/,
UINT * p12Len/*[OUT]*/,
char * outMsg,/*操作结果*/
const int iType/*[in]类型pem-der*/)
{
X509 * px509 = NULL;
EVP_PKEY * pkey = NULL;
BIO * memcert = NULL,
* memkey = NULL;
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 */
BOOL ret = TRUE;
int i = 0,
j = 0;
if(mkRoot(rootInfo,&px509,&pkey,bits,serial,days,cKusage,
cEkusage,pCertExt,outMsg))
{
X5092Mem(px509,iType,certMem,certLen);
Key2Mem(pkey,iType,priPwd,keyMem,keyLen);
CreateMemPfx(px509, pkey, priPwd, friendlyName, p12Mem, p12Len);
}
else
ret = FALSE;
BIO_free_all(memcert);
BIO_free_all(memkey);
X509_free(px509);
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,const int iNid,const char *lpszValue)
{
X509_EXTENSION *ex;
ex = X509V3_EXT_conf_nid(NULL, NULL, iNid, (char *)lpszValue);
if (!ex)
return 0;
sk_X509_EXTENSION_push(sk, ex);
return 1;
}
int mkReq(const stuSUBJECT * reqInfo,X509_REQ **req,
EVP_PKEY **pkeyp, int bits,char * outMsg)
{
if(bits < 384)
bits = 384;
X509_REQ *x = NULL;
EVP_PKEY *pk = NULL;
RSA *rsa = NULL;
X509_NAME * name=NULL;
ASN1_STRING stmp,
*str = &stmp;
char altname[255] = {0};
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,outMsg);//产生随机数种子
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...
*/
AddName(name,reqInfo);
/* 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
// sprintf(altname,"email:%s",(char *)reqInfo->MAIL);
// Add_ExtReq(exts, NID_subject_alt_name, altname);
//加入自定义扩展
// 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -