Openssl中形成X509证书的函数集中在genrsa.c,req.c,ca.c,x509.c等中,但是这些文件中的函数过于复杂,不太容易理解。下载了中国信息安全组织webmaster的CISOCA后受益非浅,思路清晰,真是非常感谢zrh。
一:准备工作
确保在windows2000系统安装了openssl,vc6.0。将libeay32.dll和SSLeay32.dll复制到system32目录下,将libeay32.lib和SSLeay32.lib复制到当前目录并且导入工程中,将openssl里inc32下的openssl复制到VC的include文件夹下(或者用option->directories也行),切记在主函数的开头包含如下:
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();
ERR_load_crypto_strings();
二:产生密钥对
从公钥基础设施(PKI)这个名词上就可以看出密钥在这个体系中的重要性,数字证书也就是将公钥和实体的一些信息绑定并且跟它相关的私钥联合使用,所以形成一对安全的密钥对是至关重要的。RSA算法是现在比较流行的公开密钥算法,在openssl里,产生RSA密钥对的文件为genrsa.c.
主要有如下两个函数:
1,app_RAND_load_files(char *file),它的目的是导入随机数种子文件。因为RSA算法的基础是随机产生两个大素数,所以随机数的产生极为重要,有时要配置专用机器随时生成,不过这里可以建立一个包含两三行以上的随机字符的文件即可。
2,RSA_generate_key(int bits, unsigned long e_value,void (*callback)(int,int,void *), void *cb_arg),参数bits是密钥的长度(如1024),参数e_value是RSA中公开的加密密钥,一般有3, 17 or 65537,常用0x10001L(十进制的65537),第三,四个参数为产生私钥过程中的回调函数,在一般应用中将它们置为NULL即可。返回一个RSA结构,不过在应用中使用的是更高一层的EVP_PKEY结构。例如:
EVP_PKEY *m_pClientKey =EVP_PKEY_new();
EVP_PKEY_assign_RSA(m_pClientKey,RSA_generate_key(1024,0x10001,NULL,NULL))。
二:产生请求证书。
在openssl中,本部分由req.c实现,不过它实在过于复杂不太利于理解。
证书请求包括3个部分:证书请求信息,一个签名算法标识符和一个对证书请求信息的数字签名。证书的请求信息包括实体的别名、实体的公钥和一系列有关实体的其他信息的属性。构造一个证书请求包含如下几个步骤:
1,构造主体信息值,包含一个主体别名,一个主体公钥和一组可选属性
当然生成req证书需要一个申请一个X509_REQ对象。
加入主体信息还必须先申请一个X509_NAME对象,然后将信息先加到这里结构中,最后把这个结构赋给req。例如添加国家和省份信息:(NID_countryName为14,NID_stateOrProvinceName为16)
X509_REQ *req; X509_NAME *subj; char *country="cn";
X509_NAME_add_entry_by_NID(subj,14, MBSTRING_ASC,(unsigned char *)country, -1,-1,0);
X509_NAME_add_entry_by_NID(subj,16,MBSTRING_ASC,(unsigned char *)provinc,-1,-1,0) ;
X509_NAME_set(&req->req_info->subject, subj);
加入一个主体公钥(上小节生成的m_pClientKey)
X509_REQ_set_pubkey(req, m_pClientKey);
加入一组可选的扩展属性
STACK_OF(X509_EXTENSION) *extlist=sk_X509_EXTENSION_new_null();
X509_EXTENSION*ext=X509V3_EXT_conf(NULL,NULL,REQ_SUBJECT_ALT_NAME,value);
生成扩展对象
sk_X509_EXTENSION_push(extlist,ext);
X509_REQ_add_extensions(req,extlist)加入扩展项目。
2,用主体的私钥对上面的req进行签名。在签名是需要选择摘要算法,
EVP_MD *digest=EVP_md5()(选择MD5算法)
X509_REQ_sign(req,,m_pClientKey ,digest)
这样一份请求证书就形成拉。
三:形成X509证书
由上面的数字证书介绍我们已经知道了证书的构成项,下面我们就只需要一项一项添加即可
申请证书对象
X509 *ptemp=NULL;
X509 *m_pClientCert;
m_pClientCert = X509_new();
设置版本号
X509_set_version(ptemp, 2)
设置证书序列号,这个sn就是CA中心颁发的第N份证书
ASN1_INTEGER_set(X509_get_serialNumber(ptemp),sn)
设置证书开始时间
X509_gmtime_adj(X509_get_notBefore(ptemp),0)
设置证书结束时间
X509_gmtime_adj(X509_get_notAfter(ptemp), (long)60*60*24*days)
设置证书的主体名称,req就是刚刚生成的请求证书
X509_set_subject_name(ptemp, X509_REQ_get_subject_name(req))
设置证书的公钥信息
X509_set_pubkey(ptemp, X509_PUBKEY_get(req->req_info->pubkey))
设置证书的签发者信息,m_pCACert是CA证书
X509_set_issuer_name(ptemp, X509_get_subject_name(m_pCACert))
设置扩展项目
X509V3_CTX ctx;
X509V3_set_ctx(&ctx, m_pCACert, m_pClientCert, NULL, NULL, 0);
X509_EXTENSION *x509_ext = X509_EXTENSION_new();
x509_ext = X509V3_EXT_conf(NULL, name,value);
X509_add_ext(m_pClientCert,x509_ext,-1))
设置签名值
X509_sign(m_pClientCert,m_pCAKey,EVP_md5());
这样一份X509证书就生成了,下面的任务就是对它进行编码保存。
i2d_X509_bio(pbio, m_pClientCert) DER格式
PEM_write_bio_X509(pbio, m_pClientCert) PEM格式
这里只是简单讲解一下openssl API制作证书的过程,没有任何错误处理,也没有任何内存释放,要看原代码还请下载中国信息安全组织(www.infosecurity.org.cn)上的CISOCA, 由于本人水平有限,如有错误敬请原谅。(