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

📄 certmng.cpp

📁 实现证书的生成和验证
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	else
	{
		if ( m_lpfnGet_Dn_Value == NULL )
		{
			CError::Interface()->Handle_Error ( 0, "回调函数指针不能为NULL" );
			return -1;
		}
		if ( m_lpfnGet_Dn_Value ( text, def, buf, n_min, n_max, m_pVoid ) == -1 && buf[0] == '\n' )
		{
			BUF_strlcpy ( buf, def, sizeof  buf );
		}
		else if ( buf[0] == '.' && buf[1] == '\n' )
			return 0;
	}
	if ( buf[0] == '\0' ) return 0;
	if ( ( buf[0] == '.' ) && ( buf[1] == '\n' || buf[1] == '\0' ) )
		return 0;
	nLen = strlen ( buf );
	buf[nLen] = '\0';
	if ( ! X509_REQ_add1_attr_by_NID ( req, nid, char_set, (unsigned char *)buf, -1 ) )
	{
		CError::Interface()->Handle_Error ( 0, "增加%s属性失败", buf );
		return -1;
	}
	return 0;
}
// 读取证书,从文件或给定的字符串中转换
X509 * CCertMng::Load_Cert ( int in_type, const char * in, int format )
{
	ASN1_HEADER * ah  = 0;
	BUF_MEM     * buf = 0;
	X509        * x   = 0;
	BIO         * bio_cert = 0;
	int         errcode;

	if ( in == 0 )
		return NULL;

	if ( ( bio_cert = Bio_Read ( in_type, in, strlen(in) )) == NULL )
	{
		CError::Interface ()->Handle_Error ( 0, "读取证书失败:%s", in );
		goto end;
	}

	switch ( format )
	{
	case FORMAT_ASN1:
		x = d2i_X509_bio ( bio_cert, NULL );
		break;
	case FORMAT_NETSCAPE:
		{
			unsigned char *p,*op;
			int size=0, i;
			const int fix_len = 1024 * 10;

			buf=BUF_MEM_new();
			for (;;)
			{
				if ( ( buf == NULL ) ||
					( ! BUF_MEM_grow ( buf, size + fix_len ) ) )
					goto end;
				i = BIO_read ( bio_cert, &(buf->data[size]), fix_len );
				size += i;
				if ( i == 0 ) break;
				if ( i < 0 ) goto end;
			}

			op = p = (unsigned char *)buf->data;

			if ( (ah = d2i_ASN1_HEADER ( NULL, &p, (long)size) ) == NULL)
				goto end;
			if ( (ah->header == NULL) ||
				( ah->header->data == NULL) ||
				( strncmp ( NETSCAPE_CERT_HDR, (char *)ah->header->data, ah->header->length) != 0))
			{
				CError::Interface ()->Handle_Error ( 0, "证书格式头不正确" );
				goto end;
			}
			p = op;
			ah->meth = X509_asn1_meth();
			if ( (ah=d2i_ASN1_HEADER( &ah, &p, (long)size)) == NULL)
				goto end;
			x = (X509 *)ah->data;
		}
		break;
	case FORMAT_PEM:
		x = PEM_read_bio_X509_AUX ( bio_cert, NULL,
			(pem_password_cb *)password_callback, NULL);
		if (x == NULL) {
			errcode = ERR_GET_REASON(ERR_peek_error());
			CError::Interface()->Handle_Error(errcode, "读取证书文件失败:%s", ERR_reason_error_string(errcode));
			if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE)
				ERR_clear_error();
			else
				X509err(X509_F_X509_LOAD_CERT_FILE,	ERR_R_PEM_LIB);
			goto end;
		}
		break;
	case FORMAT_PKCS12:
		{
			PKCS12 * p12 = d2i_PKCS12_bio ( bio_cert, NULL );
			PKCS12_parse ( p12, NULL, NULL, &x, NULL );
			PKCS12_free ( p12 );
		}
		break;
	default:
		CError::Interface()->Handle_Error ( 0, "证书的类型不正确:%d", format );
		break;
	}
end:
	if ( ah ) ASN1_HEADER_free ( ah );
	if ( bio_cert ) BIO_free ( bio_cert );
	if ( buf ) BUF_MEM_free ( buf );
	return x;
}
//用CA证书为其他证书签名
int CCertMng::Sign_Cert ( conv_tool::OPERATORS_MAP mapOpt,
						 xmlChar ** ppszXML, int *pnLen )
{
	int            result  = 0;
	int            ret     = -1;
	X509_REQ     * req     = 0;
	X509         * x509    = 0,
		         * xca509  = 0;
	EVP_PKEY     * pKey    = 0,
		         * pcaKey  = 0;
	ASN1_OBJECT  * objtmp  = 0;
	ASN1_INTEGER * sn      = 0;
	X509_STORE   * ctx     = 0;
	const EVP_MD * md_alg = 0, * md_digest = EVP_md5();
	int  infmt    = FORMAT_PEM,
		 outfmt   = FORMAT_PEM,
		 keyfmt   = FORMAT_PEM,
		 cafmt    = FORMAT_PEM,
		 cakeyfmt = FORMAT_PEM;
	int  days     = DEF_DAYS;
	int  in_type  = FILE_TYPE;
	int  out_type = FILE_TYPE;
	long nErrLine = 0;
	bool is_pubkey = false, is_req = false, is_newsn = false;
	
	string sin, sout, skeyfile, scafile, scakey;
	string sext, salias, sserial;
	CONF * extcnf = 0;
	char * p = 0;

	conv_tool::OPERATORS_MAP::iterator it;

	if ( ( it = mapOpt.find ( IN_FORMAT ) ) != mapOpt.end () )
		infmt = atoi ( it->second.c_str() );
	if ( ( it = mapOpt.find ( OUT_FORMAT ) ) != mapOpt.end () )
		outfmt = atoi ( it->second.c_str() );
	if ( ( it = mapOpt.find ( KEY_FORMAT ) ) != mapOpt.end () )
		keyfmt = atoi ( it->second.c_str() );
	if ( ( it = mapOpt.find ( CA_FORMAT ) ) != mapOpt.end () )
		cafmt = atoi ( it->second.c_str() );
	if ( ( it = mapOpt.find ( CAKEY_FORMAT ) ) != mapOpt.end () )
		cakeyfmt = atoi ( it->second.c_str() );
	if ( ( it = mapOpt.find ( IN_TYPE ) ) != mapOpt.end () )
		in_type = atoi ( it->second.c_str() );
	if ( ( it = mapOpt.find ( OUT_TYPE ) ) != mapOpt.end () )
		out_type = atoi ( it->second.c_str() );

	if ( ( it = mapOpt.find ( DAYS ) ) != mapOpt.end () )
		days = atoi ( it->second.c_str() );
	if ( ( it = mapOpt.find ( IF_PUBKEY ) ) != mapOpt.end () )
		is_pubkey = atoi ( it->second.c_str() );
	if ( ( it = mapOpt.find ( IF_REQ ) ) != mapOpt.end () )
		is_req = atoi ( it->second.c_str() );
	if ( ( it = mapOpt.find ( IF_NEWSN ) ) != mapOpt.end () )
		is_newsn = atoi ( it->second.c_str() );

	if ( ( it = mapOpt.find ( KEY ) ) != mapOpt.end () )
		skeyfile = it->second;
	if ( ( it = mapOpt.find ( IN_FILE ) ) != mapOpt.end () )
		sin  = it->second;
	if ( ( it = mapOpt.find ( OUT_FILE ) ) != mapOpt.end () )
		sout = it->second;
	if ( ( it = mapOpt.find ( CA_FILE ) ) != mapOpt.end () )
		scafile = it->second;
	if ( ( it = mapOpt.find ( CAKEY_FILE ) ) != mapOpt.end () )
		scakey = it->second;
	if ( ( it = mapOpt.find ( EXTENTIONS ) ) != mapOpt.end () )
		sext = it->second;
	if ( ( it = mapOpt.find ( CA_SERIAL ) ) != mapOpt.end () )
		sserial = it->second;
	if ( ( it = mapOpt.find ( SERIAL ) ) != mapOpt.end () )
		sn = s2i_ASN1_INTEGER ( NULL, (char*)it->second.c_str() );
	if ( ( it = mapOpt.find ( ALIAS ) ) != mapOpt.end () )
		salias = it->second;
	if ( ( it = mapOpt.find ( MD_DIGEST ) ) != mapOpt.end () )
		md_alg = EVP_get_digestbyname ( (char*)it->second.c_str() );
	if ( md_alg )
		md_digest = md_alg;

	//读取随机数
	CRandMng::Interface ()->Rand_Load_File ( m_szRandFile );

	if ( scafile.length () == 0 )
	{
		CError::Interface ()->Handle_Error ( 0, "缺少参数,没有CA证书" );
		goto end;
	}
	
	if ( ( ctx = X509_STORE_new () ) == NULL ) goto end;
	if ( ! X509_STORE_set_default_paths ( ctx ) ) goto end;

	if ( ( scakey.length () == 0 ) &&
		( scafile.length() > 0 ) &&
		( cafmt == FORMAT_PEM ) )
	{
		scakey = scafile;
	}

	if ( m_szConfFile.length () > 0 )
	{
		X509V3_CTX ctx2;
		extcnf = NCONF_new ( NULL );
		if ( NCONF_load ( extcnf, m_szConfFile.c_str(), &nErrLine ) == 0 )
		{
			CError::Interface()->Handle_Error ( 0, "读取配置文件失败:%s:%d", m_szConfFile.c_str(), nErrLine );
			goto end;
		}

		if ( Load_Config ( extcnf ) < 0 ) goto end;
		if ( sext.length () == 0 )
		{
			p = NCONF_get_string ( extcnf, DEF_SECTION, DEF_EXTENSIONS );
			if ( p )
				sext = p;
			else
				sext = DEF_SECTION;
		}
		X509V3_set_ctx_test ( &ctx2 );
		X509V3_set_nconf ( &ctx2, extcnf );
		if ( ! X509V3_EXT_add_nconf ( extcnf, &ctx2, (char*)sext.c_str(), NULL ) )
		{
			CError::Interface ()->Handle_Error ( 0, "增加扩展属性失败:%s", sext.c_str() );
			goto end;
		}
	}
	if ( is_req )
	{
		if (  ( req = Load_Request ( in_type, sin.c_str() ) ) == NULL )	goto end;
		if ( ( x509 = Request2X509 ( req, sn, days ) ) == NULL ) goto end;
	}
	else
		x509 = Load_Cert ( in_type, sin.c_str(), infmt );
	
	if ( ( xca509 = Load_Cert ( FILE_TYPE, scafile.c_str(), cafmt ) ) == NULL ) goto end;
	
	if ( salias.length () > 0 )
		X509_alias_set1 ( x509, (unsigned char *)salias.c_str(), -1 );

	//读取CA的KEY
	if ( ( pcaKey = Load_Key ( (char*)scakey.c_str(), scakey.length(), cakeyfmt ) ) == NULL )
		goto end;
	//签名
	if ( 0 == x509_Sign ( ctx, scafile.c_str(), md_digest, x509, xca509,
		pcaKey, (char*)sserial.c_str(), is_newsn, days, extcnf, sext.c_str(), sn ) )
	{
		//输出
		if ( Out_X509 ( x509, out_type, sout.c_str(), outfmt, ppszXML, pnLen ) == -1 )
		{
			CError::Interface ()->Handle_Error ( 0, "输出操作失败:%s", sout.c_str() );
			goto end;
		}
		ret = 0;
	}

end:
	CRandMng::Interface ()->Rand_Write_File ( m_szRandFile );
	if ( extcnf ) NCONF_free ( extcnf );
	if ( ctx ) X509_STORE_free ( ctx );
	if ( req ) X509_REQ_free ( req );
	if ( x509 ) X509_free ( x509 );
	if ( xca509 ) X509_free ( xca509 );
	if ( pKey ) EVP_PKEY_free ( pKey );
	if ( pcaKey ) EVP_PKEY_free ( pcaKey );
	if ( sn ) ASN1_INTEGER_free ( sn );

	return ret;
}
//用CA证书为凭证申请签名
int CCertMng::x509_Sign ( X509_STORE * ctx, const char * cafile, const EVP_MD * digest,
		X509 * x, X509 * xca, EVP_PKEY * pKey, const char * serial, bool create_sn, long days,
		CONF * conf, const char * ext_section, ASN1_INTEGER * sn )
{
	int ret = -1;
	ASN1_INTEGER   * ai = 0;
	X509_STORE_CTX   xsc;
	EVP_PKEY       * upKey = 0;

	//复制CA的KEY
	upKey = X509_get_pubkey ( xca );
	EVP_PKEY_copy_parameters ( upKey, pKey );
	EVP_PKEY_free ( upKey );
	if ( ! X509_STORE_CTX_init ( &xsc, ctx, x, NULL ) )
	{
		CError::Interface ()->Handle_Error ( 0, "初始化x509失败" );
		goto end;
	}
	//序列号
	if ( sn )
		ai = sn;
	else if ( ( ai = X509_Load_Serial ( cafile, serial, create_sn ) ) == NULL )
		goto end;

	X509_STORE_CTX_set_cert ( &xsc, x );

	//验证需要签名的证书
	/*if ( ! X509_verify_cert ( &xsc ) )
	{
		CError::Interface ()->Handle_Error ( 0, "证书错误" );
		goto end;
	}*/
	if ( CA_Sign ( x, xca, pKey, ai, days, digest, conf, ext_section ) == -1 )
	{
		CError::Interface ()->Handle_Error ( 0, "签名失败" );
		goto end;
	}
	ret = 0;
end:
	X509_STORE_CTX_cleanup ( & xsc );
	if ( ai ) ASN1_INTEGER_free ( ai );
	return ret;
}
//用CA证书为其他证书签名
int
CCertMng::CA_Sign ( X509 * x, X509 * xca,
				   EVP_PKEY * pKey,
				   ASN1_INTEGER * ai,
				   long days, const EVP_MD * digest,
				   CONF * conf, const char * extsec )
{
	int ret = -1;

	//检查CA
	if ( ! X509_check_private_key ( xca, pKey ) )
	{
		CError::Interface ()->Handle_Error ( 0, "CA证书和KEY不匹配" );
		goto end;
	}
	//用CA签名
	if ( ! X509_set_issuer_name ( x, X509_get_subject_name ( xca ) ) ) goto end;
	if ( ! X509_set_serialNumber ( x, ai ) ) goto end;
	if ( X509_gmtime_adj ( X509_get_notBefore ( x ), 0L ) == NULL ) goto end;
	if ( X509_gmtime_adj ( X509_get_notAfter ( x ), (long)60*60*24*days ) == NULL) goto end;
	if ( conf )
	{
		X509V3_CTX ctx;
		X509_set_version ( x, 2 ); /* version 3 certificate */
		X509V3_set_ctx ( & ctx, xca, x, NULL, NULL, 0);
		X509V3_set_nconf ( & ctx, conf );
		if ( ! X509V3_EXT_add_nconf ( conf, & ctx, (char*)extsec, x ) ) goto end;
	}
	if ( ! X509_sign ( x, pKey, digest ) ) goto end;
	ret = 0;
end:
	return ret;
}
//输出证书,输出格式为文件或返回XML
int CCertMng::Out_X509 ( X509 * x,
						int out_type,
						const char * outfile,
						int outfmt,
						xmlChar **ppszXML, int * pnLen )
{
	int ret = -1;
	int result = 0;
	BUF_MEM * bm = 0;
	BIO     * out = 0;

	//生成IO,如果输出文件名为空,则输出到内存中
	if ( (out = Bio_Write ( out_type, outfile ) ) < 0 )
		goto end;

	//根据输出格式写证书, 写到BIO结构
	switch ( outfmt )
	{
	case FORMAT_ASN1:
		result = i2d_X509_bio ( out, x );
		break;
	case FORMAT_PEM:
		result = PEM_write_bio_X509 ( out, x );
		break;
	default:
		CError::Interface ()->Handle_Error ( 0, "输出格式不正确:%d", outfmt );
		break;
	}
	if ( ! result )
	{
		CError::Interface ()->Handle_Error ( 0, "写证书失败" );
		goto end;
	}
	//如果输出格式不是文件的话,从BIO提出MEM生成XML
	if ( out_type != FILE_TYPE )
	{
		conv_tool::OPERATORS_MAP mapret;
		std::string sout_put;
		int nLen = 0;
		char chLen[127];

		if ( Get_BioStr( out, sout_put, & nLen ) < 0 )
			goto end;
		
		itoa (  nLen, chLen, 10 );
		mapret.insert ( std::make_pair ( std::string ( CERT_FILE ), sout_put ) );
		mapret.insert ( std::make_pair ( std::string ( CERT_LENGTH ), std::string ( chLen ) ) );
		
		if ( conv_tool::Map2XML ( mapret, ppszXML, pnLen ) == -1 )
		{
			CError::Interface()->Handle_Error ( 0, "转换成XML失败" );
			goto end;
		}
	}
	ret = 0;
end:
	if ( out ) BIO_free ( out );
	return ret;
}
//生成证书所需要的序列号(从序列号文件读取)
ASN1_INTEGER *
CCertMng::X509_Load_Serial ( const char * cafile, const char * snfile, bool create)
{
	char * buf = 0, *p = 0;
	ASN1_INTEGER * ai = 0;
	BIGNUM       * bnsn = 0;
	size_t  size;

	//文件长度
	size = (snfile == NULL ) ?
		( strlen ( cafile ) + strlen ( POSTFIX ) + 1 ) : (strlen ( snfile ) + 1 );

⌨️ 快捷键说明

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