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

📄 evp.cpp

📁 MiniCA V2.0版本源码。《小型CA系统V2.1含源码》发表以来
💻 CPP
📖 第 1 页 / 共 5 页
字号:

	else//内存区域
	{
		for(UINT i=0;;i++)
		{
			//每次BUFLEN
			len=(inlen>BUFLEN)?BUFLEN:inlen;
			inlen-=len;
			if(!EVP_VerifyUpdate(&md_ctx, (infoin+i*BUFLEN), len))
			{
				strcpy(outMsg,"中间过程错误");
				ret=FALSE;
				goto err;
			}
			if(inlen <= 0) break;          
		}		
	}

	sig_len =EVP_PKEY_size(pcert);//这里应该改动
	sig_buf=new unsigned char[sig_len];
	if(bType==0)//文件
	{		
		fread(sig_buf,sizeof(char),sig_len,outfd);
	}
	else
	{
		memcpy(sig_buf,sign,sig_len);
	}
	if(!EVP_VerifyFinal (&md_ctx, sig_buf, sig_len, pcert))
	{
		strcpy(outMsg,"最终过程出错");
		ret=FALSE;
	}
err:
	if(infd!=NULL)
		fclose(infd);
	if(outfd!=NULL)
		fclose(outfd);
	if(pcert) EVP_PKEY_free (pcert);
	if(x509) X509_free(x509);
	if(md_ctx.digest) EVP_MD_CTX_cleanup(&md_ctx);
	delete [] sig_buf;
	EVP_cleanup();
	return ret;
}


/*数字信封 - 多证书 */
//文件结构
//			加密后重要信息长度	DWORD
//			加密后重要信息长度 CRC校验码	UINT
//			加密后重要信息
//			-------------------------------重要信息开始--------------------------------
//			公钥个数n
//			n个
//				公钥加密的对称密钥长度
//				公钥加密的对称密钥内容
//			向量IV
//			-------------------------------重要信息结束--------------------------------
//			加密文件内容

BOOL CEvp::Seal(stuCertLink * pCERT/*[in]合法用户公钥链*/,
		  char * cpname/*算法名称*/,
		  char * filein/*输入文件*/, 
		  char * fileout/*输出文件*/,
		  char * outMsg)//写信
{
	//对随机数播种(seeded)。
	UCHAR iv[EVP_MAX_IV_LENGTH]="";
	UCHAR * ekey [128]; 
	EVP_PKEY * pubKey[128];
	int ekeylen[128];
	UCHAR buf[BUFLEN]="";
	UCHAR ebuf[BUFLEN + EVP_MAX_BLOCK_LENGTH]="";
	int readlen=0;
	int ebuflen = 0;
	EVP_CIPHER_CTX eCtx;
	memset(&eCtx,0,sizeof(eCtx));
	int index = 0;

	const EVP_CIPHER *cipher=NULL;
	BOOL ret=true;
	FILE *outfd,*infd;
 	DWORD fileLen=0;//文件长度
	DWORD finishLen=0;//完成长度
	UINT uCrc16 = 0; //加密后重要信息CRC码
	DWORD dOutLen = 0;//内存文件长度
	BYTE * pOut = NULL; //内存文件缓冲区
	DWORD dFileInfoLen = 0;

	if(strlen(filein)==0||strlen(fileout)==0)
	{
		strcpy(outMsg,"NO specify input or output file");
		return false;
	}

	if ((infd = fopen (filein, "rb")) == NULL)//原文
	{
		strcpy(outMsg,"open input file error");
		return false;
	}
	if ((outfd = fopen (fileout, "wb")) == NULL)//密文
	{
		strcpy(outMsg,"open output file error");
		fclose(infd);
		return false;
	}

	//加载加密公钥
	HRSRC hRsrc = FindResource(NULL,MAKEINTRESOURCE(IDR_FILE_CERT),"CERT");
	DWORD lenCert = SizeofResource(NULL, hRsrc); 
	HGLOBAL hgCert = LoadResource(NULL,hRsrc);
	LPSTR lpCert = (LPSTR)LockResource(hgCert);	


	CMemFile MemFile;				//用于存放重要信息的内存文件

	DWORD dInLen = 0;
	BYTE * pIn = NULL;				//用于MemFile.Dectch();


	fileLen = filelength(fileno(infd));//得到文件长度

	OpenSSL_add_all_algorithms();

	int nCountCert = 0;	//证书个数

	for(stuCertLink * temp = pCERT; temp != NULL; temp=temp->Link, nCountCert++)
	{
		X509 * pX509 = NULL;
		pX509 = CCertKey::LoadCert(temp->pCert, temp->CertLen, NULL, outMsg);
	    if(pX509)
		{
			pubKey[nCountCert] = X509_get_pubkey(pX509);
			if (pubKey[nCountCert] == NULL)
			{
				sprintf(outMsg,"Read Public Key Failed!");
				ret=false;
				goto err;
			}
			ekey[nCountCert] = new unsigned char[EVP_PKEY_size(pubKey[nCountCert])];
			X509_free(pX509);
		}
		else
		{
			sprintf(outMsg,"加载第%d个证书失败",nCountCert);
			ret = false;
			goto err;
		}
	}
	
	cipher = EVP_get_cipherbyname(cpname);
	if(cipher==NULL)
	{
		sprintf(outMsg,"Unknown cipher name %s\n",cpname);
		ret=false;
		goto err;
	}

	if(!EVP_SealInit(&eCtx,cipher,
		ekey,
		ekeylen,//存放所有 ek 長度
		iv,//自动生成
		pubKey,//加密 ek 用的 public key(s)
		nCountCert))
	{
		ret=false;
		goto err;
	}

	MemFile.Write(&nCountCert, sizeof(int));	//1 - 写入公钥个数

	//fwrite((char*)&nCountCert,sizeof(char), sizeof(int),outfd);//写入公钥个数
	for(index = 0; index < nCountCert; index++)
	{
		MemFile.Write(&ekeylen[index], sizeof(int));
	//	fwrite(&ekeylen[index],sizeof(char), sizeof(int),outfd);//写入n个经公钥加密的对称密钥长度
		MemFile.Write(ekey[index], ekeylen[index]);
	//	fwrite(ekey[index],sizeof(char) ,ekeylen[index],outfd);//写入n个经公钥加密的对称密钥
	}

	MemFile.Write(iv, sizeof(iv));
//	fwrite(iv,sizeof(char),sizeof(iv),outfd);//写入向量


	//构造加密结果 长度+1 内存
	dFileInfoLen = CEvp::GetEncLen(lpCert, lenCert, MemFile.GetLength());

	dOutLen = dFileInfoLen + 1;
	pOut = new BYTE[dOutLen];

	dInLen = MemFile.GetLength();
	pIn = MemFile.Detach();

	//加密重要信息
	if(!CEvp::RSAPubEnc((BYTE *)lpCert, lenCert, "", pIn, 
		dInLen, pOut, dOutLen, outMsg))
	{
		//加密失败
		ret=false;
		goto err;
	}

	//得到加密后长度的CRC校验
	if(!CRC::GetCrc16((char*)&dOutLen, sizeof(DWORD), uCrc16))
	{
		//加密失败
		ret=false;
		goto err;
	}

	//写入加密后重要信息长度和CRC校验和加密后重要信息内容
	fwrite(&dOutLen,sizeof(char),sizeof(DWORD),outfd);

	fwrite(&uCrc16,sizeof(char),sizeof(UINT),outfd);

	fwrite(pOut,sizeof(char),dOutLen,outfd);



	for(;;)
	{
		readlen = fread(buf, sizeof(char),sizeof(buf),infd);
		
		if (readlen <= 0)
		{
			break;
		}
		
		if(!EVP_SealUpdate(&eCtx, ebuf, &ebuflen, buf, readlen))
		{
			strcpy(outMsg,"中间过程出错");
			ret=false;
			goto err;
		}
		fwrite(ebuf,sizeof(char),ebuflen,outfd);
		finishLen += readlen;
		DrawProg(finishLen*HUNDRED/fileLen);//前半程

	}
	
	if(!EVP_SealFinal(&eCtx, ebuf, &ebuflen))
	{
		strcpy(outMsg,"最终过程出错");
		ret=false;
		goto err;
	}
	
	fwrite(ebuf, sizeof(char), ebuflen,outfd);

err:
	fclose(infd);
	fclose(outfd);
	
	free(pIn);

	delete [] pOut;
	
	for(int i = 0;i< nCountCert;i++)
	{
		if(pubKey[i]) EVP_PKEY_free(pubKey[i]);
		if(ekey[i]) delete [] ekey[i];
	}
	if(eCtx.cipher) EVP_CIPHER_CTX_cleanup(&eCtx);
	EVP_cleanup();
	return ret;
}

/*拆封数字信封*/
BOOL CEvp::OpenSeal(char * key/*私钥*/, int keylen, char * pwd/*私钥密码*/, 
			   char * cpname/*算法名称*/, char * filein/*输入文件*/, 
			   char * fileout/*输出文件*/,char * outMsg)
{
	unsigned char buf[BUFLEN]="";
	unsigned char ebuf[BUFLEN + EVP_MAX_BLOCK_LENGTH]="";
	unsigned char iv[EVP_MAX_IV_LENGTH]="";
	const EVP_CIPHER *cipher=NULL;
	int ebuflen=0,readlen=0;
	bool ret=true;
	FILE *outfd,*infd;
	DWORD fileLen=0;//文件长度
	DWORD finishLen=0;//完成长度
	int nCountCert = 0;	//公钥个数
	int index = 0;
	UCHAR * ekey [128] = {0}; 
	int ekeylen[128];
	BOOL bInit = FALSE;//是否初始化成功
	DWORD dFileInfoLen = 0;//加密后重要信息长度
	UINT uCrc16 = 0; //加密后重要信息CRC码


	EVP_CIPHER_CTX eCtx;
	memset(&eCtx,0,sizeof(eCtx));
	EVP_PKEY * pkey=NULL;

	if(strlen(filein)==0||strlen(fileout)==0)
	{
		strcpy(outMsg,"NO specify input or output file");
		return false;
	}
	
    if ((infd = fopen (filein, "rb")) == NULL)//原文
	{
		strcpy(outMsg,"open input file error");
		return false;
	}
	if ((outfd = fopen (fileout, "wb")) == NULL)//密文
	{
		strcpy(outMsg,"open output file error");
		fclose(infd);
		return false;
	}
	fileLen = filelength(fileno(infd));//得到文件长度

	OpenSSL_add_all_algorithms();//digests   and ciphers
	/* Read private key */
	pkey = CCertKey::LoadKey(key,keylen,pwd,outMsg);
	if (pkey == NULL)
	{ 
		fclose(infd);
		fclose(outfd);
		return FALSE;
	}

	//得到重要信息长度和CRC校验码
	readlen = fread(&dFileInfoLen, sizeof(char),sizeof(DWORD),infd);
	finishLen += readlen;

	readlen = fread(&uCrc16, sizeof(char),sizeof(UINT),infd);
	finishLen += readlen;

	if(!CRC::CheckCrc((char *)&dFileInfoLen, sizeof(DWORD), uCrc16))
	{
		strcpy(outMsg ,"文件头CRC校验错误");
		return FALSE;
	}

	//开辟缓冲区,容纳加密后的重要文件信息
	BYTE * pIn = NULL;
	pIn = new BYTE[dFileInfoLen + 1];
	readlen = fread(pIn, sizeof(char), dFileInfoLen, infd);
	finishLen += readlen;

	HRSRC hRsrc = FindResource(NULL,MAKEINTRESOURCE(IDR_FILE_KEY),"CERT");
	DWORD lenKey = SizeofResource(NULL, hRsrc); 
	HGLOBAL hgKey = LoadResource(NULL,hRsrc);
	LPSTR lpKey = (LPSTR)LockResource(hgKey);

	DWORD dOutLen = dFileInfoLen;

	//开辟缓冲区,容纳加密后的信息体
	BYTE * pOut = NULL;
	pOut = new BYTE[dOutLen];
	if(!CEvp::RSAPrivDec((BYTE *)lpKey, lenKey, pwd, pIn, 
		dFileInfoLen, pOut, dOutLen, outMsg))
	{
		//解密失败
		strcpy(outMsg ,"重要信息解密失败");
		fclose(infd);
		fclose(outfd);
		delete [] pIn;
		delete [] pOut;
		return FALSE;
	}

	CMemFile MemFile;
	MemFile.Attach(pOut, dOutLen);

	//首先是公钥个数
	MemFile.Read(&nCountCert, sizeof(int));

	for(index = 0; index < nCountCert; index++)
	{
		MemFile.Read(&ekeylen[index], sizeof(int));
		ekey[index] = new unsigned char[ekeylen[index]];
		MemFile.Read(ekey[index], ekeylen[index]);
	}

	MemFile.Read(iv, sizeof(iv));

	MemFile.Close();

	//输入文件已经偏移到加密后的文件
	
	cipher = EVP_get_cipherbyname(cpname);

	if(cipher == NULL)
	{
		sprintf(outMsg,"Unknown cipher name %s\n",cpname);
		ret = false;
		goto err;
	}

	for(index = 0; index<nCountCert; index++)
	{
		if (ekeylen[index] != EVP_PKEY_size(pkey))
		{
			continue;
		}

		if(EVP_OpenInit(&eCtx,cipher, ekey[index],ekeylen[index],iv,pkey))
		{
			bInit = TRUE;
			break;
		}
	}
	if(!bInit)
	{
		sprintf(outMsg,"指定证书不能解密此文件");
		ret=false;
		goto err;
	}
	for(;;)
	{
		readlen = fread(buf, sizeof(char),sizeof(buf),infd);
		if (readlen <= 0)
		{
			break;
		}
		
		if(!EVP_OpenUpdate(&eCtx, ebuf, &ebuflen, buf, readlen))
		{
			sprintf(outMsg,"中间过程错误");
			ret=false;
			goto err;
		}
		fwrite(ebuf,sizeof(char),ebuflen,outfd);
		finishLen += readlen;
		DrawProg(finishLen*HUNDRED/fileLen);
	}

	if(!EVP_OpenFinal(&eCtx, ebuf, &ebuflen))
	{
		sprintf(outMsg,"最终过程错误");
		ret=false;
		goto err;
	}

	fwrite(ebuf, sizeof(char), ebuflen,outfd);
err:
	fclose(infd);
	fclose(outfd);
	
	delete [] pIn;
	delete [] pOut;

	for(int i = 0;i< index;i++)
	{
		if(ekey[i]) delete ekey[i];
	}
	if(pkey) EVP_PKEY_free(pkey);
	if((&eCtx)->cipher) EVP_CIPHER_CTX_cleanup(&eCtx);

	EVP_cleanup();

	return ret;
}

//公钥加密
BOOL CEvp::RSAPubEnc(const BYTE * pCertBuf/*[in]公钥*/,const UINT nCertLen/*[in]公钥长度*/,
			const char * pPwd/*[in]公钥密码,只针对PFX包文件*/,const BYTE * pInStream/*[in]输入文件或内存*/,
			DWORD nInlen/*[in]数据长度,为0表示pInStream为文件名*/,BYTE * pOutStream/*[out]加密后的数据*/,
			DWORD & nOutlen/*[in,out]in为0时候表示pOutStream为文件名,out加密后数据长度*/,
			char * OperMsg/*[out]返回操作错误信息*/)
{
	UINT iblock_size = 0, //输入块长度
		oblock_size = 0; //输出块长度
	unsigned char * bufin=NULL,
				  * bufout=NULL;
	int inlen = 0,
		outlen = 0;
	BOOL ret = TRUE;
	long fileLen = 0;//文件长度
	long finishLen = 0;//完成长度
	X509 * x509 = NULL;
	EVP_PKEY * pcert = NULL;
	RSA * rsa = NULL;
	int memtemplen = 0; //输出内存偏移
	UINT len = 0; //输入内存剩余长度

	int uMaxMem = nOutlen;	//可能为负数,不能用UINT


	BOOL bOutType = FALSE;//输出文件类型,内存-FALSE,文件-TRUE;

	if(nOutlen == 0) 
	{
		//检测文件名是否能够打开,以防pOutStream为文件
		bOutType = TRUE;
	}

	FILE * outfd = NULL,
		* infd = NULL;

	if(nInlen == 0)//输入为文件
	{
		if(pInStream == NULL || strlen((char*)pInStream)==0)
		{
			strcpy(OperMsg,"未指定输入文件");
			return FALSE;
		}
		
		if ((infd = fopen ((char *)pInStream, "rb")) == NULL)//原文
		{
			sprintf(OperMsg,"打开文件%s失败",pInStream);
			return FALSE;
		}
		fileLen = filelength(fileno(infd));//得到文件长度
	}
	else
		fileLen = nInlen;

	if(nOutlen == 0)//输出为文件
	{
		if(pOutStream == NULL || strlen((char*)pOutStream)==0)
		{
			strcpy(OperMsg,"未指定输出文件");
			return FALSE;
		}
		
		if ((outfd = fopen ((char *)pOutStream, "wb")) == NULL)//原文
		{
			sprintf(OperMsg,"打开文件%s失败",pOutStream);
			return FALSE;
		}
	}

	x509 = CCertKey::LoadCert((char *)pCertBuf,nCertLen,(char *)pPwd,OperMsg);
	if (x509 == NULL)
	{
		ret = FALSE;

⌨️ 快捷键说明

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