首页 | 新闻资讯 | 培训认证 | 安全管理 | 病毒分析 | 安全协议 | 网络安全 | 防火墙 | 黑客技术
DB安全 | Web安全 | 入侵检测 | 安全审计 | 设备安全 | 备份恢复 | 安全标准 | 法律法规 | 无线安全
OS安全 | PKI与PMI | 病毒防治 | 隔离网闸 | XML安全 | 网管专区 | 经典案例 | 技术论坛 |  
+ 文章搜索 +
当前位置:首页>>原创作品>>PKI与PMI>>正文
关键字:
范 围:
※推荐文章※
·在web上如何自动安装用户证书及根
程序中生成证书请求的两种方法
作者:rainbow 文章出处:中国信息安全组织[原创] 发布时间:2004-07-30 点击: 字体: 【

/********************************************************************************************************************
声明:本文档用于学习与研究可以自由转载,无论以何种形式发布都必须保留完整的版权声明,商业用途不得转载.本人能力有限,如有问题欢迎交流与指正。
网站:
论坛:/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);
}



以上代码中是片段,仅供参考,本人能力有限,欢迎交流与指正,谢谢。
如果还有不清楚的地方,欢迎到论坛提问

 

返回顶部↑】 【推荐好友】 【查看评论
用户名: 新注册) 密码: 匿名评论 [查看评论] 发表评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
  Copyright © 2004-2005 infosecurity.org.cn . All Rights Reserved
版权所有:中国信息安全组织 系统管理:webmaster@infosecurity.net.cn
本站部分资源来自互联网,如有侵犯您的版权或其他问题,请通知管理员,我们会尽快处理!