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

📄 cacore.cpp

📁 一个简易的CA
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	if(req == NULL ) return CA_FAIL;

	// 生成证书对象
	X509 *ptemp=NULL;
	if(isCA)
	{
		m_pCACert = X509_new();
		ptemp = m_pCACert;
	}
	else
	{
		m_pClientCert = X509_new();
		ptemp = m_pClientCert;
	}

	
	if( !isCA&&m_pCACert == NULL ) 
	{
		strcpy(szErrorString,"缺少CA证书!");
		if(ptemp != NULL ) X509_free(ptemp);
		ptemp = NULL;
		return CA_FAIL;
	}
	
	// 设置证书基本项目
	
	if (!X509_set_version(ptemp, 2))
	{
		strcpy(szErrorString,"设置版本号失败!");
		if(ptemp != NULL ) X509_free(ptemp);
		ptemp = NULL;
		return CA_FAIL;
	}
	
	if (!ASN1_INTEGER_set(X509_get_serialNumber(ptemp),sn)) 
	{
		strcpy(szErrorString,"设置序列号失败!");
		if(ptemp != NULL ) X509_free(ptemp);
		ptemp = NULL;
		return CA_FAIL;
	}
	
	if (!X509_gmtime_adj(X509_get_notBefore(ptemp),0)) 
	{
		strcpy(szErrorString,"设置开始时间失败!");
		if(ptemp != NULL ) X509_free(ptemp);
		ptemp = NULL;
		return CA_FAIL;
	}
	if (!X509_gmtime_adj(X509_get_notAfter(ptemp), (long)60*60*24*days)) 
	{
		strcpy(szErrorString,"设置终止时间失败!");
		if(ptemp != NULL ) X509_free(ptemp);
		ptemp = NULL;
		return CA_FAIL;
	}
	
	if (!X509_set_subject_name(ptemp, X509_REQ_get_subject_name(req)))
	{
		strcpy(szErrorString,"设置主体名失败!");
		if(ptemp != NULL ) X509_free(ptemp);
		ptemp = NULL;
		return CA_FAIL;
	}
	EVP_PKEY *tmppkey = X509_REQ_get_pubkey(req);
	
	if (!tmppkey || !X509_set_pubkey(ptemp,tmppkey))
	{
		strcpy(szErrorString,"设置公钥失败!");
		if(ptemp != NULL ) X509_free(ptemp);
		if(tmppkey != NULL )EVP_PKEY_free(tmppkey);
		ptemp = NULL;
		tmppkey = NULL;
		return CA_FAIL;
	}
	EVP_PKEY_free(tmppkey);
	X509_NAME *pName=X509_NAME_new();
	if (pName == NULL ) 
	{
		strcpy(szErrorString,"创建X509名字对象失败!");
		if(ptemp != NULL ) X509_free(ptemp);
		ptemp = NULL;
		return CA_FAIL;
	}
	if(isCA == TRUE )
	{
		pName = X509_REQ_get_subject_name(req);
	}
	else if(m_pCACert != NULL)
	{
		pName = X509_get_subject_name(m_pCACert);
	}
	else
	{
		pName = NULL;
	}
	
	if( pName == NULL) 
	{
		strcpy(szErrorString,"设置证书签发者失败!");
		if(ptemp != NULL ) X509_free(ptemp);
		ptemp = NULL;
		return CA_FAIL;
	}
	if (!X509_set_issuer_name(ptemp, pName))
	{
		strcpy(szErrorString,"设置证书签发者失败!");
		if(ptemp != NULL ) X509_free(ptemp);
		ptemp = NULL;
		return CA_FAIL;
	}

	// 设置扩展项目

	X509V3_CTX ctx;
	if(isCA)
		X509V3_set_ctx(&ctx, m_pCACert, m_pCACert, NULL, NULL, 0);
	else
		X509V3_set_ctx(&ctx, m_pCACert, m_pClientCert, NULL, NULL, 0);
	for(int i = 0; i < EXT_COUNT ; i++)
	{
		X509_EXTENSION *x509_ext = X509_EXTENSION_new();
		x509_ext = X509V3_EXT_conf(NULL,&ctx,
			isCA?ca_ext_entry[i].name:client_ext_entry[i].name,
			isCA?ca_ext_entry[i].value:client_ext_entry[i].value);
		if(!x509_ext)
		{
			sprintf(szErrorString,"建立证书扩展(%s = %s)对象失败!",
				isCA?ca_ext_entry[i].name:client_ext_entry[i].name,
				isCA?ca_ext_entry[i].value:client_ext_entry[i].value);
			if(ptemp != NULL ) X509_free(ptemp);
			ptemp = NULL;
			return CA_FAIL;
		}
		if(!X509_add_ext(isCA?m_pCACert:m_pClientCert,x509_ext,-1))
		{
			strcpy(szErrorString,"加入证书扩展对象失败!");
			if(ptemp != NULL ) X509_free(ptemp);
			ptemp = NULL;
			return CA_FAIL;
		}
		X509_EXTENSION_free(x509_ext);
	}

	// 加入可选名

	int		  san_pos = -100;
	X509_EXTENSION *tmpsan = NULL;
	STACK_OF(X509_EXTENSION) *req_exts;
	req_exts = X509_REQ_get_extensions(req);
	while(req_exts != NULL) 
	{
		san_pos = X509v3_get_ext_by_NID(req_exts,OBJ_sn2nid(REQ_SUBJECT_ALT_NAME),
			-1);
		tmpsan =X509v3_get_ext(req_exts,san_pos);
		break;
	}
	if(tmpsan != NULL)
	{
		if(!X509_add_ext(ptemp,tmpsan,-1))
		{
			strcpy(szErrorString,"加入主体可选名失败!");
			if(ptemp != NULL ) X509_free(ptemp);
			ptemp = NULL;
			return CA_FAIL;
		}
	}
	
	// 签名
	if (!X509_sign(isCA?m_pCACert:m_pClientCert,m_pCAKey,digest))
	{
		strcpy(szErrorString,"为证书签名失败!");
		if(ptemp != NULL ) X509_free(ptemp);
		ptemp = NULL;
		return CA_FAIL;
	}
	return CA_OK;
}

int CCACore::ToPKCS12(CString strPwd,CString strFileName,
					  CString strFriendlyName)
{
	if(m_pClientCert == NULL || m_pClientKey == NULL)
	{
		sprintf(szErrorString,"%s","缺少证书与私钥!");
		return CA_FAIL;
	}
	BIO *pbio;
	pbio = BIO_new_file((LPSTR)(LPCTSTR)strFileName,"w");
	PKCS12 *p12;
	p12 = PKCS12_create((LPSTR)(LPCTSTR)strPwd,
		(LPSTR)(LPCTSTR)strFriendlyName,m_pClientKey, m_pClientCert,
		NULL, 0,0,0,0,0);
	if(!p12) 
	{
		sprintf(szErrorString, "创建 PKCS#12 结构失败!");
		goto err;
	}
	i2d_PKCS12_bio(pbio,p12);	
	PKCS12_free(p12);
	p12 = NULL;
	BIO_free(pbio);
	pbio = NULL;
	return CA_OK;
err:	
	PKCS12_free(p12);
	p12 = NULL;
	BIO_free(pbio);
	pbio = NULL;
	return CA_FAIL;
}

int CCACore::MakeCRL(CString strFileName,
					 CRevokeCertList *prev,
					 long crldays,
					 long crlhours)
{
	// 初始化

	int it    = 0;
	int count = 0;
	BIO *hex=NULL;
	X509_REVOKED * xrev = NULL;
	STACK_OF(X509_REVOKED) *revoked ;
	revoked = sk_X509_REVOKED_new_null();
	if(revoked == NULL)
	{
		sprintf(szErrorString,"%s","申请吊销内容空间失败!");
		goto err;
	}

	m_pCrl = X509_CRL_new();
	if(m_pCrl == NULL) 
	{
		sprintf(szErrorString,"%s","生成CRL对象失败!");
		return CA_FAIL;
	}
	if ((hex=BIO_new(BIO_s_mem())) == NULL)
	{
		sprintf(szErrorString,"%s","申请BIO内存空间失败!");
		goto err;
	}
	BIO *pbio;
	pbio = BIO_new_file((LPSTR)(LPCTSTR)strFileName,"w");
	// 合法性检查

	if(m_pCACert == NULL)
	{
		strcpy(szErrorString,"缺少CA证书!");
		return CA_FAIL;
	}

	// 生成基本项目
	
	m_pCrlInfo = m_pCrl->crl;
	if ((m_pCrlInfo->version=ASN1_INTEGER_new()) == NULL)
	{
		sprintf(szErrorString,"%s","申请版本号内存空间失败!");
		goto err;
	}
	ASN1_INTEGER_set(m_pCrlInfo->version,1); /* version 2 CRL */
	X509_NAME_free(m_pCrlInfo->issuer);
	m_pCrlInfo->issuer=X509_NAME_dup(m_pCACert->cert_info->subject);
	if (m_pCrlInfo->issuer == NULL) 
	{
		sprintf(szErrorString,"%s","无法取得CA名称");
		goto err;
	}
	X509_gmtime_adj(m_pCrlInfo->lastUpdate,0);
	if (m_pCrlInfo->nextUpdate == NULL)
		m_pCrlInfo->nextUpdate=ASN1_UTCTIME_new();
	X509_gmtime_adj(m_pCrlInfo->nextUpdate,(crldays*24+crlhours)*60*60);
	
	// 生成吊销的内容
	// revokeCertificates := SEQUENCE OF SEQUENCE 
	// {
	//		userCertificate    CertificateSerialNumber,
	//      revocationDate     Time,
	//      crlEntryExtensions Extensions OPTIONAL(if present,shall be V2)
	// }	
	
	count = prev->GetCount();
	if(count <= 0)
	{
		sprintf(szErrorString,"%s","没有证书供吊销!");
		goto err;
	}
	for(it=0; it<count ; it++)
	{
		xrev = X509_REVOKED_new();
		if(xrev == NULL)
		{
			sprintf(szErrorString,"%s","申请X509_REVOKED内容失败!");
			goto err;
		}
		time_t t;
		//time(&t);
		t=prev->GetTime_t(it);
		if(t == -1L)
		{
			sprintf(szErrorString,"%s","取证书吊销时间失败!");
			goto err;
		}
		ASN1_TIME_set(xrev->revocationDate,t);
		ASN1_INTEGER_set(xrev->serialNumber,atol(prev->GetSerialStr(it)));
		sk_X509_REVOKED_push(m_pCrlInfo->revoked,xrev);
	}
	
	sk_X509_REVOKED_sort(m_pCrlInfo->revoked);
	for (it=0; it<sk_X509_REVOKED_num(m_pCrlInfo->revoked); it++)
	{
		xrev=sk_X509_REVOKED_value(m_pCrlInfo->revoked,it);
		xrev->sequence=it;
	}
	
	// 签名

	if (!X509_CRL_sign(m_pCrl,m_pCAKey,digest))
	{
		sprintf(szErrorString,"%s","为CRL签名失败!");
		goto err;
	}
	
	// 输出到文件

	if(!PEM_write_bio_X509_CRL(pbio,m_pCrl))
	{
		sprintf(szErrorString,"%s","CRL写入文件失败!");
		goto err;
	}

	if(hex	   != NULL) BIO_free(hex);
	if(pbio	   != NULL) BIO_free(pbio);	
	if(revoked != NULL) sk_X509_REVOKED_pop_free(revoked,X509_REVOKED_free);
	if(m_pCrl  != NULL) X509_CRL_free(m_pCrl);	

	return CA_OK;

	// 集中进行出错处理,以解决内存泄漏问题

err:
	if(hex	   != NULL) BIO_free(hex);
	if(pbio	   != NULL) BIO_free(pbio);	
	if(revoked != NULL) sk_X509_REVOKED_pop_free(revoked,X509_REVOKED_free);
	if(m_pCrl  != NULL) X509_CRL_free(m_pCrl);
	return CA_FAIL;

}

void CCACore::FreeCertificate(BOOL isCA)
{
	if(isCA&&m_pCACert != NULL)
	{
		X509_free(m_pCACert);
		m_pCACert = NULL;
	}
	if(!isCA&&m_pClientCert != NULL)
	{
		X509_free(m_pCACert);
		m_pCACert = NULL;
	}
}

// 将私钥转成pem字符串

int CCACore::PrivateKeyToPEM(
				BOOL isCA,		// 是否为CA
				CString strPwd,	// 密码
				char *buf,		// 外面缓冲区
				int len)		// 缓冲区的长度
{
	BIO *pbio;
	pbio = BIO_new(BIO_s_mem());
	// 写入缓冲区
	if(!PEM_write_bio_PrivateKey(pbio,isCA?m_pCAKey:m_pClientKey,
		EVP_des_cbc(),(unsigned char*)(LPCTSTR)strPwd,
		strPwd.GetLength(),0,NULL))
		goto err;
	// 拷贝到buf中
	BUF_MEM * bptr;
	BIO_get_mem_ptr(pbio,&bptr);
	if(bptr->length < len)
	{
		memcpy(buf,bptr->data,bptr->length);
		buf[bptr->length]='\0';
	}
	else
		buf[0]='\0';
	BIO_set_close(pbio,BIO_CLOSE);
	BIO_free(pbio);
	pbio = NULL;
	return CA_OK;
	err:
	strcpy(szErrorString,"将私钥转成PEM失败!");
	BIO_free(pbio);
	pbio = NULL;
	return CA_FAIL;
}

// 将证书转成pem字符串

int CCACore::CertificateToPEM(BOOL isCA,char *buf, int len)
{
	BIO *pbio;
	pbio = BIO_new(BIO_s_mem());
	// 写入缓冲区
	if(!PEM_write_bio_X509(pbio,isCA?m_pCACert:m_pClientCert))
		goto err;
	// 拷贝到buf中
	BUF_MEM * bptr;
	BIO_get_mem_ptr(pbio,&bptr);
	if(bptr->length < len)
	{
		memcpy(buf,bptr->data,bptr->length);
		buf[bptr->length]='\0';
	}
	else
		buf[0]='\0';
	BIO_set_close(pbio,BIO_CLOSE);
	BIO_free(pbio);
	pbio = NULL;
	return CA_OK;
	err:
	strcpy(szErrorString,"将私钥转成PEM失败!");
	BIO_free(pbio);
	pbio = NULL;
	return CA_FAIL;
}

BOOL CCACore::HasValidCA()
{
	BOOL bRet  = FALSE;
	if(m_pCAKey != NULL && m_pCACert != NULL&&X509_check_private_key(m_pCACert,m_pCAKey))
		bRet = TRUE;
	return bRet;
}

int CCACore::add_ext(STACK_OF(X509_REQUEST) *sk, int nid, char *value)
{
	X509_EXTENSION *ex;
	ex = X509V3_EXT_conf_nid(NULL, NULL, nid, value);
	if (!ex)
		return CA_FAIL;
	sk_X509_EXTENSION_push(sk, ex);

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -