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

📄 certmng.cpp

📁 实现证书的生成和验证
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	if ( ( buf = (char *)OPENSSL_malloc ( size ) ) == NULL )
	{
		CError::Interface ()->Handle_Error ( 0, "内存不足(malloc操作失败)" );
		goto end;
	}
	if ( snfile == NULL )
	{
		BUF_strlcpy ( buf, cafile, size );
		for ( p = buf; *p; p++ )
			if ( *p == '.' )
			{
				*p = '\0';
				break;
			}
		BUF_strlcat ( buf, POSTFIX, size );
	}
	else
		BUF_strlcpy ( buf, snfile, size );
	//构造序列号
	bnsn = BN_new ();
	ai = ASN1_INTEGER_new ();
	if ( ! bnsn || ! ai )
	{
		CError::Interface ()->Handle_Error ( 0, "内存不足(BN_new操作失败)" );
		goto end;
	}
	//读取序列号
	if ( ( bnsn = X509_sn::Load_Serial ( snfile, create, NULL ) ) == NULL )
		goto end;
	//递增
	if ( ! BN_add_word ( bnsn, 1 ) ) goto end;
	//保存序列号
	X509_sn::Save_Serial ( snfile, NULL, bnsn, &ai );

end:
	if ( buf ) OPENSSL_free ( buf );
	if ( bnsn ) BN_free ( bnsn );
	return ai;
}
//把申请凭证(request)转换为对应的证书(X509)
X509 * CCertMng::Request2X509 ( X509_REQ * req, ASN1_INTEGER * sn, long days )
{
	X509_CINF *  ci   = 0;
	X509      *  x509 = 0;
	EVP_PKEY  *  pKey = 0;

	if ( req == NULL ) return NULL;
	if ( ( x509 = X509_new () ) == NULL ) return NULL;
	ci = x509->cert_info;
	if ( sn )
	{
		if ( ! X509_set_serialNumber ( x509, sn ) ) goto end;
	}
	else if ( ! ASN1_INTEGER_set ( X509_get_serialNumber ( x509 ), 0 ) ) goto end;
	if ( ! X509_set_issuer_name ( x509, req->req_info->subject ) ) goto end;
	if ( ! X509_set_subject_name ( x509, req->req_info->subject ) ) goto end;
	X509_gmtime_adj ( X509_get_notBefore (x509), 0 );
	X509_gmtime_adj ( X509_get_notAfter (x509), (long)60*60*24*days );
	pKey = X509_REQ_get_pubkey ( req );
	X509_set_pubkey ( x509, pKey );
	EVP_PKEY_free ( pKey );
end:
	return x509;
}
//读取凭证
X509_REQ * CCertMng::Load_Request ( int in_type, const char * in )
{
	EVP_PKEY  *  pKey = 0;
	BIO       *  bio_in = 0;
	X509_REQ  *  req  = 0;

	if ( in == 0 )
		goto end;

	//判断输入格式
	if ( ( bio_in = Bio_Read ( in_type, in, strlen ( in ) ) ) == NULL )
	{
		CError::Interface()->Handle_Error( 0, "读取凭证信息失败%s", in );
		goto end;
	}
	
	if ( NULL == ( req = PEM_read_bio_X509_REQ ( bio_in, NULL, NULL, NULL ) ) ) 
		goto end;

	if ( ( req->req_info == NULL) ||
		( req->req_info->pubkey == NULL) ||
		( req->req_info->pubkey->public_key == NULL) ||
		( req->req_info->pubkey->public_key->data == NULL ) )
	{
		CError::Interface ()->Handle_Error ( 0, "凭证申请没用包含合法的公钥" );
		goto end;
	}
	if ( ( pKey = X509_REQ_get_pubkey ( req ) ) == NULL) goto end;
	if ( X509_REQ_verify ( req, pKey ) <= 0 )
	{
		CError::Interface ()->Handle_Error ( 0, "签名和凭证不匹配" );
		X509_REQ_free ( req );
		req = 0;
	}
end:
	if ( bio_in ) BIO_free ( bio_in );
	if ( pKey ) EVP_PKEY_free ( pKey );
	return req;
}
//输出公钥
int CCertMng::Out_Pubkey ( X509_REQ * req, BIO * out )
{
	if ( req == NULL )
		return -1;

	EVP_PKEY * pubkey = 0;
	pubkey = X509_REQ_get_pubkey ( req );
	if ( !pubkey )
	{
		CError::Interface ()->Handle_Error ( 0, "获取公钥失败" );
		return -1;
	}
	PEM_write_bio_PUBKEY ( out, pubkey );
	EVP_PKEY_free ( pubkey );
	return 0;
}
//证书验证
int CCertMng::Verify_Cert ( conv_tool::OPERATORS_MAP  mapOpt )
{
	string scapath, scafile, scertfile;
	string suntrust, strust;
	STACK_OF ( X509 ) * untrusted = 0, * trusted = 0;
	X509_STORE * xs_ctx = 0;
	X509_LOOKUP * xl = 0;
	int vflags = 0, result, type = FILE_TYPE;
	int ret = 0;
	char seps[] = "; ";
	char * stok = 0;

	conv_tool::OPERATORS_MAP::iterator it;

	if ( ! ( xs_ctx = X509_STORE_new ( ) ) ) {
		CError::Interface ()->Handle_Error ( 0, "X509_Store_new操作失败");
		goto end;
	}
	//设置回调函数
	X509_STORE_set_verify_cb_func ( xs_ctx, verify_callback );
	//获取参数
	if ( ( it = mapOpt.find ( CA_PATH ) ) != mapOpt.end() )
		scapath = it->second;
	if ( ( it = mapOpt.find ( CA_FILE ) ) != mapOpt.end () )
		scafile = it->second;
	if ( ( it = mapOpt.find ( CERT_FILE ) ) != mapOpt.end () )
		scertfile = it->second;
	if((it = mapOpt.find(IN_TYPE)) != mapOpt.end() )
		type = atoi(it->second.c_str());
	if ( ( it = mapOpt.find ( UNTRUST ) ) != mapOpt.end () )
		suntrust = it->second;
	if ( ( it = mapOpt.find ( TRUST ) ) != mapOpt.end () )
		strust = it->second;
	if ( ( it = mapOpt.find ( IGNORE_CERT ) ) != mapOpt.end () )
		vflags != X509_V_FLAG_IGNORE_CRITICAL;
	if ( ( it = mapOpt.find ( ISSUER_CHECK ) ) != mapOpt.end () )
		vflags != X509_V_FLAG_CB_ISSUER_CHECK;
	if ( ( it = mapOpt.find ( CRL_CHECK ) ) != mapOpt.end () )
		vflags != X509_V_FLAG_CRL_CHECK;
	if ( ( it = mapOpt.find ( CRL_CHECKALL ) ) != mapOpt.end () )
		vflags != X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;

	if ( scertfile.length () == 0 )
	{
		CError::Interface ()->Handle_Error ( 0, "没有要验证的证书文件" );
		goto end;
	}
	if ( ( xl = X509_STORE_add_lookup ( xs_ctx, X509_LOOKUP_file () ) ) == NULL ) {
		CError::Interface ()->Handle_Error ( 0, "X509_STORE_add_lookup()操作失败");
		goto end;
	}
	if ( scafile.length() > 0 )
	{
		result = X509_LOOKUP_load_file ( xl, (char*)scafile.c_str(), X509_FILETYPE_PEM );
		if ( !result )
		{
			CError::Interface ()->Handle_Error ( 0, "读取文件失败:%s", scafile.c_str() );
			goto end;
		}

	} 
	else
		X509_LOOKUP_load_file ( xl, NULL, X509_FILETYPE_DEFAULT );
	if ( ( xl = X509_STORE_add_lookup ( xs_ctx, X509_LOOKUP_hash_dir () ) ) == NULL) {
		CError::Interface ()->Handle_Error ( 0, "X509_STORE_add_lookup()操作失败%d", __LINE__);
		goto end;
	}
	//读取其他文件
	if ( suntrust.length () > 0 )
	{
		if ( ( untrusted = Load_UnTrusted ( suntrust.c_str() ) ) == NULL )
			goto end;
	}
	if ( strust.length () > 0 )
	{
		if ( ( trusted = Load_UnTrusted ( strust.c_str() ) ) == NULL )
			goto end;
	}
	if( type == FILE_TYPE )
	{
		stok = strtok ( (char*)scertfile.c_str(), seps );
		while ( stok != NULL )
		{
			if(!(ret = Check_Cert ( xs_ctx, stok, type, untrusted, trusted, vflags )))
				break;
			stok = strtok ( NULL, seps );
		}
	}
	else
		ret = Check_Cert(xs_ctx, scertfile.c_str(), type, untrusted, trusted, vflags );
end:
	if ( xs_ctx ) X509_STORE_free ( xs_ctx );
	if ( untrusted ) sk_X509_pop_free(untrusted, X509_free);
	if ( trusted ) sk_X509_pop_free ( trusted, X509_free );
	return ret;
}

//读取CRL
STACK_OF ( X509 ) *
CCertMng::Load_UnTrusted ( const char * certfile )
{
	STACK_OF(X509_INFO) * sk = NULL;
	STACK_OF(X509) * stack = NULL, *ret = NULL;
	BIO * in = NULL;
	X509_INFO * xi = 0;

	if( ! ( stack = sk_X509_new_null()))
		goto end;

	if( ! ( in = BIO_new_file ( certfile, "r" ) ) )
	{
		CError::Interface ()->Handle_Error ( 0, "打开文件失败:%s", certfile );
		goto end;
	}

	/* This loads from a file, a stack of x509/crl/pkey sets */
	if ( ! ( sk = PEM_X509_INFO_read_bio ( in, NULL, NULL, NULL ) ) )
	{
		CError::Interface ()->Handle_Error ( 0, "读取文件失败:%s", certfile );
		goto end;
	}

	/* scan over it and pull out the certs */
	while ( sk_X509_INFO_num ( sk ) )
	{
		xi = sk_X509_INFO_shift ( sk );
		if ( xi->x509 != NULL )
		{
			sk_X509_push ( stack, xi->x509 );
			xi->x509 = NULL;
		}
		X509_INFO_free(xi);
	}
	if( ! sk_X509_num ( stack ) )
	{
		CError::Interface ()->Handle_Error ( 0, "文件%s不包含证书信息", certfile );
		sk_X509_free ( stack );
		goto end;
	}

	ret = stack;
end:
	if ( in ) BIO_free(in);
	if ( sk ) sk_X509_INFO_free(sk);

	return ret;
}
//检查证书(包括CRL)
int CCertMng::Check_Cert ( X509_STORE * ctx, const char * certfile, int type,
				STACK_OF(X509) *uchain,
				STACK_OF(X509) *tchain, int vflags )
{
	
	int  ret = 0;
	X509 * x = 0;
	X509_STORE_CTX * xsc = 0;
	
	if ( ( x = Load_Cert ( type, certfile, FORMAT_PEM ) ) == NULL ) goto end;
	if ( ( xsc = X509_STORE_CTX_new () ) == NULL ) goto end;
	X509_STORE_set_flags ( ctx, vflags );
	if ( ! X509_STORE_CTX_init ( xsc, ctx, x, uchain ) ) goto end;
	if ( tchain )
		X509_STORE_CTX_trusted_stack ( xsc, tchain );
	ret = X509_verify_cert ( xsc );
	
end:
	if ( xsc ) X509_STORE_CTX_free ( xsc );
	if ( x ) X509_free ( x );
	return ret;
}

//证书验证回调函数
int CCertMng::verify_callback ( int ok, X509_STORE_CTX * ctx )
{
	if ( ! ok )
	{
		if (ctx->error == X509_V_ERR_CERT_HAS_EXPIRED) ok=1;
		/* since we are just checking the certificates, it is
		 * ok if they are self signed. But we should still warn
		 * the user.
 		 */
		if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1;
		/* Continue after extension errors too */
		if (ctx->error == X509_V_ERR_INVALID_CA) ok=1;
		if (ctx->error == X509_V_ERR_PATH_LENGTH_EXCEEDED) ok=1;
		if (ctx->error == X509_V_ERR_INVALID_PURPOSE) ok=1;
		if (ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ok=1;
		if (ctx->error == X509_V_ERR_CRL_HAS_EXPIRED) ok=1;
		if (ctx->error == X509_V_ERR_CRL_NOT_YET_VALID) ok=1;
		if (ctx->error == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION) ok=1;
	}
	return ok;
}
// 读取文件或字符串,返回BIO指针
BIO * CCertMng::Bio_Read (int in_type, const char * in, int len )
{
	BIO * bio_in = 0;

	if ( in_type == FILE_TYPE )
	{
		if ( ( bio_in = BIO_new ( BIO_s_file () ) ) == NULL )
			goto end;
		if ( BIO_read_filename ( bio_in, in ) < 0 )
		{
			BIO_free ( bio_in );
			bio_in = NULL;
			goto end;
		}
	}
	else
	{
		if ( ( bio_in = BIO_new( BIO_s_mem() ) ) == NULL )
			goto end;
		if ( BIO_write ( bio_in, in, len ) < 0 )
		{
			BIO_free ( bio_in );
			bio_in = NULL;
			goto end;
		}
	}
end:
	return bio_in;
}
//生成输出的BIO,根据类型判断输出是否是文件或者BUFFER
BIO * CCertMng::Bio_Write( int out_type, const char *out)
{
	BIO * bio_out = 0;

	if ( out == NULL )
		goto end;

	if ( out_type == FILE_TYPE )
	{
		bio_out = BIO_new ( BIO_s_file () );
		if ( BIO_write_filename ( bio_out, ( char*)out ) <= 0 )
		{
			BIO_free ( bio_out );
			bio_out = 0;
			goto end;
		}
	}
	else
		bio_out = BIO_new ( BIO_s_mem () );
end:
	return bio_out;
}
//从BIO中提取MEM指针,再本节BUF_MEM的地址和长度,把BIO中保存的内容取出到STR
int CCertMng::Get_BioStr( BIO * bio_out, std::string & sout, int * pnLen )
{
	BUF_MEM * buf_mem = 0;
	char    * buf     = 0;
	int       len     = 0;
	int       ret     = -1;

	if ( bio_out == NULL )
		goto end;

	BIO_get_mem_ptr ( bio_out, &buf_mem );
	BIO_set_close ( bio_out, BIO_NOCLOSE );
	len = buf_mem->length;

	buf = (char*)OPENSSL_malloc( len + 1 );

	memset ( buf, 0, len + 1 );
	memcpy ( buf, buf_mem->data, len );

	sout  = std::string ( buf );
	*pnLen = len;

	OPENSSL_free ( buf );
	ret = 0;
end:
	return ret;
}
/*检查证书是否和私钥以及公钥匹配,如果没有私钥参数,则只对证书及公钥进行检查*/
/*其中私钥可以为CA证书的私钥*/
int CCertMng::IsMatch(conv_tool::OPERATORS_MAP mapOpt)
{
	std::string scert;
	std::string skey;
	int type = FILE_TYPE, ret = 0;
	EVP_PKEY * pkey = NULL, * pukey = NULL;
	X509 * xcert = NULL;
	conv_tool::OPERATORS_MAP::iterator it;

	if( ( it=mapOpt.find( CERT_FILE ) ) !=mapOpt.end() )
		scert = it->second;
	if ( (it=mapOpt.find( KEY ) ) != mapOpt.end() )
		skey = it->second;
	if ( (it=mapOpt.find( IN_TYPE ) ) != mapOpt.end() )
		type = atoi( it->second.c_str() );
	if ( skey.length() != 0 )
		pkey = Load_Key((char*)skey.c_str(), skey.length(), FORMAT_PEM, type );
	//没有证书则返回
	if ( scert.length() == 0 )
		goto end;
	xcert = Load_Cert ( type, scert.c_str(), FORMAT_PEM);
	pukey = X509_get_pubkey (xcert);
	//公钥不匹配则直接返回
	if ( !(ret = X509_verify ( xcert, pukey ) ))
		goto end;
	//检查私钥
	if ( pkey )
		ret = X509_verify ( xcert, pkey );
end:
	if ( pkey ) EVP_PKEY_free(pkey);
	if ( pukey ) EVP_PKEY_free(pukey);
	if ( xcert ) X509_free(xcert);
	return ret;
}

⌨️ 快捷键说明

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