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

📄 ca.cpp

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