⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ca.cpp

📁 minica2的第2个版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	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 + -