⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ca.cpp

📁 小型CA的完整代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
BOOL MakeReq(stuSUBJECT * reqInfo,/*请求信息*/int bits/*位数*/,char * reqFile/*证书请求文件*/,
			 char * priFile/*私钥文件*/,char * outMsg/*操作结果*/,int type)
{
	X509_REQ *req=NULL;
	EVP_PKEY *pkey=NULL;
	BIO * breq=NULL,* bkey=NULL;
	int i=0,j=0;
	if(((breq=BIO_new_file(reqFile, "w"))== NULL)||((bkey=BIO_new_file(priFile, "w")) == NULL))
	{
		strcpy(outMsg,"Create File Error");
		return false;
	}
	if(!mkReq(reqInfo,&req,&pkey,bits,outMsg))
	{
		strcpy(outMsg,"Make CertReq Error");
		return false;
	}

	if(type==PEM)
	{
		i=PEM_write_bio_X509_REQ(breq,req);		
		j=PEM_write_bio_PrivateKey(bkey,pkey,NULL,NULL,0,NULL, NULL);
	}
	else if(type==DER)
	{
		i=i2d_X509_REQ_bio(breq,req);
		j=i2d_PrivateKey_bio(bkey,pkey);
	}
	BIO_free(breq);
	BIO_free(bkey);
	X509_REQ_free(req);
	EVP_PKEY_free(pkey);
	if(!i||!j)
	{
		strcpy(outMsg,"Save Cert or Key File Error");
		return false;
	}
	return true;
}
////////////////////////// end //////////////////////////////////////
////////////////////////////////////////////////////////////////////
/////////////////////////// begin ////////////////////////////////////////
int copy_extensions(X509 *x, X509_REQ *req, int copy_type)//在证书中加入req自带扩展信息
{
	STACK_OF(X509_EXTENSION) *exts = NULL;
	X509_EXTENSION *ext, *tmpext;
	ASN1_OBJECT *obj;
	int i, idx, ret = 0;
	if (!x || !req || (copy_type == EXT_COPY_NONE))
		return 1;
	exts = X509_REQ_get_extensions(req);
	
	for(i = 0; i < sk_X509_EXTENSION_num(exts); i++)
	{
		ext = sk_X509_EXTENSION_value(exts, i);
		obj = X509_EXTENSION_get_object(ext);
		idx = X509_get_ext_by_OBJ(x, obj, -1);
		/* Does extension exist? */
		if (idx != -1) 
		{
			/* If normal copy don't override existing extension */
			if (copy_type == EXT_COPY_ADD)
				continue;
			/* Delete all extensions of same type */
			do
			{
				tmpext = X509_get_ext(x, idx);
				X509_delete_ext(x, idx);
				X509_EXTENSION_free(tmpext);
				idx = X509_get_ext_by_OBJ(x, obj, -1);
			} while (idx != -1);
		}
		if (!X509_add_ext(x, ext, -1))
			goto end;
	}
	
	ret = 1;
	
end:
	
	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
	
	return ret;
}


int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,int serial,
			char *startdate, char *enddate, int days,X509_REQ * req,stuKEYUSAGE * KUSAGE,
			stuEKEYUSAGE * EKUSAGE,char * outMsg)
{
	X509_NAME *name=NULL,*CAname=NULL;
	X509 *ret=NULL;
	X509_CINF *ci;
	EVP_PKEY *pktmp;
	int ok= -1,i=0;
//	STACK_OF (X509_EXTENSION) * req_exts;//如何释放??
	char kusage[160]={0};
	char ekusage[360]={0};
	name=X509_REQ_get_subject_name(req);
	if ((ret=X509_new()) == NULL) 
	{
		ok=0;
		goto err;
	}
	ci=ret->cert_info;

	/* Make it an X509 v3 certificate. 版本1扩展*/
	if (!X509_set_version(ret,2L)) //版本
	{
		ok=0;
		goto err;
	}
	
	ASN1_INTEGER_set(X509_get_serialNumber(ret),serial);//序列号

	if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))//发行者
	{
		ok=0;
		goto err;
	}
	
	if (strcmp(startdate,"today") == 0)
		X509_gmtime_adj(X509_get_notBefore(ret),0);//开始日期
	else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
	
	if (enddate == NULL)
		X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);//结束日期
	else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
	
	if (!X509_set_subject_name(ret,name)) //主体 ---所有者
	{
		ok=0;
		goto err;
	}
	
	pktmp=X509_REQ_get_pubkey(req);
	i = X509_set_pubkey(ret,pktmp);//公钥
	EVP_PKEY_free(pktmp);
	if (!i) 
	{
		ok=0;
		goto err;
	}
	
	//加入req自带扩展信息,生成REQ文件时候加入的
	if (!copy_extensions(ret, req, EXT_COPY_ALL))
	{
		strcpy("加入自带扩展信息失败",outMsg);
		goto err;
	}

	/* Lets add the extensions, if there are any 加入标准扩展*/

	//基本限制Note if the CA option is false the pathlen option should be omitted. 
	Add_ExtCert(ret,ret,NID_basic_constraints, "critical,CA:FALSE,pathlen:1");

	//主题密钥标示符--------区分拥有者多对密钥
	Add_ExtCert(ret,ret,NID_subject_key_identifier, "hash");

	//Authority密钥标示符----区分发行者有多个签名密钥时
	Add_ExtCert(ret,x509, NID_authority_key_identifier, "keyid,issuer:always");
	

	//密钥用法 ----数字签名、不可否认性、密钥加密、数据加密、密钥协商、证书签名、
	//CRL签名、仅仅加密、仅仅解密
		
	if(KUSAGE->DS)
		strcpy(kusage,"digitalSignature");
	if(KUSAGE->NR)
		if(strlen(kusage))//添加
			strcat(kusage, ",nonRepudiation");
		else
			strcpy(kusage,"nonRepudiation");
	if(KUSAGE->KE)
		if(strlen(kusage))//添加
			strcat(kusage, ",keyEncipherment");
		else
			strcpy(kusage,"keyEncipherment");
	if(KUSAGE->DE)
		if(strlen(kusage))//添加
			strcat(kusage, ",dataEncipherment");
		else
			strcpy(kusage,"dataEncipherment");
	if(KUSAGE->KA)
		if(strlen(kusage))//添加
			strcat(kusage, ",keyAgreement");
		else
			strcpy(kusage,"keyAgreement");
	if(KUSAGE->KC)
		if(strlen(kusage))//添加
			strcat(kusage, ",keyCertSign");
		else
			strcpy(kusage,"keyCertSign");
	if(KUSAGE->CS)
		if(strlen(kusage))//添加
			strcat(kusage, ",cRLSign");
		else
			strcpy(kusage,"cRLSign");
	if(KUSAGE->EO)
		if(strlen(kusage))//添加
			strcat(kusage, ",encipherOnly");
		else
			strcpy(kusage,"encipherOnly");
	if(KUSAGE->DO)
		if(strlen(kusage))//添加
			strcat(kusage, ",decipherOnly");
		else
			strcpy(kusage,"decipherOnly");
	if(strlen(kusage))
		Add_ExtCert(ret,ret, NID_key_usage, kusage);

	//增强型密钥用法--一般只用于末端证书RFC3280
	//增强用法     证书目的
	//--------------------------------------------------------------------------------------------------------------
	//服务器验证   	     保证远程计算机的身份     
	//客户端验证		 向远程计算机证明您的身份 
	//代码签名			 确保软件来自软件发行商   
	//安全电子邮件		 保护软件在发行后不被改动 
	//时间戳			 保护电子邮件消息    
	//--------------------------------------------------------------------------------------------------------------
	//					保证软件来自一个软件发行商
	//					保护软件在发行后不被改动。
	//					保证软件来自商业软件发行商
	//					允许您用数字签名证书信任列表
	//					允许联机事务处理/通讯的严格加密
	//					允许加密磁盘上的数据
	//					智能卡登录
	//IP安全终端系统   	     允许 Internet 上的安全通讯     
	//IP安全隧道终止		 
	//IP 安全用户			
	//--------------------------------------------------------------------------------------------------------------

	if(EKUSAGE->SA)
		strcpy(ekusage,"serverAuth");
	if(EKUSAGE->CA)
		if(strlen(ekusage))//添加
			strcat(ekusage,",clientAuth");
		else
			strcpy(ekusage,"clientAuth");
	if(EKUSAGE->CS)
		if(strlen(ekusage))//添加
			strcat(ekusage,",codeSigning");
		else
			strcpy(ekusage,"codeSigning");
	if(EKUSAGE->EP)
		if(strlen(ekusage))//添加
			strcat(ekusage,",emailProtection");
		else
			strcpy(ekusage,"emailProtection");
	if(EKUSAGE->TS)
		if(strlen(ekusage))//添加
			strcat(ekusage,",timeStamping");
		else
			strcpy(ekusage,"timeStamping");
	if(EKUSAGE->msCC)
		if(strlen(ekusage))//添加
			strcat(ekusage,",msCodeCom");
		else
			strcpy(ekusage,"msCodeCom");
	if(EKUSAGE->msCTLS)
		if(strlen(ekusage))//添加
			strcat(ekusage,",msCTLSign");
		else
			strcpy(ekusage,"msCTLSign");
	if(EKUSAGE->msSGC)
		if(strlen(ekusage))//添加
			strcat(ekusage,",msSGC");
		else
			strcpy(ekusage,"msSGC");
	if(EKUSAGE->msEFS)
		if(strlen(ekusage))//添加
			strcat(ekusage,",msEFS");
		else
			strcpy(ekusage,"msEFS");
	if(EKUSAGE->msSC)
		if(strlen(ekusage))//添加
			strcat(ekusage,",msSmartcardLogin");
		else
			strcpy(ekusage,"msSmartcardLogin");
	if(EKUSAGE->IP)
		if(strlen(ekusage))//添加
			strcat(ekusage,",ipsecEndSystem,ipsecTunnel,ipsecUser");
		else
			strcpy(ekusage,"ipsecEndSystem,ipsecTunnel,ipsecUser");
	if(strlen(ekusage))
	Add_ExtCert(ret,ret,NID_ext_key_usage,ekusage);

	/*
	Application			keyUsage  Values 
	SSL Client			digitalSignature 
	SSL Server			keyEncipherment 
	S/MIME Signing		digitalSignature 
	S/MIME Encryption	keyEncipherment 
	Certificate			Signing keyCertSign 
	Object Signing		digitalSignature */

	//颁发者备用名称,URL:http://my.url.here/、不支持email  copy
	Add_ExtCert(ret,ret, NID_issuer_alt_name, "DNS:hpxs,email:hpxs@hotmail.com,RID:1.2.3.4,URI:https://hpxs,IP:192.168.0.22");

	//证书策略
	Add_ExtCert(ret,ret,NID_certificate_policies,"OK");
	//颁发机构信息访问
	Add_ExtCert(ret,ret,NID_info_access,"OCSP;URI:https://hpxs");//或者caIssuers;URI:http://my.ca/ca.html
	//CRL分发点
	Add_ExtCert(ret,x509, NID_crl_distribution_points, "URI:https://hpxs/hpxs.crl");

	/* Some Netscape specific extensions */
//	Add_ExtCert(ret,ret, NID_crl_number, "sslCA");

//	Add_ExtCert(ret,x509, NID_netscape_comment, "See http://cert.umd.edu/root for details.");
	/* In each case the 'value' of the extension is placed directly in the
	extension. Currently supported extensions in this category are: nsBaseUrl,
	nsRevocationUrl, nsCaRevocationUrl, nsRenewalUrl, nsCaPolicyUrl,
	nsSslServerName and nsComment	*/

//	Add_ExtCert(ret,x509, NID_netscape_cert_type, "client, server, email,objsign, reserved, sslCA,emailCA, objCA");
	/*nsCertType (netscape certificate type) takes the flags: client, server, email,
	objsign, reserved, sslCA, emailCA, objCA.*/
	/* Maybe even add our own extension based on existing */
	//加入自定义信息begin
	int nid;
	nid = OBJ_create("1.2.3.4.9", "Hpxs", "I love OpenSSL!");
	X509V3_EXT_add_alias(nid, NID_netscape_comment);
	Add_ExtCert(ret,ret, nid, "I love OpenSSL");
	//加入自定义信息end
	X509V3_EXT_cleanup();//cleanup the extension code if any custom extensions have been added

	if (!X509_sign(ret,pkey,dgst))//加入签名,签名算法
	{
		ok=0;
		goto err;
	}
	ok=1;
err:
	if (CAname != NULL)
		X509_NAME_free(CAname);
	if (ok <= 0)
	{
		if (ret != NULL) X509_free(ret);
		ret=NULL;
	}
	else
		*xret=ret;
	return(ok);
}

int certify(X509 **xret, X509_REQ *req, EVP_PKEY *pkey, X509 *x509,const EVP_MD *dgst,
				   int serial, char *startdate, char *enddate, int days,stuKEYUSAGE * KUSAGE,
				   stuEKEYUSAGE * EKUSAGE,char * outMsg)
{//返回公钥证书,请求文件,根私钥,根公钥,
	EVP_PKEY *pktmp=NULL;
	int ok= -1,i=0;	
	if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)//得到公钥
	{
		sprintf(outMsg,"error unpacking public key\n");
		ok=0;
		goto err;
	}
	i=X509_REQ_verify(req,pktmp);//证书请求里面有私要签名,这里验证一下,看此公钥主人是否持有私钥
	EVP_PKEY_free(pktmp);
	if (i < 0)
	{
		ok=0;
		sprintf(outMsg,"Signature verification problems....\n");
		goto err;
	}
	if (i == 0)
	{
		ok=0;
		sprintf(outMsg,"Signature did not match the certificate request\n");
		goto err;
	}
	
	ok=do_body(xret,pkey,x509,dgst,serial,startdate, enddate,
		days,req,KUSAGE,EKUSAGE,outMsg);
	
err:
	return(ok);
}


BOOL MakeCert(char *certfile/*根证书公钥*/,int certlen,/*为0则certfile为磁盘文件,否则为内存区域*/
			  char *keyfile/*根证书私钥*/,int keylen,int serial/*序列号*/,char *enddate/*作废日期*/,
			  int days/*有效期*/, char *reqfile/*请求文件*/,stuKEYUSAGE * KUSAGE/*密钥用法*/,
			  stuEKEYUSAGE * EKUSAGE/*增强密钥用法*/,char *outfile/*结果文件*/,
			  char * outMsg/*操作结果*/,int type/*结果类型DER,PEM*/)//通过证书请求,得到证书
{
	int ret=1;
	char * md=NULL;
	EVP_PKEY *pkey=NULL;
	X509 * x509=NULL;
	X509_REQ *req=NULL;
	X509 * x=NULL;
	BIO * bcert=NULL,* reqbio=NULL;
	int j;
	const EVP_MD *dgst=NULL;

	OpenSSL_add_all_digests();//加入签名算法

	if((reqbio=BIO_new_file(reqfile, "r")) == NULL)
	{
		ret=0;
		goto err;
	}
	
	if ((req=PEM_read_bio_X509_REQ(reqbio,NULL,NULL,NULL)) == NULL)//PEM_read_X509_REQ 
	{
		BIO_reset(reqbio);
		if ((req=d2i_X509_REQ_bio(reqbio,NULL)) == NULL)
		{
			sprintf(outMsg,"Error get certificate request");
			ret=0;
			goto err;
		}
	}

	pkey=LoadKey(keyfile,keylen,NULL,outMsg);
	if (pkey == NULL)
	{
		ret = 0;
		goto err;
	}

	x509=LoadCert(certfile,certlen,outMsg);
	if (x509 == NULL)
	{
		ret = 0;
		goto err;
	}
	
	if (!X509_check_private_key(x509,pkey))
	{
		sprintf(outMsg,"CA certificate and CA private key do not match\n");
		ret = 0;
		goto err;
	}
	md="sha1";//////////!!!!!!!!!!!!!!!!!////////////////////////////
	if ((dgst=EVP_get_digestbyname(md)) == NULL)//return an EVP_MD structure when passed a digest name
	{
		sprintf(outMsg,"%s is an unsupported message digest type\n",md);
		ret = 0;
		goto err;
	}
	j=certify(&x,req,pkey,x509,dgst,//公钥证书out,请求文件,根私钥,根公钥,
		serial,"today",enddate,days,KUSAGE,EKUSAGE,outMsg);
	if (j <= 0) 
	{
		ret=0;
		goto err;
	}

	if(((bcert=BIO_new_file(outfile, "w"))== NULL))
	{
		strcpy(outMsg,"Create File Error");
		goto err;
	}
	if (type==DER)
	{
		i2d_X509_bio(bcert,x);
	}
	else if(type==PEM)
	{
		PEM_write_bio_X509(bcert,x);
	}
err:
	if (reqbio != NULL) BIO_free(reqbio);
	BIO_free_all(bcert);
	EVP_PKEY_free(pkey);
	X509_free(x509);
	X509_free(x);
	if (req != NULL) X509_REQ_free(req);
	EVP_cleanup();//frees all three stacks and sets their pointers to NULL ---- EVP_CIPHER
	return ret;

}
///////////////////////// end ////////////////////////////////////////
BOOL DirectCert(char *certfile/*根证书公钥*/,int certlen,/*为0则certfile为磁盘文件,否则为内存区域*/
			 char *keyfile/*根证书私钥*/,int keylen,int serial/*序列号*/,char *enddate/*作废日期*/,
			 int days/*有效期*/,stuCERT * sCERT/*用户信息与密钥用法*/,int bits,char * cert/*输出证书公钥*/,int * certl/*长度*/,
			 char * key/*输出证书私钥*/,int * keyl/*长度*/,char * outMsg/*,int type结果类型DER,PEM*/)//直接生成公私钥
{
	X509_REQ * req=NULL;
	EVP_PKEY * pkey=NULL, * prkey=NULL;//证书私钥,//根私钥
	X509 * x509=NULL,* x=NULL;//根公钥,证书公钥
	BIO * memcert=NULL, * memkey=NULL;//输出证书公私钥
	BUF_MEM *bptrcert=NULL,*bptrkey=NULL;
	int ret=1;
	char * md=NULL;
	int i=0,j=0,ok=0;
	const EVP_MD *dgst=NULL;

	OpenSSL_add_all_digests();//加入签名算法
	memcert= BIO_new(BIO_s_mem());
	memkey= BIO_new(BIO_s_mem());
	BIO_set_close(memcert, BIO_CLOSE); /*  BIO_free() free BUF_MEM  */
	BIO_set_close(memkey, BIO_CLOSE); /*  BIO_free() free BUF_MEM  */

	prkey=LoadKey(keyfile,keylen,NULL,outMsg);//RAND_bytes
	if (prkey == NULL)
	{
		ret = 0;
		goto err;
	}

	x509=LoadCert(certfile,certlen,outMsg);
	if (x509 == NULL)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -