📄 evp.cpp
字号:
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 + -