// CA.cpp : Defines the entry point for the DLL application.
//
#define sprintf_s sprintf
#include "stdafx.h"
#include <LOCALE.H>
#include "ca.h"
#include <OPENSSL pem.h>
#include <OPENSSL x509.h>
#include <OPENSSL x509v3.h>
#include <OPENSSL pkcs12.h>
#include <OPENSSL rand.h>
#include<STDLIB.H>
#include<STDIO.H>
#include <OPENSSL engine.h>
#define EXT_COPY_NONE 0
#define EXT_COPY_ADD 1
#define EXT_COPY_ALL 2
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
/*此函数可以将DER、PEM、P12文件公钥读出来*/
X509 *load_cert(BIO *cert/*输入BIO*/, int format/*格式*/,char * pwd,/*P12密码*/
char * outMsg) //从DER、PEM、P12格式中读取公钥证书
{
X509 * x=NULL;
if (format == DER)
x=d2i_X509_bio(cert,NULL);
else if (format == PEM)
x=PEM_read_bio_X509(cert,NULL,NULL,NULL);//PEM_read_bio_X509_AUX
else if (format == P12)
{
PKCS12 *p12 = d2i_PKCS12_bio(cert, NULL);
PKCS12_parse(p12, pwd, NULL, &x, NULL);
PKCS12_free(p12);
p12 = NULL;
}
else
{
sprintf_s(outMsg,"bad input format specified for input cert\n");
goto end;
}
end:
if (x == NULL)
{
sprintf(outMsg,"unable to load certificate\n");
}
return(x);
}
X509 * LoadCert(char * cert,int certlen,char * outMsg)//枚举DER/PEM格式
{
BIO * in=NULL;
X509 * x509=NULL;
if(certlen==0)//输入为磁盘文件
{
if((in=BIO_new_file(cert, "r")) == NULL)
{
sprintf(outMsg,"open CA certificate file error");
return NULL;
}
}
else//输入为内存中文件
{
if((in=BIO_new_mem_buf(cert,certlen))== NULL)//只读类型
{
sprintf(outMsg,"Make Mem Bio Error");
return NULL;
}
}
if((x509=load_cert(in,DER,NULL,outMsg))==NULL)//尝试DER
{
BIO_reset(in);//恢复bio
x509=load_cert(in,PEM,NULL,outMsg);//尝试PEM
}
if (in != NULL) BIO_free(in);
return x509;
}
EVP_PKEY *load_key(BIO *bio, int format, char *pass,char * outMsg)//枚举DER/PEM格式
{
EVP_PKEY *pkey=NULL;
if (format == DER)
{
pkey=d2i_PrivateKey_bio(bio, NULL);
}
else if (format == PEM)
{
pkey=PEM_read_bio_PrivateKey(bio,NULL,NULL,pass);
}
else if (format == P12)
{
PKCS12 *p12 = d2i_PKCS12_bio(bio, NULL);
PKCS12_parse(p12, pass, &pkey, NULL, NULL);
PKCS12_free(p12);
p12 = NULL;
}
else
{
sprintf(outMsg,"bad input format specified for key\n");
goto end;
}
end:
if (pkey == NULL)
sprintf(outMsg,"unable to load Private Key\n");
return(pkey);
}
EVP_PKEY * LoadKey(char * key,int keylen,char * pass,char * outMsg)
{
EVP_PKEY *pkey=NULL;
BIO * in=NULL;
if(keylen==0)//输入为磁盘文件
{
if((in=BIO_new_file(key, "r")) == NULL)
{
sprintf(outMsg,"open CA certificate file error");
return NULL;
}
}
else//输入为内存中文件
{
if((in=BIO_new_mem_buf(key,keylen))== NULL)//只读类型
{
sprintf(outMsg,"Make Mem Bio Error");
return NULL;
}
}
if((pkey=load_key(in,DER,pass,outMsg))==NULL)//尝试DER
{
BIO_reset(in);//BIO是可读写的,那么该BIO所有数据都会被清空;
//如果该BIO是只读的,那么该操作只会简单将指
//针指向原始位置,里面的数据可以再读.
pkey=load_key(in,PEM,pass,outMsg);//尝试PEM
}
if (in != NULL) BIO_free(in);
return pkey;
}
int Rand(const char *file,int dont_warn,char * outMsg)//产生随机数,return 0 ---成功
{
int consider_randfile = (file == NULL);
char buffer[200];
RAND_screen();
if (file == NULL)
file = RAND_file_name(buffer, sizeof buffer);
else if (RAND_egd(file) > 0)
{
/* we try if the given filename is an EGD socket.
if it is, we don't write anything back to the file. */
return 1;
}
if (file == NULL || !RAND_load_file(file, -1))
{
if (RAND_status() == 0 && !dont_warn)
{
sprintf(outMsg,"unable to load 'random state'\n");
sprintf(outMsg,"This means that the random number generator has not been seeded\n");
if (consider_randfile) /* explanation does not apply when a file is explicitly named */
{
sprintf(outMsg,"Consider setting the RANDFILE environment variable to point at a file that\n");
sprintf(outMsg,"'random' data can be kept in (the file will be overwritten).\n");
}
}
return 0;
}
return 1;
}
/ end
//
/ begin //
/* Add extension using V3 code: we can set the config file as NULL
* because we wont reference any other sections.
*/
int Add_ExtCert(X509 *cert/*正被添加的证书*/,X509 * root/*根证书(从中得到信息)*/, int nid, char *value)
{
X509_EXTENSION *ex;
X509V3_CTX ctx;
/* This sets the 'context' of the extensions. */
/* No configuration database */
// X509V3_set_ctx_nodb(&ctx);
/* Issuer and subject certs: both the target since it is self signed,
* no request and no CRL
*/
X509V3_set_ctx(&ctx,root, cert, NULL, NULL, 0);
ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
if (!ex)
return 0;
X509_add_ext(cert,ex,-1);
X509_EXTENSION_free(ex);
return 1;
}
bool Add_Name(X509_NAME * x509name,int type/*c\cn*/,char * iput/*中国*/,
int ilen/*输入长度*/,char * outMsg)//支持中文名称
{
wchar_t * ws,wc;
ASN1_STRING stmp, *str = &stmp;
UCHAR cbuf[256]={0};
int wslen, wcnt,i;
char input[256]={0};
strncpy(input, iput, ilen);
wslen = strlen(input) + 1;
if(wslen==1)
return true;
ws =new unsigned short[sizeof(wchar_t) * wslen];
if ((wcnt = mbstowcs(ws, input, wslen)) == -1)
{
sprintf(outMsg,"mbstowcs convert error");
delete ws;
return false;
}
for(i=0;i<(int)wcslen(ws);i++)
{
wc=ws[i];
cbuf[2*i]=wc/256;
cbuf[2*i+1]=wc%256;
}
ASN1_mbstring_copy(&str, cbuf, 2*wslen, MBSTRING_BMP, B_ASN1_UTF8STRING);
X509_NAME_add_entry_by_NID(x509name,type,V_ASN1_UTF8STRING,stmp.data,stmp.length, -1, 0);
delete ws;
return true;
}
bool mkRoot(stuSUBJECT * rootInfo,X509 **x509p/*out公钥*/, EVP_PKEY **pkeyp/*out私钥*/,
int bits/*位数*/, int serial/*序列号*/, int days/*有效期*/,char * out/*操作结果*/)
{
X509 *x;
EVP_PKEY *pk;
RSA *rsa;
X509_NAME *name=NULL;
int i=0,len=0;
if ((pkeyp == NULL) || (*pkeyp == NULL))
{
if ((pk=EVP_PKEY_new()) == NULL)
{
abort();
return false;
}
}
else
pk= *pkeyp;
if ((x509p == NULL) || (*x509p == NULL))
{
if ((x=X509_new()) == NULL)
goto err;
}
else
x= *x509p;
Rand(NULL,1,out);//产生随机数种子
rsa=RSA_generate_key(bits,RSA_F4,0/*回调函数callback*/,NULL);//产生密钥对,//RSA存储了公钥私钥
if (!EVP_PKEY_assign_RSA(pk,rsa))//完成RSA密钥的pkey结构初始工作,当pk不为NULL的时候,返回1,否则返回0
{
abort();
goto err;
}
rsa=NULL;
X509_set_version(x,2);//版本号,显示+1
ASN1_INTEGER_set(X509_get_serialNumber(x),serial);//序列号
X509_gmtime_adj(X509_get_notBefore(x),0);//起始时间
X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);//结束时间
X509_set_pubkey(x,pk);//公钥
name=X509_get_subject_name(x);
/* This function creates and adds the entry, working out the
* correct string type and performing checks on its length.
* Normally we'd check the return value for errors
*/
//C-国家,ST-省,L-城市,O-组织,OU-部门,CN-个体,T-title,D-description,G-givenName,I-initials,
//Email-emailAddress,S-surname,SN-serialNumber,dnQualifier-dnQualifier,unstructuredName,challengePassword,unstructuredAddress,
setlocale(LC_CTYPE, "");
Add_Name(name,NID_countryName,(char *)rootInfo->C,sizeof(rootInfo->C),out);
Add_Name(name,NID_stateOrProvinceName,(char *)rootInfo->ST,sizeof(rootInfo->ST),out);
Add_Name(name,NID_localityName,(char *)rootInfo->L,sizeof(rootInfo->L),out);
Add_Name(name,NID_organizationName,(char *)rootInfo->O,sizeof(rootInfo->O),out);
Add_Name(name,NID_organizationalUnitName,(char *)rootInfo->OU,sizeof(rootInfo->OU),out);
Add_Name(name,NID_commonName,(char *)rootInfo->CN,sizeof(rootInfo->CN),out);
Add_Name(name,NID_pkcs9_emailAddress,(char *)rootInfo->MAIL,sizeof(rootInfo->MAIL),out);
Add_Name(name,NID_email_protect,(char *)rootInfo->PMAIL,sizeof(rootInfo->PMAIL),out);
Add_Name(name,NID_title,(char *)rootInfo->T,sizeof(rootInfo->T),out);
Add_Name(name,NID_description,(char *)rootInfo->D,sizeof(rootInfo->D),out);
Add_Name(name,NID_givenName,(char *)rootInfo->G,sizeof(rootInfo->G),out);
Add_Name(name,NID_initials,(char *)rootInfo->I,sizeof(rootInfo->I),out);
Add_Name(name,NID_name,(char *)rootInfo->NAME,sizeof(rootInfo->NAME),out);
Add_Name(name,NID_surname,(char *)rootInfo->S,sizeof(rootInfo->S),out);
Add_Name(name,NID_dnQualifier,(char *)rootInfo->QUAL,sizeof(rootInfo->QUAL),out);
Add_Name(name,NID_pkcs9_unstructuredName,(char *)rootInfo->STN,sizeof(rootInfo->STN),out);
Add_Name(name,NID_pkcs9_challengePassword,(char *)rootInfo->PW,sizeof(rootInfo->PW),out);
Add_Name(name,NID_pkcs9_unstructuredAddress,(char *)rootInfo->ADD,sizeof(rootInfo->ADD),out);
/* Its self signed so set the issuer name to be the same as the
* subject.
*/
X509_set_issuer_name
openssl主要流程程序代码
最新推荐文章于 2024-07-12 08:46:23 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)