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

📄 ca.cpp

📁 minica2的第2个版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// CA.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include <locale.h>
#include "ca.h"
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/pkcs12.h>
#include <openssl/rand.h>
//#include <sys/stat.h>   stat() 可以得到文件状态

#define EXT_COPY_NONE	0
#define EXT_COPY_ADD	1
#define EXT_COPY_ALL	2

#define MAX_CERT_LEN 8192 //最大公钥长度
#define MAX_KEY_LEN 4096 //最大私钥长度

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
	switch(ul_reason_for_call) 
	{ 
	case DLL_PROCESS_ATTACH: 
		OpenSSL_add_all_algorithms();	//leak EVP_cleanup(void);
		ERR_load_crypto_strings();	// leak  ERR_free_strings()
		//ENGINE_load_builtin_engines();
		break;
		
	case DLL_PROCESS_DETACH: 
		CONF_modules_unload(1);
		EVP_cleanup();
		CRYPTO_cleanup_all_ex_data(); 
		ERR_remove_state(0);
		ERR_free_strings(); 
		CONF_modules_free();
		break; 
	}
	return TRUE;
}

void LastError(char * info)
{
/*	BIO * mem = BIO_new(BIO_s_mem());
	BIO_set_close(mem, BIO_CLOSE); 
	ERR_print_errors(mem);
	BUF_MEM * bptr = NULL;
	BIO_get_mem_ptr(mem, &bptr);
	int len = bptr->length;
	char * pbuf = new char[len+1];
	memset(pbuf,0,len+1);
	memcpy(pbuf,bptr->data,len);
	delete [] pbuf;*/
	
}
/*此函数可以将DER、PEM、P12文件公钥读出来*/
X509 *load_cert(BIO * pBioCert/*输入BIO*/, const int iFormat/*格式*/,
				const char * lpszPwd,/*P12密码*/
				char * outMsg) //从DER、PEM、P12格式中加载公钥证书
{
	X509 * x = NULL;
	if(iFormat == DER)
		x = d2i_X509_bio(pBioCert,NULL);
	else if (iFormat == PEM)
		x = PEM_read_bio_X509(pBioCert,NULL,NULL,NULL);//PEM_read_bio_X509_AUX
	else if (iFormat == P12)
	{
		OpenSSL_add_all_algorithms();
		PKCS12 *p12 = d2i_PKCS12_bio(pBioCert, NULL);
		PKCS12_parse(p12, lpszPwd, NULL, &x, NULL);
		PKCS12_free(p12);
		p12 = NULL;
//		EVP_cleanup();
	}
	else
	{
		sprintf(outMsg,"bad input format specified for input cert\n");
		goto end;
	}
end:
	if (x == NULL)
	{
		sprintf(outMsg,"unable to load certificate\n");
	}
	else
		sprintf(outMsg,"");
	return(x);
}

X509 * LoadCert(const char * lpszCert,const int iCertlen,
				const char * lpszPass,char * outMsg)//枚举DER/PEM格式
{
	BIO * in = NULL;
	X509 * x509 = NULL;

	if(iCertlen == 0)//输入为磁盘文件
	{
		if((in = BIO_new_file(lpszCert, "r")) == NULL)
		{
			sprintf(outMsg,"open CA certificate file error");
			return NULL;
		}
	}
	else//输入为内存中文件
	{
		if((in = BIO_new_mem_buf((void *)lpszCert,iCertlen)) == NULL)//只读类型
		{
			sprintf(outMsg,"Make Mem Bio Error");
			return NULL;
		}
	}
	if((x509 = load_cert(in,DER,NULL,outMsg)) == NULL)//尝试DER
	{
		BIO_reset(in);//恢复bio
		if((x509 = load_cert(in,PEM,NULL,outMsg)) == NULL)//尝试PEM
		{
			BIO_reset(in);//恢复bio
			x509 = load_cert(in,P12,lpszPass,outMsg);//尝试P12
		}
	}
	if (in != NULL) BIO_free(in);
	return x509;
}

EVP_PKEY * load_key(BIO * pBioKey, const int iFormat, const char * lpszPass,char * outMsg)//枚举DER/PEM格式
{
	EVP_PKEY * pkey = NULL;
	OpenSSL_add_all_algorithms();
	
	if (iFormat == DER)
	{
		if(NULL == lpszPass || strlen(lpszPass) == 0)
		{
			pkey = d2i_PrivateKey_bio(pBioKey, NULL);
		}
		else
		{
			//添加解密链
			unsigned char key[EVP_MAX_KEY_LENGTH] = "";//算法最长的KEY长度
			unsigned char iv[EVP_MAX_IV_LENGTH] = "";//算法最长的IV长度
			BIO * bDec = NULL;
			bDec = 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 *)lpszPass,
				strlen(lpszPass),1,key,iv))
			{
				BIO_set_cipher(bDec,cipher,key,iv, 0);//1-加密、0-解密
				pBioKey = BIO_push(bDec, pBioKey); 
				BIO_flush(pBioKey);
		
				pkey = d2i_PrivateKey_bio(pBioKey, NULL);//私钥解密
		
				pBioKey = BIO_pop(pBioKey);
				BIO_free(bDec);
			}
			else
			{
				strcpy(outMsg,"初始化key or iv 失败");
				goto end;
			}
		}
	}
	else if (iFormat == PEM)
	{
		pkey = PEM_read_bio_PrivateKey(pBioKey,NULL,NULL,(void * )lpszPass);
	}
	else if (iFormat == P12)
	{
		PKCS12 *p12 = d2i_PKCS12_bio(pBioKey, NULL);
		PKCS12_parse(p12, lpszPass, &pkey, NULL, NULL);
		PKCS12_free(p12);
		p12 = NULL;
	}
	else
	{
		sprintf(outMsg,"bad input format specified for key\n");
		goto end;
	}
end:
//	EVP_cleanup();
	if (pkey == NULL)
		sprintf(outMsg,"unable to load Private Key\n");
	else
		sprintf(outMsg,"");
	return(pkey);
}

EVP_PKEY * LoadKey(const char * lpszkey,const int iKeylen,const char * lpszPass,char * outMsg) //leak 4772
{
	EVP_PKEY *pkey = NULL;
	BIO * in = NULL;

	if(iKeylen ==0 )//输入为磁盘文件
	{
		if((in = BIO_new_file(lpszkey, "r")) == NULL)
		{
			sprintf(outMsg,"open CA certificate file error");
			goto end;
		}
	}
	else//输入为内存中文件
	{
		if((in = BIO_new_mem_buf((void *)lpszkey,iKeylen)) == NULL)//只读类型
		{
			sprintf(outMsg,"Make Mem Bio Error");
			goto end;
		}
	}

	if((pkey = load_key(in,DER,lpszPass,outMsg)) == NULL)//尝试DER
	{
		BIO_reset(in);//BIO是可读写的,那么该BIO所有数据都会被清空;
						//如果该BIO是只读的,那么该操作只会简单将指
						//针指向原始位置,里面的数据可以再读.
		if((pkey = load_key(in,PEM,lpszPass,outMsg)) == NULL)//尝试PEM
		{
			BIO_reset(in);
			pkey = load_key(in,P12,lpszPass,outMsg);
		}
	}
end:
	if (in != NULL)
	{
		BIO_flush(in);
		BIO_free_all(in);
	}
	return pkey;
}

int Rand(const char * file,const int dont_warn,char * outMsg)//产生随机数,return 0 ---成功
{
	int consider_randfile = (file == NULL);
	char buffer[200];
	
	RAND_screen();
	if (file == NULL)
		file = RAND_file_name(buffer, sizeof buffer);
	else if (RAND_egd(file) > 0)
	{
	/* we try if the given filename is an EGD socket.
		if it is, we don't write anything back to the file. */
		return 1;
	}
	if (file == NULL || !RAND_load_file(file, -1))
	{
		if (RAND_status() == 0 && !dont_warn)
		{
			sprintf(outMsg,"unable to load 'random state'\n");
			sprintf(outMsg,"This means that the random number generator has not been seeded\n");
			if (consider_randfile) /* explanation does not apply when a file is explicitly named */
			{
				sprintf(outMsg,"Consider setting the RANDFILE environment variable to point at a file that\n");
				sprintf(outMsg,"'random' data can be kept in (the file will be overwritten).\n");
			}
		}
		return 0;
	}
	return 1;
}


///////////////////////// end ////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
///////////////////////// begin //////////////////////////////////////

/* Add extension using V3 code: we can set the config file as NULL
* because we wont reference any other sections.
*/
int Add_ExtCert(X509 * pCert/*正被添加的证书*/,X509 * pRoot/*根证书(从中得到信息)*/,
				const int iNid, const char * lpszValue)
{
	X509_EXTENSION * ex = NULL;
	X509V3_CTX ctx;
	/* This sets the 'context' of the extensions. */
	/* No configuration database */
	X509V3_set_ctx_nodb(&ctx);
	/* Issuer and subject certs: both the target since it is self signed,
	* no request and no CRL
	*/
	X509V3_set_ctx(&ctx,pRoot, pCert, NULL, NULL, 0);
	ex = X509V3_EXT_nconf_nid(NULL, &ctx, iNid, (char *)lpszValue);//X509V3_EXT_nconf
	if (!ex)
	{
		return 0;
	}	
	X509_add_ext(pCert,ex,-1);
	X509_EXTENSION_free(ex);
	return 1;
}

int Add_ExtCert(X509 *pCert/*正被添加的证书*/,X509 * pRoot/*根证书(从中得到信息)*/, 
				const char * lpszName, const char *lpszValue)
{
	X509_EXTENSION * ex = NULL;
	X509V3_CTX ctx;
	/* This sets the 'context' of the extensions. */
	/* No configuration database */
	X509V3_set_ctx_nodb(&ctx);
	/* Issuer and subject certs: both the target since it is self signed,
	* no request and no CRL
	*/
	X509V3_set_ctx(&ctx, pRoot, pCert, NULL, NULL, 0);
	ex = X509V3_EXT_conf(NULL, &ctx, (char *)lpszName, (char *)lpszValue);//X509V3_EXT_nconf
	if (!ex)
	{
		return 0;
	}	
	X509_add_ext(pCert,ex,-1);
	X509_EXTENSION_free(ex);
	return 1;
}

int AddExtCert(X509 *pCert/*正被添加的证书*/,X509 * pRoot/*根证书(从中得到信息)*/, 
			   const stuCERTEXT * pCertExt)
{
	/* This sets the 'context' of the extensions. */
	/* No configuration database */
	/* Issuer and subject certs: both the target since it is self signed,
	* no request and no CRL
	*/
	//基本限制Note if the CA option is FALSE the pathlen option should be omitted. 
//	Add_ExtCert(pCert,pCert,NID_friendlyName, "130203197703060618");

	//主题密钥标示符--------区分拥有者多对密钥
//	Add_ExtCert(pCert,pCert,NID_subject_key_identifier, "hash");

	//Authority密钥标示符----区分发行者有多个签名密钥时
//	Add_ExtCert(pCert,pRoot, NID_authority_key_identifier, "keyid,issuer:always");
	

	//密钥用法 ----数字签名、不可否认性、密钥加密、数据加密、密钥协商、证书签名、

		//颁发者备用名称,URL:http://my.url.here/、不支持email  copy
//	Add_ExtCert(pCert,pCert, NID_issuer_alt_name, 
//		"DNS:hpxs,email:hpxs@hotmail.com,RID:1.2.3.4,URI:https://hpxs,IP:192.168.0.22");
//
	//证书策略
//	Add_ExtCert(pCert,pCert,NID_certificate_policies,"requireExplicitPolicy:3");
	//颁发机构信息访问
//	Add_ExtCert(pCert,pCert,NID_info_access,"OCSP;URI:https://hpxs");//或者caIssuers;URI:http://my.ca/ca.html
	//CRL分发点
//	Add_ExtCert(pCert,pCert, NID_crl_distribution_points, "URI:https://hpxs/hpxs.crl");

	/* Some Netscape specific extensions */
//	Add_ExtCert(ret,ret, NID_crl_number, "sslCA");

//	Add_ExtCert(ret,px509, NID_netscape_comment, "See http://cert.umd.edu/root for details.");
	/* In each case the 'value' of the extension is placed directly in the
	extension. Currently supported extensions in this category are: nsBaseUrl,
	nsRevocationUrl, nsCaRevocationUrl, nsRenewalUrl, nsCaPolicyUrl,
	nsSslServerName and nsComment	*/

//	Add_ExtCert(ret,px509, NID_netscape_cert_type, "client, server, email,objsign, reserved, sslCA,emailCA, objCA");
	/*nsCertType (netscape certificate type) takes the flags: client, server, email,
	objsign, reserved, sslCA, emailCA, objCA.*/
	/* Maybe even add our own extension based on existing */
	
//	nid = OBJ_create("1.3.6.1.4.1.5315.100.2.5", "Hpxs", "OC61108551");0.9.2342.19200300.100.1.1
//	X509V3_EXT_add_alias(nid, NID_netscape_comment);
//	Add_ExtCert(ret,ret, nid, "OC61108551");

	
	while(pCertExt!=NULL)//遍历链表
	{
		if(OBJ_sn2nid(pCertExt->cName) == NID_authority_key_identifier)
		{
			Add_ExtCert(pCert, pRoot, OBJ_sn2nid(pCertExt->cName), (char *)pCertExt->cInfo);
		}
		else if(strstr(pCertExt->cName, ".") == NULL) //没有发现.
		{
			Add_ExtCert(pCert, pCert, OBJ_sn2nid(pCertExt->cName), (char *)pCertExt->cInfo);
		}
		else
		{				//加入自定义信息begin
			int nid;
			nid = OBJ_create(pCertExt->cName, pCertExt->cName, pCertExt->cName);
			if(nid != NID_undef)
			{
				X509V3_EXT_add_alias(nid, NID_netscape_comment);
				Add_ExtCert(pCert,pCert, nid, pCertExt->cInfo);
			}
			OBJ_cleanup();	
		}		
		pCertExt = pCertExt->Link;
	}
	return 1;
}

void Ansi2Utf8(const LPSTR lpsrc, const int srclen, LPSTR lpdst, int& dstlen)
{
	WCHAR * pwUnicode;      
    int len = MultiByteToWideChar(CP_ACP,0,(char*)lpsrc,srclen,NULL,0);      
    pwUnicode = new WCHAR[len];  
    memset(pwUnicode,0,len);
    MultiByteToWideChar(CP_ACP,0 ,(char*)lpsrc,srclen,pwUnicode,len);      
    dstlen = WideCharToMultiByte(CP_UTF8,0,pwUnicode,len,NULL,0,NULL,NULL);      
    WideCharToMultiByte(CP_UTF8,0,pwUnicode,len,lpdst,dstlen,NULL,NULL);      
    delete []pwUnicode;      
}

BOOL Add_Name(X509_NAME * px509Name,const int iNid/*c\cn*/,
			  const int iType/*V_ASN1_UTF8STRING*/,
			  const char * lpszInput/*中国*/,
			  const int iLen/*输入长度*/)//支持中文名称
{
	if(NULL == lpszInput || strlen(lpszInput) == 0)
		return FALSE;
	if(iType == V_ASN1_UTF8STRING)
	{
		char lpdst[1024] = {0};
		int dstlen = 0;
		char input[256]={0};
		strncpy(input, lpszInput, iLen);
		Ansi2Utf8(input, iLen, lpdst, dstlen);
		X509_NAME_add_entry_by_NID(px509Name,iNid,V_ASN1_UTF8STRING,(UCHAR *)lpdst,dstlen, -1, 0);	
	}
	else
		X509_NAME_add_entry_by_NID(px509Name,iNid,iType,(UCHAR *)lpszInput,iLen, -1, 0);	
	return TRUE;
}

BOOL Add_Name(X509_NAME * px509Name,const char * field/*c\cn*/,
			  const char * lpszInput/*中国*/,
			  const int iLen/*输入长度*/)//支持中文名称
{
	if(NULL == lpszInput || strlen(lpszInput) == 0)
		return FALSE;

	BOOL bRet = FALSE;

	int nid = NID_undef;

	int iType = V_ASN1_UTF8STRING;

	if(strstr(field, ".") == NULL) //没有发现.
	{
		nid = OBJ_txt2nid(field);
	}
	else
	{
		nid = OBJ_create(field, field, field);
	}
	if(nid != NID_undef)
	{
		if(NID_pkcs9_emailAddress == nid)
		{
			iType = V_ASN1_IA5STRING;
		}
		else
		{
			iType = V_ASN1_UTF8STRING;
		}

		bRet = Add_Name(px509Name, nid, iType, lpszInput, iLen);
	}
	OBJ_cleanup();	

	return bRet;
}

void AddName(X509_NAME * px509Name,const stuSUBJECT * pSubJect)
{
	setlocale(LC_CTYPE, "");

	while(pSubJect != NULL)//遍历链表
	{
		Add_Name(px509Name, (char *)pSubJect->cName, (char *)pSubJect->cInfo,strlen((char *)pSubJect->cInfo));
		pSubJect = pSubJect->Link;
	}

/*




	Add_Name(px509Name,NID_stateOrProvinceName,V_ASN1_UTF8STRING,(char *)pSubJect->ST,strlen((char *)pSubJect->ST));
	Add_Name(px509Name,NID_localityName,V_ASN1_UTF8STRING,(char *)pSubJect->L,strlen((char *)pSubJect->L));
	Add_Name(px509Name,NID_organizationName,V_ASN1_UTF8STRING,(char *)pSubJect->O,strlen((char *)pSubJect->O));
	Add_Name(px509Name,NID_organizationalUnitName,V_ASN1_UTF8STRING,(char *)pSubJect->OU,strlen((char *)pSubJect->OU));

⌨️ 快捷键说明

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