程序中生成证书请求的两种方法

作者在 2006-12-03 00:43:00 发布以下内容
文章作者:Rainbow

程序中在web页面上生成证书请求的方法有两种,分别通过调用enumProviders接口和OpenSSL接口来实现。本文为您详细介绍这两种方法并提供相应的实例源代码。

一、在web页面上生成证书请求

在本地生成的证书请求的方式适用于CA不备份私钥或者说该私钥用于签名的情况。

1、枚举CSP

生成私钥的时候是通过枚举本地的CSP进行的,这个功能只需要通过调用xenroll.dll的enumProviders接口来实现。举例如下:


EnumProviders function EnumProviders()
nCSPIndex=0
ON ERROR resume next
do
sProviderName=IControl.enumProviders(nCSPIndex, 0)
if err.Number<>0 then
If &H80070103=Err.Number Then
Err.Clear
exit do
elseif err.number = 438 then
document.location="xenroll.dll"
exit do
else
msgbox Err.description
exit do
end if
end if
/*在这里添加你自己对CSP的显示部分*/
loop
end function


2、另外几个接口

xenroll.dll与生成证书请求相关的另外几接口是:

KeySpec ---用于设置或取得密钥的类型(即签名AT_SIGNATURE或密钥交换AT_KEYEXCHANGE)
HashAlgorithm-- 用于设置或取得对证书进行散列的算法,可以为MD2/MD5/SHA1,默认是SHA1。
GenKeyFlags---- 用于控制生成的私钥是否可以导出。默认是不可导出的,但可以设置成CRYPT_EXPORTABLE。或者按里的定义#define CRYPT_EXPORTABLE 0x00000001直接设置成1也可以。
ProviderName-- 就是CSP的名字,就是从注册表时读的名字。


3、生成DN

自己可以做一个简单的网页用来接收输入信息,我们将用这些信息生成dn.如果有对DN不熟悉的可以看一下网站里pki/pmi版面的内容。

比如:我们可以用vbscript定义一个dn的变量,然后将它们拼接起来。



DN = "";
DN = DN + "C=" + "\"" + cCountry + "\"" + ",";
DN = DN + "S=" + "\"" + cState + "\"" + ",";
DN = DN + "L=" + "\"" + cCity + "\"" + ",";
DN = DN + "CN=" + "\"" + cName + "\"" + ",";
DN = DN + "E=" + "\"" + cEMail + "\"";


4、调用CreatePKCS10接口

这个接口有两个参数第一个是上面所说的DN,另外一个是证书的用途,这里就一长串的OID,具体的用途可以看一下x.509 v3的rfx文档。

举例如下:

szPKCS10 = IControl.CreatePKCS10(DN, "1.3.6.1.5.5.7.3.2");


二、调用openssl接口生成请求

调用OpenSSL接口生成证书相对复杂一点,不过也可通过下面几个步骤来完成。

1、生成
RSA密钥对

第一个参数是密钥的长度,第二个是RSA算法中的e,这个参数在pkcs#1中有建议,

这里取65535(细节请到安全标准栏目中下载相关文档)

示例代码如下:

EVP_PKEY *pkey = NULL;
RSA *rsa = NULL;
rsa = RSA_generate_key(*(pReq->keylen),0x10001,NULL,NULL);
pkey =
EVP_PKEY_new();
if(!EVP_PKEY_assign_RSA(pkey,rsa))
{
m_str.Format("%s","generate RSA key pair error");
goto err;
}


2、生成X509Name

在这里我用了一个类来处理

// 加一个条目
int CX509Name::AddEntry(int key, char *value)
{

char *key_value[]={"countryName","stateOrProvinceName","localityName",
"organizationName","organizationalUnitName","commonName",
"emailAddress"};
int nid;
X509_NAME_ENTRY *ent;
if(subject == NULL)return -1;
if ((nid = OBJ_txt2nid(key_value[key])) == NID_undef)
return -1;
if (!(ent = X509_NAME_ENTRY_create_by_NID(NULL, nid,MBSTRING_ASC,(unsigned char*)value, -1)))
return -1;
if (X509_NAME_add_entry(subject, ent, -1, 0) != 1)
return -1;
return 1;
}
// 取得最终的结果
X509_NAME* CX509Name::getName(REQ_INFO *p)
{
if(p->szCN) AddEntry(0,p->szCN);
if(p->szST) AddEntry(0,p->szST);
if(p->szL) AddEntry(0,p->szL);
(编程)Work | 阅读 1821 次
文章评论,共0条
游客请输入验证码