📄 openssl.txt
字号:
标题:程序中生成证书请求的两种方法
时间:2004-07-30
来源:中国信息安全组织[原创]
程序中生成证书请求的两种方法
Rainbow(不经历风雨,怎么见彩虹)
/********************************************************************************************************************
声明:本文档用于学习与研究可以自由转载,无论以何种形式发布都必须保留完整的版权声明,商业用途不得转载.本人能力有限,如有问题欢迎交流与指正。
网站:http://www.infosecurity.org.cn
论坛:http://www.infosecurity.org.cn/forum/forum.html
邮件:rainbow_zrh@sina.com webmaster@infosecurity.org.cn
*********************************************************************************************************************/
一、在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
或者按<wincrypt.h>里的定义#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);
if(p->szO) AddEntry(0,p->szO);
if(p->szOU) AddEntry(0,p->szOU);
if(p->szName) AddEntry(0,p->szName);
if(p->szEmail) AddEntry(0,p->szEmail);
return subject;
}
3、设置好其它信息并签名
除了上面所的信息要设置以外,还要设置版本号、公钥、名字等。
req=X509_REQ_new();
if(!req)
{
goto err;
}
subject=x_name.getName(pReq);
if(!subject)
{
goto err;
}
if(!X509_REQ_set_version(req,0L)) goto err;
if(!X509_REQ_set_subject_name(req,subject)) goto err;
if(!X509_REQ_set_pubkey(req,pkey)) goto err;
if(!X509_REQ_sign(req,pkey,digest)) goto err;
4、保存
// output private key
outPvk = BIO_new_file(szPrivateKeyFileName, "w");
if (!outPvk)
{
m_str.Format("Error opening file %s", szPrivateKeyFileName);
goto err;
}
if (pkey)
{
if(szPrivateKeyPwd)
{
int len =strlen(szPrivateKeyPwd);
PEM_write_bio_PrivateKey(outPvk, pkey, EVP_des_ede3_cbc(),
(unsigned char*)szPrivateKeyPwd,len, NULL, NULL);
}
else
PEM_write_bio_PrivateKey(outPvk, pkey, NULL,NULL,0, NULL, NULL);
}
// output certificate request file
outReq = BIO_new_file(szReqFileName, "w");
if (!outReq)
{
m_str.Format("Error opening file %s", szReqFileName);
goto err;
}
if (req)
{
PEM_write_bio_X509_REQ(outReq, req);
}
以上代码中是片段,仅供参考,本人能力有限,欢迎交流与指正,谢谢。
如果还有不清楚的地方,欢迎到论坛提问
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -