?? certmng.cpp
字號:
#include "stdafx.h"
#include "CertMng.h"
using namespace std;
CCertMng * CCertMng::m_pMng = 0;
CRWLock CCertMng::m_Cert_Lock;
volatile bool CCertMng::m_bCert_Locked = false;
CCertMng::CCertMng()
{
m_pVoid = 0;
m_lpfnGenKey = 0;
m_lpfnPass_Callback = 0;
m_lpfnGet_Dn_Value = 0;
}
int CCertMng::Initialize ( conv_tool::OPERATORS_MAP mapOpr,
LPGENERATEKEY pfnGenKey,
LPPASSWORD_CALLBACK pfnPass,
LPGET_DN_VALUE pfnDnValue,
LPVERIFY_CALLBACK pfnVerify,
void * pVoid)
{
m_pVoid = pVoid;
m_lpfnGenKey = pfnGenKey;
m_lpfnPass_Callback = pfnPass;
m_lpfnGet_Dn_Value = pfnDnValue;
m_lpfnVerify_Callback = pfnVerify;
conv_tool::OPERATORS_MAP::iterator it = mapOpr.find ( RAND_FILE );
if ( it != mapOpr.end () )
{
m_szRandFile = it->second;
}
if ( ( it = mapOpr.find ( CONF_FILE ) ) != mapOpr.end () )
m_szConfFile = it->second;
return 0;
}
void CCertMng::Uninitialize ()
{
}
int CCertMng::Generate_Key ( conv_tool::OPERATORS_MAP mapOpt, xmlChar ** ppszXML, int *pnLen )
{
RSA * rsa = NULL;
const EVP_CIPHER * enc = NULL;
unsigned long exp = RSA_F4;
BIO * bio_out = NULL;
int ret = -1;
int nSize = 1024;
int nCipher = RSA_CIPHER;
int nOut = FILE_TYPE;
std::string szKeyFile;
conv_tool::OPERATORS_MAP mapRet;
conv_tool::OPERATORS_MAP::iterator it;
it = mapOpt.find ( KEY_LENGTH );
if ( it != mapOpt.end () )
nSize = atoi ( it->second.c_str () );
it = mapOpt.find ( CIPHER_TYPE );
if ( it != mapOpt.end () )
nCipher = atoi ( it->second.c_str() );
it = mapOpt.find ( OUT_TYPE );
if ( it != mapOpt.end () )
nOut = atoi ( it->second.c_str() );
it = mapOpt.find ( KEY );
if ( it != mapOpt.end () )
szKeyFile = it->second;
if ( nOut == FILE_TYPE && szKeyFile.length() == 0 )
{
CError::Interface ()->Handle_Error ( 0, "參數(輸出文件名)不能為NULL" );
return -1;
}
switch ( nCipher )
{
case RSA_CIPHER:
break;
case DES_CIPHER:
enc = EVP_des_cbc ();
break;
case DES3_CIPHER:
enc = EVP_des_ede3_cbc ();
break;
default:
break;
}
//生成輸出BIO
if ( ( bio_out = Bio_Write ( nOut, szKeyFile.c_str() ) ) == NULL )
{
CError::Interface ()->Handle_Error ( 0, "生成密鑰文件失敗:%s", szKeyFile.c_str() );
goto end;
}
CRandMng::Interface ()->Rand_Load_File ( m_szRandFile );
rsa = RSA_generate_key ( nSize, exp, Process_Key, this );
CRandMng::Interface()->Rand_Write_File ( m_szRandFile );
if ( rsa == NULL )
CError::Interface ()->Handle_Error ( 0, "生成密鑰失敗(返回值=NULL)" );
else
{
if ( ! PEM_write_bio_RSAPrivateKey ( bio_out, rsa, enc, NULL, 0, ( pem_password_cb *)password_callback, this) )
CError::Interface ()->Handle_Error ( 0, "寫密鑰信息失敗" );
else
{
if ( nOut != FILE_TYPE )
{
std::string sout_put;
int nLen = 0;
char chLen[127];
if ( Get_BioStr ( bio_out, sout_put, &nLen ) < 0 )
{
CError::Interface()->Handle_Error( 0, "獲取輸出內容失敗");
goto end;
}
itoa ( nLen, chLen, 10 );
mapRet.insert ( std::make_pair ( std::string ( KEY ), sout_put ) );
mapRet.insert ( std::make_pair ( std::string ( KEY_LENGTH ), std::string ( chLen ) ) );
}
ret = 0; //返回值,成功
}
}
if ( conv_tool::Map2XML ( mapRet, ppszXML, pnLen ) < 0 )
{
CError::Interface()->Handle_Error ( 0, "轉換XML失敗" );
ret = -1;
}
end:
if (rsa != NULL)
RSA_free ( rsa );
if (bio_out != NULL)
BIO_free_all ( bio_out );
return ret;
}
// 生成證書憑證
int CCertMng::Generate_Req ( conv_tool::OPERATORS_MAP mapOpt,
xmlChar ** ppszXML, int * pnLen )
{
int ret = -1;
char * p = 0;
X509 * x509 = 0;
X509_REQ * x509_req = 0;
EVP_PKEY * pKey = 0;
int nKey_Type = TYPE_RSA;
int nKey_Fmt = FORMAT_PEM;
int nInFmt = FORMAT_PEM;
int nOutFmt = FORMAT_PEM;
int nDays = 30;
long nErrLine = 0;
int out_type = FILE_TYPE;
int in_type = FILE_TYPE;
ASN1_INTEGER * pSerial = 0;
CONF * req_conf = NULL;
BIO * bio_in = 0;
string szKeyFile, szOutFile, szInFile, szExt, szReqExt;
bool pub_key = 0, new_req = 0, if_x509 = 0, asn_kludge = false, verify = false;
unsigned long nCharset = MBSTRING_UTF8;
const EVP_MD * md_alg = NULL, * md_digest = EVP_md5();
conv_tool::OPERATORS_MAP::iterator it;
if ( ( it = mapOpt.find ( IN_FORMAT ) ) != mapOpt.end () )
nInFmt = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( OUT_FORMAT ) ) != mapOpt.end () )
nOutFmt = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( KEY ) ) != mapOpt.end () )
szKeyFile = it->second;
if ( ( it = mapOpt.find ( IF_PUBKEY ) ) != mapOpt.end () )
pub_key = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( IF_NEWREQ ) ) != mapOpt.end () )
new_req = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( KEY_FORMAT ) ) != mapOpt.end () )
nKey_Fmt = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( OUT_FILE ) ) != mapOpt.end () )
szOutFile = it->second;
if ( ( it = mapOpt.find ( IN_FILE ) ) != mapOpt.end () )
szInFile = it->second;
if ( ( it = mapOpt.find ( EXTENTIONS ) ) != mapOpt.end () )
szExt = it->second;
if ( ( it = mapOpt.find ( REQ_EXT ) ) != mapOpt.end () )
szReqExt = it->second;
if ( ( it = mapOpt.find ( CHAR_SET ) ) != mapOpt.end () )
nCharset = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( IF_X509 ) ) != mapOpt.end () )
if_x509 = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( DAYS ) ) != mapOpt.end () )
nDays = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( SERIAL ) ) != mapOpt.end () )
pSerial = s2i_ASN1_INTEGER ( NULL, (char*)it->second.c_str() );
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;
if ( ( it = mapOpt.find ( ASN_KLUDGE ) ) != mapOpt.end () )
asn_kludge = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( IF_VERIFY ) ) != mapOpt.end () )
verify = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( OUT_TYPE ) ) != mapOpt.end () )
out_type = atoi ( it->second.c_str() );
if ( ( it = mapOpt.find ( IN_TYPE ) ) != mapOpt.end () )
in_type = atoi ( it->second.c_str() );
if ( m_szConfFile.length () == 0 )
{
CError::Interface ()->Handle_Error ( 0, "缺少配置文件" );
goto end;
}
if ( szKeyFile.length () == 0 )
{
CError::Interface ()->Handle_Error ( 0, "缺少Key文件" );
goto end;
}
req_conf = NCONF_new ( NULL );
if ( NCONF_load ( req_conf, m_szConfFile.c_str(), &nErrLine ) == 0 )
{
CError::Interface()->Handle_Error ( 0, "讀取配置文件失敗:%s:%d", m_szConfFile.c_str(), nErrLine );
goto end;
}
if ( Load_Config ( req_conf ) < 0 )
goto end;
p = NCONF_get_string ( req_conf, NULL, OID_FILE );
if ( p != NULL)
{
BIO * bio_oid;
bio_oid = BIO_new_file ( p, "r" );
if ( bio_oid )
{
OBJ_create_objects ( bio_oid );
BIO_free ( bio_oid );
}
}
if ( Add_Oid_Section ( req_conf ) < 0 ) goto end;
if ( md_alg == NULL)
{
p = NCONF_get_string ( req_conf, REQ_SECTION, DEFAULT_MD );
if ( p != NULL )
{
if ( ( md_alg = EVP_get_digestbyname ( p ) ) != NULL )
md_digest = md_alg;
}
}
if ( szExt.length () == 0 )
{
p = NCONF_get_string ( req_conf, REQ_SECTION, V3_EXTENSIONS);
if ( p )
szExt = p;
}
if ( szExt.length () > 0 )
{
X509V3_CTX ctx;
X509V3_set_ctx_test ( &ctx );
X509V3_set_nconf ( &ctx, req_conf );
if ( ! X509V3_EXT_add_nconf ( req_conf, &ctx, (char*)szExt.c_str(), NULL ) )
{
CError::Interface()->Handle_Error ( 0, "讀取:%s失敗%s", V3_EXTENSIONS, szExt.c_str() );
goto end;
}
}
p = NCONF_get_string ( req_conf, REQ_SECTION, STRING_MASK );
if ( p && ! ASN1_STRING_set_default_mask_asc ( p ) )
{
CError::Interface()->Handle_Error ( 0, "不正確的字符串標識:%s", p);
goto end;
}
if ( nCharset != MBSTRING_UTF8 )
{
p = NCONF_get_string ( req_conf, REQ_SECTION, UTF8_IN );
if ( p )
{
if ( ! strcmp ( p, "yes" ) )
nCharset = MBSTRING_UTF8;
}
}
if ( szReqExt.length() == 0 )
{
p = NCONF_get_string ( req_conf, REQ_SECTION, REQ_EXTENSIONS );
if ( p ) szReqExt = p;
}
if ( szReqExt.length() > 0 )
{
X509V3_CTX ctx;
X509V3_set_ctx_test ( &ctx );
X509V3_set_nconf ( &ctx, req_conf );
if ( !X509V3_EXT_add_nconf ( req_conf, &ctx, (char*)szReqExt.c_str(), NULL ) )
{
CError::Interface ()->Handle_Error ( 0, "讀取%s失敗%s", REQ_EXTENSIONS, REQ_SECTION );
goto end;
}
}
if ( szKeyFile.length() > 0 )
{
pKey = Load_Key ( (char*)szKeyFile.c_str(), szKeyFile.length(), nKey_Fmt, in_type );
if ( pKey == NULL ) goto end;
if ( EVP_PKEY_type ( pKey->type ) == EVP_PKEY_DSA )
{
CRandMng::Interface ()->Rand_Load_File ( m_szRandFile );
}
}
if ( ! new_req )
{
if ( szInFile.length() == 0 )
{
CError::Interface ()->Handle_Error ( 0, "沒有證書文件" );
goto end;
}
//如果輸入為文件格式,則從文件中讀取
//讀取KEY
if ( ( bio_in = Bio_Read ( in_type, szInFile.c_str(), szInFile.length () ) ) == NULL )
{
CError::Interface ()->Handle_Error ( 0, "讀取證書文件失敗:%s", szInFile.c_str() );
goto end;
}
// 根據輸入格式生成X509憑證
switch ( nInFmt )
{
case FORMAT_ASN1:
x509_req = d2i_X509_REQ_bio ( bio_in, NULL );
break;
case FORMAT_PEM:
x509_req = PEM_read_bio_X509_REQ ( bio_in, NULL, NULL, NULL );
break;
default:
CError::Interface ()->Handle_Error ( 0, "證書格式不正確:%d,%s", nInFmt, szInFile.c_str() );
goto end;
break;
}
if ( x509_req == NULL )
{
CError::Interface ()->Handle_Error ( 0, "讀取x509 證書文件失敗:%s", szInFile.c_str() );
goto end;
}
}
// 判斷是否要新建憑證,并且是否需要自簽名
if ( new_req || if_x509 )
{
if ( pKey == NULL )
{
CError::Interface()->Handle_Error ( 0, "密鑰文件不存在" );
goto end;
}
if ( x509_req == NULL )
{
if ( ( x509_req = X509_REQ_new() ) == NULL ) goto end;
ret = Make_Request ( req_conf, x509_req, pKey, !if_x509, nCharset );
if ( asn_kludge && ! sk_X509_ATTRIBUTE_num ( x509_req->req_info->attributes ) )
{
sk_X509_ATTRIBUTE_free ( x509_req->req_info->attributes );
x509_req->req_info->attributes = 0;
}
if ( ret == -1 ) goto end;
}
// 如果要自簽名時進行下面操作
if ( if_x509 )
{
if ( ( x509 = X509_new ( ) ) == NULL )
{
CError::Interface ()->Handle_Error ( 0, "函數X509_new出錯(指針為NULL)" );
goto end;
}
if ( -1 == Sign_Request ( req_conf, x509, x509_req, pKey, szExt.c_str(),
pSerial, nDays, md_digest ) )
goto end;
}
else
{
X509V3_CTX ext_ctx;
X509V3_set_ctx ( &ext_ctx, NULL, NULL, x509_req, NULL, 0 );
X509V3_set_nconf ( &ext_ctx, req_conf );
if ( ( szReqExt.length() > 0 ) &&
! X509V3_EXT_REQ_add_nconf ( req_conf, &ext_ctx, (char*)szReqExt.c_str(), x509_req ) )
{
CError::Interface()->Handle_Error ( 0, "增加擴展屬性失敗:%s", szReqExt.c_str() );
goto end;
}
if ( ! X509_REQ_sign ( x509_req, pKey, md_digest ) )
goto end;
}
}
// 如果沒有自簽名,并且需要證書驗證時,進行下面操作
if ( verify && ! if_x509 )
{
if ( Verify_Request ( x509_req, pKey ) == -1 )
goto end;
}
if ( Out_Request ( x509, x509_req, out_type, szOutFile.c_str(),
if_x509, pub_key, nOutFmt, ppszXML, pnLen ) == -1 )
goto end;
ret = 0;
end:
if ( req_conf != NULL ) NCONF_free(req_conf);
if ( bio_in ) BIO_free ( bio_in );
if ( pKey ) EVP_PKEY_free ( pKey );
if ( x509_req ) X509_REQ_free ( x509_req );
if ( x509 ) X509_free ( x509 );
if ( pSerial ) ASN1_INTEGER_free ( pSerial );
OBJ_cleanup();
return ret;
}
//輸出憑證
int CCertMng::Out_Request ( X509 * x509, X509_REQ * req,
int out_type, const char *out,
bool is_x509, bool is_pub_key, int out_fmt,
xmlChar ** ppszXML, int * pnLen )
{
BIO * bio_out = 0;
BUF_MEM * mem_out = 0;
int ret = -1;
bool result = false;
conv_tool::OPERATORS_MAP mapret;
if ( ( bio_out = Bio_Write ( out_type, out) ) == NULL )
goto end;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -