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

📄 evp.cpp

📁 MiniCA V2.0版本源码。《小型CA系统V2.1含源码》发表以来
💻 CPP
📖 第 1 页 / 共 5 页
字号:
				outStr.Format("摘要校验错误");
				ret=FALSE;
			}
			delete [] pmdbuf;
		}
	}

	return ret;
}

BOOL CEvp::InitSeal2(stuCertLink * pCERT, const CString strCpName,
			  CFile & File, EVP_CIPHER_CTX & eCtx, CString & outStr)
{
	//对随机数播种(seeded)。
	UCHAR iv[EVP_MAX_IV_LENGTH]="";
	UCHAR * ekey [128]; 
	EVP_PKEY * pubKey[128];
	int ekeylen[128];
	int index = 0;

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

	//加载加密公钥
	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, outStr.GetBuffer(255));
		outStr.ReleaseBuffer();
	    if(pX509)
		{
			pubKey[nCountCert] = X509_get_pubkey(pX509);
			if (pubKey[nCountCert] == NULL)
			{
				outStr = "Read Public Key Failed!";
				ret=false;
				goto err;
			}
			ekey[nCountCert] = new unsigned char[EVP_PKEY_size(pubKey[nCountCert])];
			X509_free(pX509);
		}
		else
		{
			outStr.Format("加载第 %d 个证书 %s 失败", nCountCert+1, temp->pCert);
			ret = false;
			goto err;
		}
	}
	
	cipher = EVP_get_cipherbyname(strCpName);
	if(cipher==NULL)
	{
		outStr.Format("Unknown cipher name %s\n",strCpName);
		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 - 写入公钥个数

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

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

	//构造加密结果 长度+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, outStr.GetBuffer(255)))
	{
		//加密失败
		ret=false;
		goto err;
	}

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

	//写入加密后重要信息长度和CRC校验和加密后重要信息内容
	File.Write(&dOutLen, sizeof(DWORD));
	File.Write(&uCrc16, sizeof(UINT));
	File.Write(pOut, dOutLen);

err:
	outStr.ReleaseBuffer();

	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;
}

void CEvp::CleanSeal2(EVP_CIPHER_CTX & sealCtx)
{
	if(sealCtx.cipher) 
		EVP_CIPHER_CTX_cleanup(&sealCtx); //清除所有信息释放内存
	EVP_cleanup();
	CRYPTO_cleanup_all_ex_data();
}


DWORD CEvp::Seal2(EVP_CIPHER_CTX * pCtx,const CString strFileName, CFile & File, CString & outStr)
{
	int readlen = 0;
	int ebuflen = 0;
	UCHAR buf[BUFLEN]="";
	UCHAR ebuf[BUFLEN + EVP_MAX_BLOCK_LENGTH]="";
	BOOL ret = TRUE;
	DWORD finishLen = 0;
	CFile inSideFile;//内部文件
	DWORD dProgLen = 0; //总共需要加密的长度
	DWORD dProgFinshLen = 0;//已经加密的长度

	if(!inSideFile.Open(strFileName, CFile::modeRead | CFile::typeBinary))
	{
		outStr = "不能打开指定文件";
		return -1;
	}

	dProgLen = inSideFile.GetLength();

	for(;;)
	{
		readlen = inSideFile.Read(buf, sizeof(buf));
		
		if (readlen <= 0)
		{
			break;
		}
		
		if(!EVP_SealUpdate(pCtx, ebuf, &ebuflen, buf, readlen))
		{
			outStr = "中间过程出错";
			ret=false;
			goto err;
		}
		File.Write(ebuf, ebuflen);
		finishLen += ebuflen;

		dProgFinshLen += readlen;
		DrawProg(dProgFinshLen*HUNDRED/dProgLen);
	}
	
	if(!EVP_SealFinal(pCtx, ebuf, &ebuflen))
	{
		outStr = "最终过程出错";
		ret = false;
		goto err;
	}
	File.Write(ebuf, ebuflen);
	finishLen += ebuflen;

err:
	inSideFile.Close();
	if(ret)
		return finishLen;
	else
		return ret;
}

BOOL CEvp::InitOpenSeal2(char * key, int keylen, char * pwd, const CString strCpName,
			  CFile & File, EVP_CIPHER_CTX & eCtx, CString & outStr)
{
	if(File.m_hFile == CFile::hFileNull)
		return FALSE;

	unsigned char iv[EVP_MAX_IV_LENGTH]="";
	const EVP_CIPHER *cipher=NULL;
	int ebuflen=0,readlen=0;
	bool ret=true;
	int nCountCert = 0;	//公钥个数
	int index = 0;
	UCHAR * ekey [128] = {0}; 
	int ekeylen[128];
	BOOL bInit = FALSE;//是否初始化成功
	DWORD dFileInfoLen = 0;//加密后重要信息长度
	UINT uCrc16 = 0; //加密后重要信息CRC码

	EVP_PKEY * pkey=NULL;
	CMemFile MemFile;
	HRSRC hRsrc = FindResource(NULL,MAKEINTRESOURCE(IDR_FILE_KEY),"CERT");
	DWORD lenKey = SizeofResource(NULL, hRsrc); 
	HGLOBAL hgKey = LoadResource(NULL,hRsrc);
	LPSTR lpKey = (LPSTR)LockResource(hgKey);
	BYTE * pIn = NULL;
	BYTE * pOut = NULL;
	DWORD dOutLen = 0;

	OpenSSL_add_all_algorithms();//digests   and ciphers
	/* Read private key */
	pkey = CCertKey::LoadKey(key,keylen,pwd,outStr.GetBuffer(255));
	outStr.ReleaseBuffer();
	if (pkey == NULL)
	{ 
		ret = false;
		goto err;
	}

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

	readlen = File.Read(&uCrc16, sizeof(UINT));
//	finishLen += readlen;

	if(!CRC::CheckCrc((char *)&dFileInfoLen, sizeof(DWORD), uCrc16))
	{
		outStr = "文件头CRC校验错误";
		ret = false;
		goto err;
	}

	//开辟缓冲区,容纳加密后的重要文件信息
	pIn = new BYTE[dFileInfoLen + 1];
	dOutLen = dFileInfoLen;

	readlen = File.Read(pIn, dFileInfoLen);
//	finishLen += readlen;



	//开辟缓冲区,容纳加密后的信息体
	pOut = new BYTE[dOutLen];
	if(!CEvp::RSAPrivDec((BYTE *)lpKey, lenKey, "", pIn, 
		dFileInfoLen, pOut, dOutLen, outStr.GetBuffer(255)))
	{
		//解密失败
		outStr.ReleaseBuffer();
		outStr = "重要信息解密失败";
		ret = false;
		goto err;
	}

	outStr.ReleaseBuffer();
	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(strCpName);

	if(cipher == NULL)
	{
		outStr.Format("Unknown cipher name %s\n",strCpName);
		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)
	{
		outStr = "指定证书不能解密文件,请确认证书合法性";
		ret=false;
		goto err;
	}
err:
	delete [] pIn;
	delete [] pOut;

	for(int i = 0;i< nCountCert;i++)
	{
		if(ekey[i]) delete ekey[i];
	}
	if(pkey) EVP_PKEY_free(pkey);

	EVP_cleanup();

	return ret;

}


DWORD CEvp::OpenSeal2(EVP_CIPHER_CTX & eCtx, CFile & File, DWORD dBolckLen, const CString strFileName, CString & outStr)
{
	unsigned char buf[BUFLEN]="";
	unsigned char ebuf[BUFLEN + EVP_MAX_BLOCK_LENGTH]="";
	int ebuflen = 0,
		readlen = 0,
		fileLen = 0,
		finishLen = 0;
	bool ret=true;

	DWORD dProgLen = dBolckLen; //总共需要处理的长度
	DWORD dProgFinshLen = 0;//已经处理的长度


	CFile inSideFile;//内部文件

	if(!inSideFile.Open(strFileName, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary))
	{
		outStr.Format("创建文件%s错误", strFileName);
		return -1;
	}
	for(;;)
	{
		//每次 iblock_size 或实际长度
		fileLen = (dBolckLen > BUFLEN) ? BUFLEN:dBolckLen;//内存区域长度
		readlen = File.Read(buf, fileLen);
		if(readlen == 0)//可能加密时文件长度为0
			break;

		if(!EVP_OpenUpdate(&eCtx, ebuf, &ebuflen, buf, readlen))
		{
			outStr = "中间过程错误";
			ret=false;
			goto err;
		}

		inSideFile.Write(ebuf, ebuflen);


		finishLen += ebuflen;
		dBolckLen -= fileLen;

		dProgFinshLen += readlen;
		DrawProg(dProgFinshLen*HUNDRED/dProgLen);

		if(dBolckLen <= 0) break;
	}

		//DrawProg(finishLen*HUNDRED/fileLen);
	if(!EVP_OpenFinal(&eCtx, ebuf, &ebuflen))
	{
		outStr = "最终过程错误";
		ret=false;
		goto err;
	}

	inSideFile.Write(ebuf, ebuflen);
	finishLen += ebuflen;

err:
	inSideFile.Close();
	if(ret)
		return finishLen;
	else
		return -1;
}

void CEvp::CleanOpenSeal2(EVP_CIPHER_CTX & eCtx)
{
	if(eCtx.cipher) 
		EVP_CIPHER_CTX_cleanup(&eCtx); //清除所有信息释放内存
	EVP_cleanup();
	CRYPTO_cleanup_all_ex_data();
}


BOOL CEvp::GetPubRsa(const BYTE * pCertBuf/*[in]公钥*/, const UINT nCertLen/*[in]公钥长度*/, RSA *& pRsa)
{
	X509 * x509 = NULL;
	EVP_PKEY * pcert = NULL;
	CString outStr;
	BOOL ret = TRUE;
	
	x509 = CCertKey::LoadCert((char *)pCertBuf, nCertLen, "", outStr.GetBuffer(255));
	outStr.ReleaseBuffer();
	if (x509 == NULL)
	{
		ret = FALSE;
		goto err;
	}

	pcert = X509_get_pubkey(x509);
	if(pcert==NULL)
	{
		outStr = "取得公钥密钥失败";
		ret = FALSE;
		goto err;
	}

    if (!(pRsa = EVP_PKEY_get1_RSA(pcert)))
	{
		outStr = "取得RSA密钥失败";
		ret=FALSE;
		goto err;
    }

err:
	if(pcert) EVP_PKEY_free(pcert);
    if(x509) X509_free(x509);
	return ret;
}

BOOL CEvp::GetPrivRsa(const BYTE * pKeyBuf/*[in]私钥*/,const UINT nKeyLen/*[in]私钥长度*/,
			const char * pPwd/*[in]私钥密码*/, RSA *& pRsa)
{
	EVP_PKEY * pkey = NULL;
	CString outStr;
	pkey = CCertKey::LoadKey((char *)pKeyBuf,nKeyLen,(char *)pPwd,outStr.GetBuffer(255));
	outStr.ReleaseBuffer();
	BOOL ret = TRUE;

	if (pkey == NULL)
	{ 
		outStr = "取得私钥密钥失败";
		ret=FALSE;
		goto err;
	}
	
    if (!(pRsa = EVP_PKEY_get1_RSA(pkey)))
	{
		outStr = "取得RSA密钥失败";
		ret=FALSE;
		goto err;
    }
err:
	if(pkey) EVP_PKEY_free(pkey);
	return ret;
}

void CEvp::FreeRsa(RSA *& pRsa)
{
	if(pRsa) RSA_free(pRsa);
	CRYPTO_cleanup_all_ex_data();
}


//公钥加密
DWORD CEvp::RSAPubEnc2(RSA * pRsa, const CString strFileName, CFile & File, CString & outStr)
{
	if(pRsa == NULL)
	{
		outStr = "RSA非法";
		return -1;
	}
	UINT iblock_size = 0, //输入块长度
		 oblock_size = 0; //输出块长度

	unsigned char * bufin=NULL,
				  * bufout=NULL;

	int inlen = 0,
		outlen = 0;

	DWORD dProgLen = 0; //总共需要处理的长度
	DWORD dProgFinshLen = 0;//已经处理的长度

	BOOL ret = TRUE;
	long fileLen = 0;//文件长度
	long finishLen = 0;//完成长度
	DWORD returnLen = 0;//最后返回文件加密后长度

	CFile inSideFile;//内部文件
	if(!inSideFile.O

⌨️ 快捷键说明

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