Evp.cpp
上传用户:dengkfang
上传日期:2008-12-30
资源大小:5233k
文件大小:70k
源码类别:

CA认证

开发平台:

Visual C++

  1. // Evp.cpp: implementation of the CEvp class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "minica.h"
  6. #include "Evp.h"
  7. #include <io.h>
  8. #include "CertKey.h"
  9. #include "rc.h"
  10. #ifdef _DEBUG
  11. #undef THIS_FILE
  12. static char THIS_FILE[]=__FILE__;
  13. #define new DEBUG_NEW
  14. #endif
  15. //////////////////////////////////////////////////////////////////////
  16. // Construction/Destruction
  17. //////////////////////////////////////////////////////////////////////
  18. CProgressCtrlST *  CEvp::m_pProgress = NULL;
  19. const UINT BUFLEN = 1024;
  20. const float HUNDRED = 100.0;
  21. CEvp::CEvp()
  22. {
  23. }
  24. CEvp::~CEvp()
  25. {
  26. }
  27. //函数功能:对称加解密
  28. //参数: [in] cpName - 算法名称
  29. // [in] inStream - 输入文件或内存区域
  30. // [in] inLen - 输入长度,0->标示输入为文件
  31. // [in] outStream - 输出为文件名或内存区域
  32. // [in,out] outLen - 输入为结果内存长度,输出为实际加密结果长度
  33. // [in] char * pwd - 用于初始iv的密码
  34. // [in] type - 1-加密、0-解密
  35. // [out] outMsg - 输出信息
  36. BOOL CEvp::Crypt(const char * cpName, const char * inStream, UINT inLen, 
  37.    char * outStream, UINT & outLen, char * pwd, const int type,
  38.    char * outMsg)
  39. {
  40. unsigned char inbuf[BUFLEN]="";
  41. unsigned char outbuf[BUFLEN + EVP_MAX_BLOCK_LENGTH]="";//所有算法最长的块长度。
  42. unsigned char key[EVP_MAX_KEY_LENGTH]="";//算法最长的KEY长度
  43.     unsigned char iv[EVP_MAX_IV_LENGTH]="";//算法最长的IV长度
  44. int infilelen=0, outlen=0;
  45. BOOL ret=true;
  46. const EVP_CIPHER *cipher=NULL;
  47. EVP_CIPHER_CTX ctx;
  48. memset(&ctx,0,sizeof(ctx));
  49. long fileLen=0;//文件长度
  50. long finishLen=0;//完成长度
  51. int uMaxMem = outLen; //可能为负数,不能用UINT
  52. outLen = 0;
  53. UINT len = 0;
  54. FILE * outfd=NULL,* infd=NULL;
  55. if(inLen==0&&(strlen(inStream)==0||strlen(outStream)==0))
  56. {
  57. strcpy(outMsg,"NO specify input or output file");
  58. return FALSE;
  59. }
  60. if(inLen==0)//文件
  61. {
  62. if ((infd = fopen (inStream, "rb")) == NULL)//原文
  63. {
  64. strcpy(outMsg,"open input file error");
  65. return FALSE;
  66. }
  67. fileLen = filelength(fileno(infd));//得到文件长度
  68. if ((outfd = fopen (outStream, "wb")) == NULL)//密文
  69. {
  70. strcpy(outMsg,"open output file error");
  71. fclose(infd);
  72. return FALSE;
  73. }
  74. }
  75. OpenSSL_add_all_algorithms();//add digests   and ciphers
  76. cipher=EVP_get_cipherbyname(cpName);
  77. if(cipher==NULL)
  78. {
  79. sprintf(outMsg,"Unknown cipher name %sn",cpName);
  80. ret=FALSE;
  81. goto err;
  82. }
  83. //表示產生的 key 是給哪一種 cipher 用的
  84. //過程中所使用的 hash 演算法,
  85. //用來加密的 salt,至少為八個 bytes,否則必須NULL,
  86. //重覆幾次 hashing 的動作,愈多次愈花時間,但相對地也愈安全
  87. if(!EVP_BytesToKey(cipher,EVP_md5(),NULL,(unsigned char *)pwd,
  88. strlen(pwd),1,key,iv))
  89. {
  90. strcpy(outMsg,"Crypt初始化key or iv 失败");
  91. ret=FALSE;
  92. goto err;
  93. }
  94. EVP_CIPHER_CTX_init(&ctx);//初始化一个EVP_CIPHER_CTX结构体
  95. //type为1,则加密;如果type为0,则解密;如果type是-1,则不改变数据
  96. if(!EVP_CipherInit_ex(&ctx, cipher, NULL/*NULL使用缺省的实现算法*/,key,iv,type))//初始化
  97. {
  98. strcpy(outMsg,"Crypt初始化加解密结构体失败");
  99. ret=FALSE;
  100. goto err;
  101. }
  102. //该函数进行加密算法结构EVP_CIPHER_CTX密钥长度的设置。
  103. //如果算法是一个密钥长度固定的算法,
  104. //那么如果设置的密钥长度跟它固定的长度不一致,就会产生错误。
  105. // EVP_CIPHER_CTX_set_key_length(&ctx, 10); 
  106. // EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, type);
  107. if(inLen==0)//文件
  108. {
  109. for(;;)
  110. {                       
  111. infilelen = fread(inbuf, sizeof(char), BUFLEN, infd);
  112. if(infilelen <= 0) break;
  113. if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, infilelen))//中間過程 
  114. {
  115. strcpy(outMsg,"Crypt中间过程错误");
  116. ret=FALSE;
  117. goto err;
  118. }
  119. fwrite(outbuf, sizeof(char), outlen, outfd);
  120. finishLen+=infilelen;
  121. DrawProg(finishLen*HUNDRED/fileLen);
  122. }               
  123. if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen))    //最終步驟-处理最后(Final)的一段数据
  124. {                       
  125. strcpy(outMsg,"Crypt最终过程错误"); 
  126. ret=FALSE;
  127. goto err;
  128. }               
  129. fwrite(outbuf, sizeof(char), outlen, outfd);
  130. }
  131. else//内存
  132. {
  133. fileLen = inLen;
  134. for(UINT i=0;;i++)
  135. {
  136. //每次1024
  137. len=(inLen>BUFLEN)?BUFLEN:inLen;
  138. inLen-=len;
  139. if(!EVP_CipherUpdate(&ctx, outbuf, &outlen,(UCHAR *)(inStream+i*BUFLEN), len))//中間過程
  140. {
  141. strcpy(outMsg,"Crypt中间过程错误");
  142. ret=FALSE;
  143. goto err;
  144. }
  145. //计算缓冲区长度是否能容纳结果数据集
  146. uMaxMem -= outlen;
  147. if(uMaxMem < 0)
  148. {
  149. strcpy(outMsg,"输出缓冲过小,不能容纳操作结果"); 
  150. ret = FALSE;
  151. goto err;
  152. }
  153. memcpy(outStream + outLen, outbuf, outlen);//拷贝到调用函数
  154. outLen+=outlen;
  155. if(inLen <= 0) break;          
  156. }
  157. if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen)) //最終步驟-处理最后(Final)的一段数据
  158. {   
  159. strcpy(outMsg,"Crypt最终过程错误"); 
  160. ret=FALSE;
  161. goto err;
  162. }               
  163. uMaxMem -= outlen;
  164. if(uMaxMem < 0)
  165. {
  166. strcpy(outMsg,"输出缓冲过小,不能容纳操作结果"); 
  167. ret = FALSE;
  168. goto err;
  169. }
  170. memcpy(outStream + outLen,outbuf,outlen);//拷贝到调用函数
  171. outLen += outlen;
  172. }
  173. err:
  174. if(infd!=NULL)
  175. fclose(infd);
  176. if(outfd!=NULL)
  177. fclose(outfd);
  178. if(ctx.cipher) EVP_CIPHER_CTX_cleanup(&ctx); //清除所有信息释放内存
  179. EVP_cleanup();//frees all three stacks and sets their pointers to NULL ---- EVP_CIPHER
  180. return ret;
  181. }
  182. /*消息摘要*/ 
  183. BOOL CEvp::Digest(const char * mdname/*摘要算法*/,const char * infoin/*输入,文件或内存*/,
  184. UINT inlen/*文件时候为0,内存为长度*/,unsigned char * md_value/*返回摘要*/,
  185. unsigned int * md_len/*摘要长度*/, char * outMsg)
  186. {
  187. const EVP_MD *md=NULL;
  188. char inbuf[BUFLEN]="";
  189. UINT len=0;
  190. BOOL ret=true;
  191. EVP_MD_CTX md_ctx;
  192. memset(&md_ctx,0,sizeof(md_ctx));
  193. FILE * infd=NULL;
  194. long fileLen=0;//文件长度
  195. long finishLen=0;//完成长度
  196. if(strlen(infoin)==0)
  197. {
  198. strcpy(outMsg,"NO specify input");
  199. return FALSE;
  200. }
  201. if(inlen==0)//输入为文件
  202. {
  203. if ((infd = fopen (infoin, "rb")) == NULL)//原文
  204. {
  205. strcpy(outMsg,"open input file error");
  206. return FALSE;
  207. }
  208. fileLen=filelength(fileno(infd));//得到文件长度
  209. }
  210. //使EVP_Digest系列函数支持所有有效的信息摘要算法
  211. OpenSSL_add_all_digests();
  212.     
  213. //根据输入的信息摘要函数的名字得到相应的EVP_MD算法结构
  214. md = EVP_get_digestbyname(mdname);  
  215. if(!md) 
  216. {
  217. sprintf(outMsg,"Unknown message digest %s",mdname);
  218. ret=FALSE;
  219. goto err;
  220. }
  221. //初始化信息摘要结构md_ctx。
  222. EVP_MD_CTX_init(&md_ctx);
  223. //使用md的算法结构设置mdctx结构,impl为NULL,即使用缺省实现的算法(openssl本身提供的信息摘要算法)
  224. if(!EVP_DigestInit_ex(&md_ctx, md, NULL/*impl*/))
  225. {
  226. strcpy(outMsg,"Digest初始化算法结构错误");
  227. ret=FALSE;
  228. goto err;
  229. }
  230. //信息摘要运算
  231. if(inlen==0)//输入为文件
  232. {
  233. for(;;)
  234. {
  235. len = fread(inbuf, 1, BUFLEN, infd);
  236. if(len <= 0) break;          
  237. if(!EVP_DigestUpdate(&md_ctx, inbuf, len))
  238. {
  239. strcpy(outMsg,"Digest中间过程错误");
  240. ret=FALSE;
  241. goto err;
  242. }
  243. finishLen+=len;
  244. DrawProg(finishLen * HUNDRED / fileLen);
  245. }
  246. }
  247. else//内存区域
  248. {
  249. for(UINT i=0;;i++)
  250. {
  251. //每次BUFLEN
  252. len=(inlen>BUFLEN)?BUFLEN:inlen;
  253. inlen-=len;
  254. if(!EVP_DigestUpdate(&md_ctx, (infoin+i*BUFLEN), len))
  255. {
  256. strcpy(outMsg,"Digest中间过程错误");
  257. ret=FALSE;
  258. goto err;
  259. }
  260. if(inlen <= 0) break;          
  261. }
  262. }
  263. //完成信息摘要计算过程,将完成的摘要信息存储在md_value里面,长度信息存储在md_len里面
  264. if(!EVP_DigestFinal_ex(&md_ctx, md_value, md_len))
  265. {
  266. strcpy(outMsg,"Digest最终过程错误");
  267. ret=FALSE;
  268. }
  269. err:
  270. //使用该函数释放mdctx占用的资源,如果使用_ex系列函数,这是必须调用的。
  271. if(infd!=NULL)
  272. fclose(infd);
  273. if(md_ctx.digest) EVP_MD_CTX_cleanup(&md_ctx);
  274. EVP_cleanup();
  275. return ret;
  276. }
  277. /*数字签名*/
  278. BOOL CEvp::Sign(const char * key/*私钥*/,const int keylen/*0-内存私钥*/,const char * pwd,
  279. const char * mdname/*签名算法*/,const char * infoin/*输入文件*/,
  280. int inlen,/*输入长度,0->内存*/char * infout/*输出*/,
  281. UINT & outlen/*输出长度,输入文件时=0*/,char * outMsg)
  282. {
  283. BOOL ret=true;
  284. unsigned char * sig_buf=NULL;
  285. unsigned int sig_len,len=0;
  286. unsigned char inbuf[BUFLEN]="";
  287. EVP_PKEY * pkey=NULL;
  288. const EVP_MD *md=NULL;
  289. EVP_MD_CTX md_ctx;
  290. memset(&md_ctx,0,sizeof(md_ctx));
  291. BIO *in=NULL;
  292. FILE * outfd=NULL,* infd=NULL;
  293. long fileLen=0;//文件长度
  294. long finishLen=0;//完成长度
  295. BOOL bType=inlen;
  296. if(bType==0&&(strlen(infoin)==0||strlen(infout)==0))//输入文件时候
  297. {
  298. strcpy(outMsg,"NO specify input or output file");
  299. return FALSE;
  300. }
  301. if(bType==0)//文件
  302. {
  303. if ((infd = fopen (infoin, "rb")) == NULL)//原文
  304. {
  305. strcpy(outMsg,"open input file error");
  306. return FALSE;
  307. }
  308. if ((outfd = fopen (infout, "wb")) == NULL)//密文
  309. {
  310. strcpy(outMsg,"open output file error");
  311. fclose(infd);
  312. return FALSE;
  313. }
  314. fileLen=filelength(fileno(infd));//得到文件长度
  315. }
  316. OpenSSL_add_all_digests();
  317. pkey = CCertKey::LoadKey((char *)key,keylen,(char *)pwd,outMsg);
  318. if (pkey == NULL)
  319. ret=FALSE;
  320. goto err;
  321. }
  322. /* Do the signature */
  323. md = EVP_get_digestbyname(mdname);
  324. if(!md)
  325. {
  326. sprintf(outMsg,"Unknown message digest %s",mdname);
  327. ret=FALSE;
  328. goto err;
  329. }
  330. EVP_MD_CTX_init(&md_ctx);
  331. if(!EVP_SignInit_ex(&md_ctx,md,NULL))
  332. {
  333. strcpy(outMsg,"初始化算法结构出错");
  334. ret=FALSE;
  335. goto err;
  336. }
  337. if(bType==0)//文件
  338. {
  339. for(;;)
  340. {
  341. len = fread(inbuf, sizeof(char), BUFLEN, infd);
  342. if(len <= 0) break;
  343. if(!EVP_SignUpdate(&md_ctx, inbuf, len))
  344. {
  345. sprintf(outMsg,"中间过程出错");
  346. ret=FALSE;
  347. goto err;
  348. }
  349. finishLen+=len;
  350. DrawProg(finishLen*HUNDRED/fileLen);
  351. }
  352. }
  353. else//内存区域
  354. {
  355. for(UINT i=0;;i++)
  356. {
  357. //每次BUFLEN
  358. len=(inlen>BUFLEN)?BUFLEN:inlen;
  359. inlen-=len;
  360. if(!EVP_SignUpdate(&md_ctx, (infoin+i*BUFLEN), len))
  361. {
  362. strcpy(outMsg,"中间过程错误");
  363. ret=FALSE;
  364. goto err;
  365. }
  366. if(inlen <= 0) break;          
  367. }
  368. }
  369. sig_len =EVP_PKEY_size(pkey);
  370. sig_buf=new unsigned char[sig_len];
  371. // 簽名後的結果,必須是個夠大視 private key 長度不同而不同,可以 EVP_PKEY_size() 取得
  372. if(!EVP_SignFinal (&md_ctx, sig_buf, &sig_len, pkey))
  373. {
  374. sprintf(outMsg,"最终过程出错");
  375. ret=FALSE;
  376. }
  377. else if(bType!=0)//内存
  378. {
  379. memcpy(infout,sig_buf,sig_len);
  380. outlen=sig_len;
  381. }
  382. if(outfd!=NULL)
  383. {
  384. fwrite(sig_buf,sizeof(char),sig_len,outfd);
  385. outlen=0;
  386. }
  387. err:
  388. if(infd!=NULL)
  389. fclose(infd);
  390. if(outfd!=NULL)
  391. fclose(outfd);
  392. BIO_free(in);
  393. if(pkey) EVP_PKEY_free (pkey);
  394. if(md_ctx.digest) EVP_MD_CTX_cleanup(&md_ctx);
  395. delete [] sig_buf;
  396. EVP_cleanup();
  397. return ret;
  398. }
  399. /*数字签名验证*/
  400. BOOL CEvp::VerifySign(const char * cert/*公钥*/,const int certlen,
  401.   const char * pwd,const char * mdname/*签名算法*/,
  402.   const char * infoin,/*原始信息*/ 
  403.   int inlen/*输入长度0->文件*/,char * sign/*签名结果*/,
  404.   char * outMsg)
  405. {
  406. const EVP_MD *md=NULL;
  407. unsigned char inbuf[BUFLEN]="";
  408. BOOL ret=true;
  409. unsigned char * sig_buf=NULL;
  410. unsigned int sig_len,len=0;
  411. FILE * outfd=NULL,* infd=NULL;
  412. long fileLen=0;//文件长度
  413. long finishLen=0;//完成长度
  414. X509 * x509=NULL;
  415. EVP_PKEY * pcert=NULL;
  416. EVP_MD_CTX md_ctx;
  417. memset(&md_ctx,0,sizeof(md_ctx));
  418. BOOL bType=inlen;
  419. if(bType==0&&(strlen(infoin)==0||strlen(sign)==0))//输入文件时候
  420. {
  421. strcpy(outMsg,"NO specify input file");
  422. return FALSE;
  423. }
  424. if(bType==0)//内存
  425. {
  426. if ((infd = fopen (infoin, "rb")) == NULL)//原文
  427. {
  428. strcpy(outMsg,"open input file error");
  429. return FALSE;
  430. }
  431. if ((outfd = fopen (sign, "rb")) == NULL)//密文
  432. {
  433. strcpy(outMsg,"open output file error");
  434. fclose(infd);
  435. return FALSE;
  436. }
  437. fileLen=filelength(fileno(infd));//得到文件长度
  438. }
  439. OpenSSL_add_all_digests();
  440. x509 = CCertKey::LoadCert((char *)cert,certlen,(char *)pwd,outMsg);
  441. if (x509 == NULL)
  442. {
  443. ret=FALSE;
  444. goto err;
  445. }
  446. pcert=X509_get_pubkey(x509);
  447. if (pcert == NULL)
  448. {
  449. sprintf(outMsg,"Read Public Key Failed!");
  450. ret=FALSE;
  451. goto err;
  452. }
  453. md = EVP_get_digestbyname(mdname);  
  454. if(!md) 
  455. {
  456. sprintf(outMsg,"Unknown message digest %s",mdname);
  457. ret=FALSE;
  458. goto err;
  459. }
  460. EVP_MD_CTX_init(&md_ctx);
  461. if(!EVP_VerifyInit_ex(&md_ctx,md,NULL))
  462. {
  463. strcpy(outMsg,"初始化算法结构出错");
  464. ret=FALSE;
  465. goto err;
  466. }
  467. if(bType==0)//文件
  468. {
  469. for(;;)
  470. {
  471. len = fread(inbuf, sizeof(char), BUFLEN, infd);                  
  472. if(len <= 0) break;
  473. if(!EVP_VerifyUpdate (&md_ctx, inbuf, len))
  474. {
  475. strcpy(outMsg,"中间过程出错");
  476. ret=FALSE;
  477. goto err;
  478. }
  479. finishLen+=len;
  480. DrawProg(finishLen*HUNDRED/fileLen);
  481. }
  482. }
  483. else//内存区域
  484. {
  485. for(UINT i=0;;i++)
  486. {
  487. //每次BUFLEN
  488. len=(inlen>BUFLEN)?BUFLEN:inlen;
  489. inlen-=len;
  490. if(!EVP_VerifyUpdate(&md_ctx, (infoin+i*BUFLEN), len))
  491. {
  492. strcpy(outMsg,"中间过程错误");
  493. ret=FALSE;
  494. goto err;
  495. }
  496. if(inlen <= 0) break;          
  497. }
  498. }
  499. sig_len =EVP_PKEY_size(pcert);//这里应该改动
  500. sig_buf=new unsigned char[sig_len];
  501. if(bType==0)//文件
  502. {
  503. fread(sig_buf,sizeof(char),sig_len,outfd);
  504. }
  505. else
  506. {
  507. memcpy(sig_buf,sign,sig_len);
  508. }
  509. if(!EVP_VerifyFinal (&md_ctx, sig_buf, sig_len, pcert))
  510. {
  511. strcpy(outMsg,"最终过程出错");
  512. ret=FALSE;
  513. }
  514. err:
  515. if(infd!=NULL)
  516. fclose(infd);
  517. if(outfd!=NULL)
  518. fclose(outfd);
  519. if(pcert) EVP_PKEY_free (pcert);
  520. if(x509) X509_free(x509);
  521. if(md_ctx.digest) EVP_MD_CTX_cleanup(&md_ctx);
  522. delete [] sig_buf;
  523. EVP_cleanup();
  524. return ret;
  525. }
  526. /*数字信封 - 多证书 */
  527. //文件结构
  528. // 加密后重要信息长度 DWORD
  529. // 加密后重要信息长度 CRC校验码 UINT
  530. // 加密后重要信息
  531. // -------------------------------重要信息开始--------------------------------
  532. // 公钥个数n
  533. // n个
  534. // 公钥加密的对称密钥长度
  535. // 公钥加密的对称密钥内容
  536. // 向量IV
  537. // -------------------------------重要信息结束--------------------------------
  538. // 加密文件内容
  539. BOOL CEvp::Seal(stuCertLink * pCERT/*[in]合法用户公钥链*/,
  540.   char * cpname/*算法名称*/,
  541.   char * filein/*输入文件*/, 
  542.   char * fileout/*输出文件*/,
  543.   char * outMsg)//写信
  544. {
  545. //对随机数播种(seeded)。
  546. UCHAR iv[EVP_MAX_IV_LENGTH]="";
  547. UCHAR * ekey [128]; 
  548. EVP_PKEY * pubKey[128];
  549. int ekeylen[128];
  550. UCHAR buf[BUFLEN]="";
  551. UCHAR ebuf[BUFLEN + EVP_MAX_BLOCK_LENGTH]="";
  552. int readlen=0;
  553. int ebuflen = 0;
  554. EVP_CIPHER_CTX eCtx;
  555. memset(&eCtx,0,sizeof(eCtx));
  556. int index = 0;
  557. const EVP_CIPHER *cipher=NULL;
  558. BOOL ret=true;
  559. FILE *outfd,*infd;
  560.   DWORD fileLen=0;//文件长度
  561. DWORD finishLen=0;//完成长度
  562. UINT uCrc16 = 0; //加密后重要信息CRC码
  563. DWORD dOutLen = 0;//内存文件长度
  564. BYTE * pOut = NULL; //内存文件缓冲区
  565. DWORD dFileInfoLen = 0;
  566. if(strlen(filein)==0||strlen(fileout)==0)
  567. {
  568. strcpy(outMsg,"NO specify input or output file");
  569. return false;
  570. }
  571. if ((infd = fopen (filein, "rb")) == NULL)//原文
  572. {
  573. strcpy(outMsg,"open input file error");
  574. return false;
  575. }
  576. if ((outfd = fopen (fileout, "wb")) == NULL)//密文
  577. {
  578. strcpy(outMsg,"open output file error");
  579. fclose(infd);
  580. return false;
  581. }
  582. //加载加密公钥
  583. HRSRC hRsrc = FindResource(NULL,MAKEINTRESOURCE(IDR_FILE_CERT),"CERT");
  584. DWORD lenCert = SizeofResource(NULL, hRsrc); 
  585. HGLOBAL hgCert = LoadResource(NULL,hRsrc);
  586. LPSTR lpCert = (LPSTR)LockResource(hgCert);
  587. CMemFile MemFile; //用于存放重要信息的内存文件
  588. DWORD dInLen = 0;
  589. BYTE * pIn = NULL; //用于MemFile.Dectch();
  590. fileLen = filelength(fileno(infd));//得到文件长度
  591. OpenSSL_add_all_algorithms();
  592. int nCountCert = 0; //证书个数
  593. for(stuCertLink * temp = pCERT; temp != NULL; temp=temp->Link, nCountCert++)
  594. {
  595. X509 * pX509 = NULL;
  596. pX509 = CCertKey::LoadCert(temp->pCert, temp->CertLen, NULL, outMsg);
  597.     if(pX509)
  598. {
  599. pubKey[nCountCert] = X509_get_pubkey(pX509);
  600. if (pubKey[nCountCert] == NULL)
  601. {
  602. sprintf(outMsg,"Read Public Key Failed!");
  603. ret=false;
  604. goto err;
  605. }
  606. ekey[nCountCert] = new unsigned char[EVP_PKEY_size(pubKey[nCountCert])];
  607. X509_free(pX509);
  608. }
  609. else
  610. {
  611. sprintf(outMsg,"加载第%d个证书失败",nCountCert);
  612. ret = false;
  613. goto err;
  614. }
  615. }
  616. cipher = EVP_get_cipherbyname(cpname);
  617. if(cipher==NULL)
  618. {
  619. sprintf(outMsg,"Unknown cipher name %sn",cpname);
  620. ret=false;
  621. goto err;
  622. }
  623. if(!EVP_SealInit(&eCtx,cipher,
  624. ekey,
  625. ekeylen,//存放所有 ek 長度
  626. iv,//自动生成
  627. pubKey,//加密 ek 用的 public key(s)
  628. nCountCert))
  629. {
  630. ret=false;
  631. goto err;
  632. }
  633. MemFile.Write(&nCountCert, sizeof(int)); //1 - 写入公钥个数
  634. //fwrite((char*)&nCountCert,sizeof(char), sizeof(int),outfd);//写入公钥个数
  635. for(index = 0; index < nCountCert; index++)
  636. {
  637. MemFile.Write(&ekeylen[index], sizeof(int));
  638. // fwrite(&ekeylen[index],sizeof(char), sizeof(int),outfd);//写入n个经公钥加密的对称密钥长度
  639. MemFile.Write(ekey[index], ekeylen[index]);
  640. // fwrite(ekey[index],sizeof(char) ,ekeylen[index],outfd);//写入n个经公钥加密的对称密钥
  641. }
  642. MemFile.Write(iv, sizeof(iv));
  643. // fwrite(iv,sizeof(char),sizeof(iv),outfd);//写入向量
  644. //构造加密结果 长度+1 内存
  645. dFileInfoLen = CEvp::GetEncLen(lpCert, lenCert, MemFile.GetLength());
  646. dOutLen = dFileInfoLen + 1;
  647. pOut = new BYTE[dOutLen];
  648. dInLen = MemFile.GetLength();
  649. pIn = MemFile.Detach();
  650. //加密重要信息
  651. if(!CEvp::RSAPubEnc((BYTE *)lpCert, lenCert, "", pIn, 
  652. dInLen, pOut, dOutLen, outMsg))
  653. {
  654. //加密失败
  655. ret=false;
  656. goto err;
  657. }
  658. //得到加密后长度的CRC校验
  659. if(!CRC::GetCrc16((char*)&dOutLen, sizeof(DWORD), uCrc16))
  660. {
  661. //加密失败
  662. ret=false;
  663. goto err;
  664. }
  665. //写入加密后重要信息长度和CRC校验和加密后重要信息内容
  666. fwrite(&dOutLen,sizeof(char),sizeof(DWORD),outfd);
  667. fwrite(&uCrc16,sizeof(char),sizeof(UINT),outfd);
  668. fwrite(pOut,sizeof(char),dOutLen,outfd);
  669. for(;;)
  670. {
  671. readlen = fread(buf, sizeof(char),sizeof(buf),infd);
  672. if (readlen <= 0)
  673. {
  674. break;
  675. }
  676. if(!EVP_SealUpdate(&eCtx, ebuf, &ebuflen, buf, readlen))
  677. {
  678. strcpy(outMsg,"中间过程出错");
  679. ret=false;
  680. goto err;
  681. }
  682. fwrite(ebuf,sizeof(char),ebuflen,outfd);
  683. finishLen += readlen;
  684. DrawProg(finishLen*HUNDRED/fileLen);//前半程
  685. }
  686. if(!EVP_SealFinal(&eCtx, ebuf, &ebuflen))
  687. {
  688. strcpy(outMsg,"最终过程出错");
  689. ret=false;
  690. goto err;
  691. }
  692. fwrite(ebuf, sizeof(char), ebuflen,outfd);
  693. err:
  694. fclose(infd);
  695. fclose(outfd);
  696. free(pIn);
  697. delete [] pOut;
  698. for(int i = 0;i< nCountCert;i++)
  699. {
  700. if(pubKey[i]) EVP_PKEY_free(pubKey[i]);
  701. if(ekey[i]) delete [] ekey[i];
  702. }
  703. if(eCtx.cipher) EVP_CIPHER_CTX_cleanup(&eCtx);
  704. EVP_cleanup();
  705. return ret;
  706. }
  707. /*拆封数字信封*/
  708. BOOL CEvp::OpenSeal(char * key/*私钥*/, int keylen, char * pwd/*私钥密码*/, 
  709.    char * cpname/*算法名称*/, char * filein/*输入文件*/, 
  710.    char * fileout/*输出文件*/,char * outMsg)
  711. {
  712. unsigned char buf[BUFLEN]="";
  713. unsigned char ebuf[BUFLEN + EVP_MAX_BLOCK_LENGTH]="";
  714. unsigned char iv[EVP_MAX_IV_LENGTH]="";
  715. const EVP_CIPHER *cipher=NULL;
  716. int ebuflen=0,readlen=0;
  717. bool ret=true;
  718. FILE *outfd,*infd;
  719. DWORD fileLen=0;//文件长度
  720. DWORD finishLen=0;//完成长度
  721. int nCountCert = 0; //公钥个数
  722. int index = 0;
  723. UCHAR * ekey [128] = {0}; 
  724. int ekeylen[128];
  725. BOOL bInit = FALSE;//是否初始化成功
  726. DWORD dFileInfoLen = 0;//加密后重要信息长度
  727. UINT uCrc16 = 0; //加密后重要信息CRC码
  728. EVP_CIPHER_CTX eCtx;
  729. memset(&eCtx,0,sizeof(eCtx));
  730. EVP_PKEY * pkey=NULL;
  731. if(strlen(filein)==0||strlen(fileout)==0)
  732. {
  733. strcpy(outMsg,"NO specify input or output file");
  734. return false;
  735. }
  736.     if ((infd = fopen (filein, "rb")) == NULL)//原文
  737. {
  738. strcpy(outMsg,"open input file error");
  739. return false;
  740. }
  741. if ((outfd = fopen (fileout, "wb")) == NULL)//密文
  742. {
  743. strcpy(outMsg,"open output file error");
  744. fclose(infd);
  745. return false;
  746. }
  747. fileLen = filelength(fileno(infd));//得到文件长度
  748. OpenSSL_add_all_algorithms();//digests   and ciphers
  749. /* Read private key */
  750. pkey = CCertKey::LoadKey(key,keylen,pwd,outMsg);
  751. if (pkey == NULL)
  752. fclose(infd);
  753. fclose(outfd);
  754. return FALSE;
  755. }
  756. //得到重要信息长度和CRC校验码
  757. readlen = fread(&dFileInfoLen, sizeof(char),sizeof(DWORD),infd);
  758. finishLen += readlen;
  759. readlen = fread(&uCrc16, sizeof(char),sizeof(UINT),infd);
  760. finishLen += readlen;
  761. if(!CRC::CheckCrc((char *)&dFileInfoLen, sizeof(DWORD), uCrc16))
  762. {
  763. strcpy(outMsg ,"文件头CRC校验错误");
  764. return FALSE;
  765. }
  766. //开辟缓冲区,容纳加密后的重要文件信息
  767. BYTE * pIn = NULL;
  768. pIn = new BYTE[dFileInfoLen + 1];
  769. readlen = fread(pIn, sizeof(char), dFileInfoLen, infd);
  770. finishLen += readlen;
  771. HRSRC hRsrc = FindResource(NULL,MAKEINTRESOURCE(IDR_FILE_KEY),"CERT");
  772. DWORD lenKey = SizeofResource(NULL, hRsrc); 
  773. HGLOBAL hgKey = LoadResource(NULL,hRsrc);
  774. LPSTR lpKey = (LPSTR)LockResource(hgKey);
  775. DWORD dOutLen = dFileInfoLen;
  776. //开辟缓冲区,容纳加密后的信息体
  777. BYTE * pOut = NULL;
  778. pOut = new BYTE[dOutLen];
  779. if(!CEvp::RSAPrivDec((BYTE *)lpKey, lenKey, pwd, pIn, 
  780. dFileInfoLen, pOut, dOutLen, outMsg))
  781. {
  782. //解密失败
  783. strcpy(outMsg ,"重要信息解密失败");
  784. fclose(infd);
  785. fclose(outfd);
  786. delete [] pIn;
  787. delete [] pOut;
  788. return FALSE;
  789. }
  790. CMemFile MemFile;
  791. MemFile.Attach(pOut, dOutLen);
  792. //首先是公钥个数
  793. MemFile.Read(&nCountCert, sizeof(int));
  794. for(index = 0; index < nCountCert; index++)
  795. {
  796. MemFile.Read(&ekeylen[index], sizeof(int));
  797. ekey[index] = new unsigned char[ekeylen[index]];
  798. MemFile.Read(ekey[index], ekeylen[index]);
  799. }
  800. MemFile.Read(iv, sizeof(iv));
  801. MemFile.Close();
  802. //输入文件已经偏移到加密后的文件
  803. cipher = EVP_get_cipherbyname(cpname);
  804. if(cipher == NULL)
  805. {
  806. sprintf(outMsg,"Unknown cipher name %sn",cpname);
  807. ret = false;
  808. goto err;
  809. }
  810. for(index = 0; index<nCountCert; index++)
  811. {
  812. if (ekeylen[index] != EVP_PKEY_size(pkey))
  813. {
  814. continue;
  815. }
  816. if(EVP_OpenInit(&eCtx,cipher, ekey[index],ekeylen[index],iv,pkey))
  817. {
  818. bInit = TRUE;
  819. break;
  820. }
  821. }
  822. if(!bInit)
  823. {
  824. sprintf(outMsg,"指定证书不能解密此文件");
  825. ret=false;
  826. goto err;
  827. }
  828. for(;;)
  829. {
  830. readlen = fread(buf, sizeof(char),sizeof(buf),infd);
  831. if (readlen <= 0)
  832. {
  833. break;
  834. }
  835. if(!EVP_OpenUpdate(&eCtx, ebuf, &ebuflen, buf, readlen))
  836. {
  837. sprintf(outMsg,"中间过程错误");
  838. ret=false;
  839. goto err;
  840. }
  841. fwrite(ebuf,sizeof(char),ebuflen,outfd);
  842. finishLen += readlen;
  843. DrawProg(finishLen*HUNDRED/fileLen);
  844. }
  845. if(!EVP_OpenFinal(&eCtx, ebuf, &ebuflen))
  846. {
  847. sprintf(outMsg,"最终过程错误");
  848. ret=false;
  849. goto err;
  850. }
  851. fwrite(ebuf, sizeof(char), ebuflen,outfd);
  852. err:
  853. fclose(infd);
  854. fclose(outfd);
  855. delete [] pIn;
  856. delete [] pOut;
  857. for(int i = 0;i< index;i++)
  858. {
  859. if(ekey[i]) delete ekey[i];
  860. }
  861. if(pkey) EVP_PKEY_free(pkey);
  862. if((&eCtx)->cipher) EVP_CIPHER_CTX_cleanup(&eCtx);
  863. EVP_cleanup();
  864. return ret;
  865. }
  866. //公钥加密
  867. BOOL CEvp::RSAPubEnc(const BYTE * pCertBuf/*[in]公钥*/,const UINT nCertLen/*[in]公钥长度*/,
  868. const char * pPwd/*[in]公钥密码,只针对PFX包文件*/,const BYTE * pInStream/*[in]输入文件或内存*/,
  869. DWORD nInlen/*[in]数据长度,为0表示pInStream为文件名*/,BYTE * pOutStream/*[out]加密后的数据*/,
  870. DWORD & nOutlen/*[in,out]in为0时候表示pOutStream为文件名,out加密后数据长度*/,
  871. char * OperMsg/*[out]返回操作错误信息*/)
  872. {
  873. UINT iblock_size = 0, //输入块长度
  874. oblock_size = 0; //输出块长度
  875. unsigned char * bufin=NULL,
  876.   * bufout=NULL;
  877. int inlen = 0,
  878. outlen = 0;
  879. BOOL ret = TRUE;
  880. long fileLen = 0;//文件长度
  881. long finishLen = 0;//完成长度
  882. X509 * x509 = NULL;
  883. EVP_PKEY * pcert = NULL;
  884. RSA * rsa = NULL;
  885. int memtemplen = 0; //输出内存偏移
  886. UINT len = 0; //输入内存剩余长度
  887. int uMaxMem = nOutlen; //可能为负数,不能用UINT
  888. BOOL bOutType = FALSE;//输出文件类型,内存-FALSE,文件-TRUE;
  889. if(nOutlen == 0) 
  890. {
  891. //检测文件名是否能够打开,以防pOutStream为文件
  892. bOutType = TRUE;
  893. }
  894. FILE * outfd = NULL,
  895. * infd = NULL;
  896. if(nInlen == 0)//输入为文件
  897. {
  898. if(pInStream == NULL || strlen((char*)pInStream)==0)
  899. {
  900. strcpy(OperMsg,"未指定输入文件");
  901. return FALSE;
  902. }
  903. if ((infd = fopen ((char *)pInStream, "rb")) == NULL)//原文
  904. {
  905. sprintf(OperMsg,"打开文件%s失败",pInStream);
  906. return FALSE;
  907. }
  908. fileLen = filelength(fileno(infd));//得到文件长度
  909. }
  910. else
  911. fileLen = nInlen;
  912. if(nOutlen == 0)//输出为文件
  913. {
  914. if(pOutStream == NULL || strlen((char*)pOutStream)==0)
  915. {
  916. strcpy(OperMsg,"未指定输出文件");
  917. return FALSE;
  918. }
  919. if ((outfd = fopen ((char *)pOutStream, "wb")) == NULL)//原文
  920. {
  921. sprintf(OperMsg,"打开文件%s失败",pOutStream);
  922. return FALSE;
  923. }
  924. }
  925. x509 = CCertKey::LoadCert((char *)pCertBuf,nCertLen,(char *)pPwd,OperMsg);
  926. if (x509 == NULL)
  927. {
  928. ret = FALSE;
  929. goto err;
  930. }
  931. pcert = X509_get_pubkey(x509);
  932. if(pcert==NULL)
  933. {
  934. sprintf(OperMsg,"取得公钥密钥失败");
  935. ret = FALSE;
  936. goto err;
  937. }
  938.     if (!(rsa = EVP_PKEY_get1_RSA(pcert)))
  939. {
  940. sprintf(OperMsg,"取得RSA密钥失败");
  941. ret=FALSE;
  942. goto err;
  943.     }
  944. iblock_size = BN_num_bytes(rsa->n) - 11;//预加密长度,117
  945. oblock_size = BN_num_bytes(rsa->n);//加密后长度,128
  946. bufin = new unsigned char[iblock_size];
  947. memset(bufin,0,iblock_size);
  948. bufout = new unsigned char[oblock_size];
  949. memset(bufout,0,oblock_size);
  950. if(nInlen==0)//文件
  951. {
  952. for(;;)
  953. {
  954. inlen = fread(bufin,sizeof(char),iblock_size,infd);
  955. if(!inlen)
  956. break;
  957. outlen = RSA_public_encrypt(inlen,bufin,bufout,rsa,RSA_PKCS1_PADDING);
  958. if (outlen == -1)//加密后资料长度
  959. {
  960. sprintf(OperMsg,"RSA加密失败");
  961. ret=FALSE;
  962. goto err;
  963. }
  964. if(bOutType)
  965. {
  966. fwrite(bufout,sizeof(char),outlen,outfd);
  967. memset(bufout,0,oblock_size);
  968. }
  969. else
  970. {
  971. uMaxMem -= outlen; //剩余缓冲大小
  972. if(uMaxMem < 0)
  973. {
  974. strcpy(OperMsg, "输出缓冲过小,不能容纳操作结果"); 
  975. ret = FALSE;
  976. goto err;
  977. }
  978. memcpy(pOutStream + memtemplen, bufout, outlen);//拷贝到调用函数
  979. memtemplen += outlen;
  980. }
  981. finishLen += inlen;
  982. DrawProg(finishLen*HUNDRED/fileLen);
  983. }
  984. nOutlen = memtemplen;
  985. }
  986. else//内存区域
  987. {
  988. for(UINT i=0;;i++)
  989. {
  990. //每次 iblock_size 或实际长度
  991. len = (nInlen>iblock_size)?iblock_size:nInlen;//内存区域长度
  992. nInlen -= len;
  993. outlen=RSA_public_encrypt(len,(UCHAR *)(pInStream+i*iblock_size),bufout,rsa,RSA_PKCS1_PADDING);
  994. if (outlen == -1)//加密后资料长度
  995. {
  996. sprintf(OperMsg,"RSA加密失败");
  997. ret = FALSE;
  998. goto err;
  999. }
  1000. if(bOutType)
  1001. {
  1002. fwrite(bufout,sizeof(char),outlen,outfd);
  1003. memset(bufout,0,outlen);
  1004. }
  1005. else
  1006. {
  1007. uMaxMem -= outlen; //剩余缓冲大小
  1008. if(uMaxMem < 0)
  1009. {
  1010. strcpy(OperMsg, "输出缓冲过小,不能容纳操作结果"); 
  1011. ret = FALSE;
  1012. goto err;
  1013. }
  1014. memcpy(pOutStream + memtemplen,bufout,outlen);//拷贝到调用函数
  1015. memtemplen += outlen;
  1016. }
  1017. finishLen += len;
  1018. DrawProg(finishLen*HUNDRED/fileLen);
  1019. if(nInlen <= 0) break;     
  1020. }
  1021. nOutlen = memtemplen;
  1022. }
  1023. err:
  1024. if(infd!=NULL)
  1025. fclose(infd);
  1026. if(outfd!=NULL)
  1027. fclose(outfd);
  1028. if(pcert) EVP_PKEY_free(pcert);
  1029.     if(x509) X509_free(x509);
  1030. if(rsa) RSA_free(rsa);
  1031. delete [] bufin;
  1032. delete [] bufout;
  1033. return ret;
  1034. }
  1035. //私钥解密
  1036. BOOL CEvp::RSAPrivDec(const BYTE * pKeyBuf/*[in]私钥*/,const UINT nKeyLen/*[in]私钥长度*/,
  1037. const char * pPwd/*[in]私钥密码*/,const BYTE * pInStream/*[in]输入文件或内存*/,
  1038. DWORD nInlen/*[in]数据长度,为0表示pInStream为文件名*/,BYTE * pOutStream/*[out]解密后的数据*/,
  1039. DWORD & nOutlen/*[in,out]in为0时候表示pOutStream为文件名,out解密后数据长度*/,
  1040.     char * OperMsg/*[out]返回操作错误信息*/)
  1041. {
  1042. unsigned char * bufin = NULL,
  1043.   * bufout = NULL;
  1044. UINT iblock_size = 0,
  1045. oblock_size = 0,
  1046. outlen = 0,
  1047. inlen = 0;
  1048. BOOL ret = true;
  1049. long fileLen = 0;//文件长度
  1050. long finishLen = 0;//完成长度
  1051. RSA * rsa = NULL;
  1052. EVP_PKEY * pkey = NULL;
  1053. FILE * outfd = NULL,
  1054.  * infd = NULL;
  1055. int memtemplen = 0; //输出内存偏移
  1056. UINT len = 0; //输入内存剩余长度
  1057. int uMaxMem = nOutlen; //可能为负数,不能用UINT
  1058. BOOL bOutType = FALSE;//输出文件类型,内存-FALSE,文件-TRUE;
  1059. if(nOutlen == 0) bOutType = TRUE;
  1060. if(nInlen == 0)//输入为文件
  1061. {
  1062. if(pInStream == NULL || strlen((char*)pInStream)==0)
  1063. {
  1064. strcpy(OperMsg,"未指定输入文件");
  1065. return FALSE;
  1066. }
  1067. if ((infd = fopen ((char *)pInStream, "rb")) == NULL)//原文
  1068. {
  1069. sprintf(OperMsg,"打开文件%s失败",pInStream);
  1070. return FALSE;
  1071. }
  1072. fileLen = filelength(fileno(infd));//得到文件长度
  1073. }
  1074. else
  1075. fileLen = nInlen;
  1076. if(nOutlen == 0)//输出为文件
  1077. {
  1078. if(pOutStream == NULL || strlen((char*)pOutStream)==0)
  1079. {
  1080. strcpy(OperMsg,"未指定输出文件");
  1081. return FALSE;
  1082. }
  1083. if ((outfd = fopen ((char *)pOutStream, "wb")) == NULL)//原文
  1084. {
  1085. sprintf(OperMsg,"打开文件%s失败",pOutStream);
  1086. return FALSE;
  1087. }
  1088. }
  1089. pkey=CCertKey::LoadKey((char *)pKeyBuf,nKeyLen,(char *)pPwd,OperMsg);
  1090. if (pkey == NULL)
  1091. // sprintf(OperMsg,"取得私钥密钥失败");
  1092. ret=FALSE;
  1093. goto err;
  1094. }
  1095.     if (!(rsa = EVP_PKEY_get1_RSA(pkey)))
  1096. {
  1097. sprintf(OperMsg,"取得RSA密钥失败");
  1098. ret=FALSE;
  1099. goto err;
  1100.     }
  1101. iblock_size = BN_num_bytes(rsa->n);//预接密长度 128
  1102. oblock_size = BN_num_bytes(rsa->n) - 11;//杰密后长度 117
  1103. bufin=new unsigned char[iblock_size];
  1104. bufout=new unsigned char[oblock_size];
  1105. if(nInlen == 0)//文件
  1106. {
  1107. for(;;)
  1108. {
  1109. inlen=fread(bufin,sizeof(char),iblock_size,infd);
  1110. if(!inlen)
  1111. break;//117,128
  1112. outlen = RSA_private_decrypt(inlen,bufin,bufout,rsa,RSA_PKCS1_PADDING);
  1113. if (outlen == -1)//加密后资料长度
  1114. {
  1115. sprintf(OperMsg,"RSA解密失败");
  1116. ret=FALSE;
  1117. goto err;
  1118. }
  1119. if(bOutType)
  1120. {
  1121. fwrite(bufout,sizeof(char),outlen,outfd);
  1122. memset(bufout,0,oblock_size);
  1123. }
  1124. else
  1125. {
  1126. uMaxMem -= outlen; //剩余缓冲大小
  1127. if(uMaxMem < 0)
  1128. {
  1129. strcpy(OperMsg, "输出缓冲过小,不能容纳操作结果"); 
  1130. ret = FALSE;
  1131. goto err;
  1132. }
  1133. memcpy(pOutStream + memtemplen,bufout,outlen);//拷贝到调用函数
  1134. memtemplen += outlen;
  1135. }
  1136. finishLen+=inlen;
  1137. DrawProg(finishLen*HUNDRED/fileLen);
  1138. }
  1139. nOutlen = memtemplen;
  1140. }
  1141. else//内存
  1142. {
  1143. for(UINT i=0;;i++)
  1144. {
  1145. //每次 iblock_size 或实际长度
  1146. len = (nInlen>iblock_size)?iblock_size:nInlen;//内存区域长度
  1147. nInlen -= len;
  1148. outlen = RSA_private_decrypt(len,(UCHAR *)(pInStream+i*iblock_size),bufout,
  1149. rsa,RSA_PKCS1_PADDING);
  1150. if (outlen == -1)//加密后资料长度
  1151. {
  1152. sprintf(OperMsg,"RSA解密失败");
  1153. ret = FALSE;
  1154. goto err;
  1155. }
  1156. if(bOutType)
  1157. {
  1158. fwrite(bufout,sizeof(char),outlen,outfd);
  1159. memset(bufout,0,outlen);
  1160. }
  1161. else
  1162. {
  1163. uMaxMem -= outlen; //剩余缓冲大小
  1164. if(uMaxMem < 0)
  1165. {
  1166. strcpy(OperMsg, "输出缓冲过小,不能容纳操作结果"); 
  1167. ret = FALSE;
  1168. goto err;
  1169. }
  1170. memcpy(pOutStream + memtemplen,bufout,outlen);//拷贝到调用函数
  1171. memtemplen += outlen;
  1172. }
  1173. finishLen += len;
  1174. DrawProg(finishLen*HUNDRED/fileLen);
  1175. if(nInlen <= 0) break;          
  1176. }
  1177. nOutlen = memtemplen;
  1178. }
  1179. err:
  1180. if(pkey) EVP_PKEY_free(pkey);
  1181. if(infd!=NULL)
  1182. fclose(infd);
  1183. if(outfd!=NULL)
  1184. fclose(outfd);
  1185. if(rsa) RSA_free(rsa);
  1186. delete [] bufin;
  1187. delete [] bufout;
  1188. return ret;
  1189. }
  1190. /*私钥加密(签名)*/
  1191. BOOL CEvp::RSAPrivEnc(const BYTE * pKeyBuf/*[in]私钥*/,const UINT nKeyLen/*[in]私钥长度*/,
  1192. const char * pPwd/*[in]私钥密码*/,const BYTE * pInStream/*[in]输入文件或内存*/,
  1193. DWORD nInlen/*[in]数据长度,为0表示pInStream为文件名*/,BYTE * pOutStream/*[out]加密后的数据*/,
  1194. DWORD & nOutlen/*[in,out]in为0时候表示pOutStream为文件名,out加密后数据长度*/,
  1195. char * OperMsg/*[out]返回操作错误信息*/)
  1196. {
  1197. RSA * rsa = NULL;
  1198. EVP_PKEY * pkey = NULL;
  1199. UINT iblock_size = 0,
  1200. oblock_size = 0,
  1201. outlen = 0,
  1202. inlen = 0;
  1203. BOOL ret = TRUE;
  1204. UCHAR * bufin = NULL,
  1205.   * bufout = NULL;
  1206. long fileLen = 0;//文件长度
  1207. long finishLen = 0;//完成长度
  1208. int memtemplen = 0; //输出内存偏移
  1209. UINT len = 0; //输入内存剩余长度
  1210. int uMaxMem = nOutlen; //可能为负数,不能用UINT
  1211. FILE * outfd = NULL,
  1212.  * infd = NULL;
  1213. BOOL bOutType = FALSE;//输出文件类型,内存-FALSE,文件-TRUE;
  1214. if(nOutlen == 0) bOutType = TRUE;
  1215. if(nInlen == 0)//输入为文件
  1216. {
  1217. if(pInStream == NULL || strlen((char*)pInStream)==0)
  1218. {
  1219. strcpy(OperMsg,"未指定输入文件");
  1220. return FALSE;
  1221. }
  1222. if ((infd = fopen ((char *)pInStream, "rb")) == NULL)//原文
  1223. {
  1224. sprintf(OperMsg,"打开文件%s失败",pInStream);
  1225. return FALSE;
  1226. }
  1227. fileLen = filelength(fileno(infd));//得到文件长度
  1228. }
  1229. else
  1230. fileLen = nInlen;
  1231. if(nOutlen == 0)//输出为文件
  1232. {
  1233. if(pOutStream == NULL || strlen((char*)pOutStream)==0)
  1234. {
  1235. strcpy(OperMsg,"未指定输出文件");
  1236. return FALSE;
  1237. }
  1238. if ((outfd = fopen ((char *)pOutStream, "wb")) == NULL)//原文
  1239. {
  1240. sprintf(OperMsg,"打开文件%s失败",pOutStream);
  1241. return FALSE;
  1242. }
  1243. }
  1244. pkey=CCertKey::LoadKey((char *)pKeyBuf,nKeyLen,(char *)pPwd,OperMsg);
  1245. if (pkey == NULL)
  1246. // sprintf(OperMsg,"取得私钥密钥失败");
  1247. ret=FALSE;
  1248. goto err;
  1249. }
  1250.     if (!(rsa = EVP_PKEY_get1_RSA(pkey)))
  1251. {
  1252. sprintf(OperMsg,"取得RSA密钥失败");
  1253. ret=FALSE;
  1254. goto err;
  1255.     }
  1256. iblock_size = BN_num_bytes(rsa->n) - 11;//输入长度 117
  1257.   oblock_size = BN_num_bytes(rsa->n);//加密后长度 128
  1258. bufin=new unsigned char[iblock_size];
  1259. bufout=new unsigned char[oblock_size];
  1260. if(nInlen == 0)//文件
  1261. {
  1262. for(;;)
  1263. {
  1264. inlen=fread(bufin,sizeof(char),iblock_size,infd);
  1265. if(!inlen)
  1266. break;//117,128
  1267. outlen = RSA_private_encrypt(inlen,bufin,bufout,rsa,RSA_PKCS1_PADDING);
  1268. if (outlen == -1)//加密后资料长度
  1269. {
  1270. sprintf(OperMsg,"RSA加密失败");
  1271. ret=FALSE;
  1272. goto err;
  1273. }
  1274. if(bOutType)
  1275. {
  1276. fwrite(bufout,sizeof(char),outlen,outfd);
  1277. memset(bufout,0,oblock_size);
  1278. }
  1279. else
  1280. {
  1281. uMaxMem -= outlen; //剩余缓冲大小
  1282. if(uMaxMem < 0)
  1283. {
  1284. strcpy(OperMsg, "输出缓冲过小,不能容纳操作结果"); 
  1285. ret = FALSE;
  1286. goto err;
  1287. }
  1288. memcpy(pOutStream + memtemplen,bufout,outlen);//拷贝到调用函数
  1289. memtemplen += outlen;
  1290. }
  1291. finishLen+=inlen;
  1292. DrawProg(finishLen*HUNDRED/fileLen);
  1293. }
  1294. nOutlen = memtemplen;
  1295. }
  1296. else//内存
  1297. {
  1298. for(UINT i=0;;i++)
  1299. {
  1300. //每次 iblock_size 或实际长度
  1301. len = (nInlen>iblock_size)?iblock_size:nInlen;//内存区域长度
  1302. nInlen -= len;
  1303. outlen = RSA_private_encrypt(len,(UCHAR *)(pInStream+i*iblock_size),
  1304. bufout,rsa,RSA_PKCS1_PADDING);
  1305. if (outlen == -1)//加密后资料长度
  1306. {
  1307. sprintf(OperMsg,"RSA加密失败");
  1308. ret = FALSE;
  1309. goto err;
  1310. }
  1311. if(bOutType)
  1312. {
  1313. fwrite(bufout,sizeof(char),outlen,outfd);
  1314. memset(bufout,0,outlen);
  1315. }
  1316. else
  1317. {
  1318. uMaxMem -= outlen; //剩余缓冲大小
  1319. if(uMaxMem < 0)
  1320. {
  1321. strcpy(OperMsg, "输出缓冲过小,不能容纳操作结果"); 
  1322. ret = FALSE;
  1323. goto err;
  1324. }
  1325. memcpy(pOutStream + memtemplen,bufout,outlen);//拷贝到调用函数
  1326. memtemplen += outlen;
  1327. }
  1328. finishLen += len;
  1329. DrawProg(finishLen*HUNDRED/fileLen);
  1330. if(nInlen <= 0) break;          
  1331. }
  1332. nOutlen = memtemplen;
  1333. }
  1334. err:
  1335. if(pkey) EVP_PKEY_free(pkey);
  1336. if(infd!=NULL)
  1337. fclose(infd);
  1338. if(outfd!=NULL)
  1339. fclose(outfd);
  1340. if(rsa) RSA_free(rsa);
  1341. delete [] bufin;
  1342. delete [] bufout;
  1343. return ret;
  1344. }
  1345. //公钥解密
  1346. BOOL CEvp::RSAPubDec(const BYTE * pCertBuf/*[in]公钥*/,const UINT nCertLen/*[in]公钥长度*/,
  1347. const char * pPwd/*[in]公钥密码,只针对PFX包文件*/,const BYTE * pInStream/*[in]输入文件或内存*/,
  1348. DWORD nInlen/*[in]数据长度,为0表示pInStream为文件名*/,BYTE * pOutStream/*[out]加密后的数据*/,
  1349. DWORD & nOutlen/*[in,out]in为0时候表示pOutStream为文件名,out加密后数据长度*/,
  1350. char * OperMsg/*[out]返回操作错误信息*/)
  1351. {
  1352. UINT iblock_size = 0, //输入块长度
  1353. oblock_size = 0; //输出块长度
  1354. unsigned char * bufin=NULL,
  1355.   * bufout=NULL;
  1356. int inlen = 0,
  1357. outlen = 0;
  1358. BOOL ret = TRUE;
  1359. long fileLen = 0;//文件长度
  1360. long finishLen = 0;//完成长度
  1361. X509 * x509 = NULL;
  1362. EVP_PKEY * pcert = NULL;
  1363. RSA * rsa = NULL;
  1364. int memtemplen = 0; //输出内存偏移
  1365. UINT len = 0; //输入内存剩余长度
  1366. int uMaxMem = nOutlen; //可能为负数,不能用UINT
  1367. BOOL bOutType = FALSE;//输出文件类型,内存-FALSE,文件-TRUE;
  1368. if(nOutlen == 0) bOutType = TRUE;
  1369. FILE * outfd = NULL,
  1370. * infd = NULL;
  1371. if(nInlen == 0)//输入为文件
  1372. {
  1373. if(pInStream == NULL || strlen((char*)pInStream)==0)
  1374. {
  1375. strcpy(OperMsg,"未指定输入文件");
  1376. return FALSE;
  1377. }
  1378. if ((infd = fopen ((char *)pInStream, "rb")) == NULL)//原文
  1379. {
  1380. sprintf(OperMsg,"打开文件%s失败",pInStream);
  1381. return FALSE;
  1382. }
  1383. fileLen = filelength(fileno(infd));//得到文件长度
  1384. }
  1385. else
  1386. fileLen = nInlen;
  1387. if(nOutlen == 0)//输出为文件
  1388. {
  1389. if(pOutStream == NULL || strlen((char*)pOutStream)==0)
  1390. {
  1391. strcpy(OperMsg,"未指定输出文件");
  1392. return FALSE;
  1393. }
  1394. if ((outfd = fopen ((char *)pOutStream, "wb")) == NULL)//原文
  1395. {
  1396. sprintf(OperMsg,"打开文件%s失败",pOutStream);
  1397. return FALSE;
  1398. }
  1399. }
  1400. x509 = CCertKey::LoadCert((char *)pCertBuf,nCertLen,(char *)pPwd,OperMsg);
  1401. if (x509 == NULL)
  1402. {
  1403. ret = FALSE;
  1404. goto err;
  1405. }
  1406. pcert = X509_get_pubkey(x509);
  1407. if(pcert==NULL)
  1408. {
  1409. sprintf(OperMsg,"取得公钥密钥失败");
  1410. ret = FALSE;
  1411. goto err;
  1412. }
  1413.     if (!(rsa = EVP_PKEY_get1_RSA(pcert)))
  1414. {
  1415. sprintf(OperMsg,"取得RSA密钥失败");
  1416. ret=FALSE;
  1417. goto err;
  1418.     }
  1419. iblock_size = BN_num_bytes(rsa->n);//预解密长度128
  1420. oblock_size = BN_num_bytes(rsa->n) - 11;//解密后长度117
  1421. bufin=new unsigned char[iblock_size];
  1422. bufout=new unsigned char[oblock_size];
  1423. if(nInlen==0)//文件
  1424. {
  1425. for(;;)
  1426. {
  1427. inlen = fread(bufin,sizeof(char),iblock_size,infd);
  1428. if(!inlen)
  1429. break;
  1430. outlen = RSA_public_decrypt(inlen,bufin,bufout,rsa,RSA_PKCS1_PADDING);
  1431. if (outlen == -1)//加密后资料长度
  1432. {
  1433. sprintf(OperMsg,"RSA解密失败");
  1434. ret=FALSE;
  1435. goto err;
  1436. }
  1437. if(bOutType)
  1438. {
  1439. fwrite(bufout,sizeof(char),outlen,outfd);
  1440. memset(bufout,0,oblock_size);
  1441. }
  1442. else
  1443. {
  1444. uMaxMem -= outlen; //剩余缓冲大小
  1445. if(uMaxMem < 0)
  1446. {
  1447. strcpy(OperMsg, "输出缓冲过小,不能容纳操作结果"); 
  1448. ret = FALSE;
  1449. goto err;
  1450. }
  1451. memcpy(pOutStream + memtemplen,bufout,outlen);//拷贝到调用函数
  1452. memtemplen += outlen;
  1453. }
  1454. finishLen += inlen;
  1455. DrawProg(finishLen*HUNDRED/fileLen);
  1456. }
  1457. nOutlen = memtemplen;
  1458. }
  1459. else//内存区域
  1460. {
  1461. for(UINT i=0;;i++)
  1462. {
  1463. //每次 iblock_size 或实际长度
  1464. len = (nInlen>iblock_size)?iblock_size:nInlen;//内存区域长度
  1465. nInlen -= len;
  1466. outlen = RSA_public_decrypt(len,(UCHAR *)(pInStream+i*iblock_size),bufout,rsa,RSA_PKCS1_PADDING);
  1467. if (outlen == -1)//加密后资料长度
  1468. {
  1469. sprintf(OperMsg,"RSA解密失败");
  1470. ret = FALSE;
  1471. goto err;
  1472. }
  1473. if(bOutType)
  1474. {
  1475. fwrite(bufout,sizeof(char),outlen,outfd);
  1476. memset(bufout,0,outlen);
  1477. }
  1478. else
  1479. {
  1480. uMaxMem -= outlen; //剩余缓冲大小
  1481. if(uMaxMem < 0)
  1482. {
  1483. strcpy(OperMsg, "输出缓冲过小,不能容纳操作结果"); 
  1484. ret = FALSE;
  1485. goto err;
  1486. }
  1487. memcpy(pOutStream + memtemplen,bufout,outlen);//拷贝到调用函数
  1488. memtemplen += outlen;
  1489. }
  1490. finishLen += len;
  1491. DrawProg(finishLen*HUNDRED/fileLen);
  1492. if(nInlen <= 0) break;     
  1493. }
  1494. nOutlen = memtemplen;
  1495. }
  1496. err:
  1497. if(infd!=NULL)
  1498. fclose(infd);
  1499. if(outfd!=NULL)
  1500. fclose(outfd);
  1501. if(pcert) EVP_PKEY_free(pcert);
  1502.     if(x509) X509_free(x509);
  1503. if(rsa) RSA_free(rsa);
  1504. delete [] bufin;
  1505. delete [] bufout;
  1506. return ret;
  1507. }
  1508. void CEvp::DrawProg(float fPot)
  1509. {
  1510. if(m_pProgress)
  1511. m_pProgress->SetPos((int)fPot);
  1512. }
  1513. void CEvp::SetProgRess(CProgressCtrlST *pProgress)
  1514. {
  1515. m_pProgress = pProgress;
  1516. }
  1517. //功能:得到加密后缓冲区大小
  1518. //参数:
  1519. // pCertBuf [in] - 公钥
  1520. // nCertLen [in] - 公钥长度
  1521. // nInlen   [in] - 数据长度
  1522. //返回值:输出缓冲区大小 -1 标示函数操作失败
  1523. DWORD CEvp::GetEncLen(const char * pCertBuf, const UINT nCertLen, const DWORD nInlen)
  1524. {
  1525. X509 * x509 = NULL;
  1526. EVP_PKEY * pcert = NULL;
  1527. RSA * rsa = NULL;
  1528. DWORD len = 0;
  1529. UINT iblock_size = 0, //输入块长度
  1530. oblock_size = 0; //输出块长度
  1531. UINT uMultiple = 0;//输入是块长度的倍数,用于计算输出
  1532. char OperMsg[100] = {0};
  1533. x509 = CCertKey::LoadCert((char *)pCertBuf,nCertLen,"",OperMsg);
  1534. if (x509 == NULL)
  1535. {
  1536. len = -1;
  1537. goto err;
  1538. }
  1539. pcert = X509_get_pubkey(x509);
  1540. if(pcert==NULL)
  1541. {
  1542. sprintf(OperMsg,"取得公钥密钥失败");
  1543. len = -1;
  1544. goto err;
  1545. }
  1546.     if (!(rsa = EVP_PKEY_get1_RSA(pcert)))
  1547. {
  1548. sprintf(OperMsg,"取得RSA密钥失败");
  1549. len = 0;
  1550. goto err;
  1551.     }
  1552. iblock_size = BN_num_bytes(rsa->n) - 11;//预加密长度,117
  1553. oblock_size = BN_num_bytes(rsa->n);//加密后长度,128
  1554. if(nInlen%iblock_size == 0)//正好整除
  1555. uMultiple = nInlen/iblock_size;
  1556. else
  1557. uMultiple = nInlen/iblock_size + 1;
  1558. len = (nInlen > iblock_size) ? (uMultiple * oblock_size) : oblock_size;//内存区域长度
  1559. err:
  1560. if(pcert) EVP_PKEY_free(pcert);
  1561.     if(x509) X509_free(x509);
  1562. if(rsa) RSA_free(rsa);
  1563. return len;
  1564. }
  1565. //目录部分
  1566. //功能:初始化对称加密结构
  1567. //支持目录加密
  1568. //返回值 : 成功TRUE
  1569. //    失败FALSE
  1570. //参数 : 
  1571. // strCpName - 算法名称
  1572. // strPwd - 密钥
  1573. // type - 类型 1 - 加密; 0 - 解密
  1574. // Ctx - 返回加密信息体
  1575. //调用时机: 加密前
  1576. BOOL CEvp::InitCrypt2(const CString strCpName, CString strPwd, const int type, EVP_CIPHER_CTX & Ctx)
  1577. {
  1578. const EVP_CIPHER * cipher=NULL;
  1579. unsigned char key[EVP_MAX_KEY_LENGTH]="";//算法最长的KEY长度
  1580.     unsigned char iv[EVP_MAX_IV_LENGTH]="";//算法最长的IV长度
  1581. OpenSSL_add_all_algorithms();//add digests   and ciphers
  1582. cipher = EVP_get_cipherbyname(strCpName);
  1583. if(cipher==NULL)
  1584. {
  1585. // sprintf(outMsg,"Unknown cipher name %sn",cpname);
  1586. return FALSE;
  1587. }
  1588. //表示產生的 key 是給哪一種 cipher 用的
  1589. //過程中所使用的 hash 演算法,
  1590. //用來加密的 salt,至少為八個 bytes,否則必須NULL,
  1591. //重覆幾次 hashing 的動作,愈多次愈花時間,但相對地也愈安全
  1592. if(!EVP_BytesToKey(cipher,EVP_md5(),NULL,(unsigned char *)strPwd.GetBuffer(0),
  1593. strPwd.GetLength(),1,key,iv))
  1594. {
  1595. // strcpy(outMsg,"Crypt初始化key or iv 失败");
  1596. return FALSE;
  1597. }
  1598. //EVP_CIPHER_CTX Ctx;
  1599. EVP_CIPHER_CTX_init(&Ctx);//初始化一个EVP_CIPHER_CTX结构体
  1600. //type为1,则加密;如果type为0,则解密;如果type是-1,则不改变数据
  1601. if(!EVP_CipherInit_ex(&Ctx, cipher, NULL/*NULL使用缺省的实现算法*/,key,iv,type))//初始化
  1602. {
  1603. // strcpy(outMsg,"Crypt初始化加解密结构体失败");
  1604. return FALSE;
  1605. }
  1606. EVP_cleanup();//frees all three stacks and sets their pointers to NULL ---- EVP_CIPHER
  1607. return TRUE;
  1608. }
  1609. //功能:清除对称加密结构
  1610. //调用:加密完毕后
  1611. void CEvp::CleanCrypt2(EVP_CIPHER_CTX & Ctx)
  1612. {
  1613. if(Ctx.cipher) 
  1614. EVP_CIPHER_CTX_cleanup(&Ctx); //清除所有信息释放内存
  1615. CRYPTO_cleanup_all_ex_data();
  1616. }
  1617. //返回值 : 加密时候返回加密后文件大小
  1618. //    解密时候返回解密后文件大小
  1619. //参数 : 
  1620. // pCtx - 已经初始化的加密信息体
  1621. // strFileName - 加密为要加密的文件名,解密为解密后保存的文件名
  1622. // File - 文件指针 ,具体位置的偏移有调用者负责
  1623. // dBolckLen - 块长度,块标示某个文件加密后的内容,只在解密时候有效,可以解密某个文件
  1624. //  加密时候无效,为0
  1625. // outStr - 返回错误信息
  1626. DWORD CEvp::Crypt2(EVP_CIPHER_CTX * pCtx, const CString & strFileName,
  1627. CFile & File, DWORD dBolckLen, CString & outStr)    
  1628. {
  1629. if(File.m_hFile == CFile::hFileNull)
  1630. return -1;
  1631. unsigned char inbuf[BUFLEN] = "";
  1632. unsigned char outbuf[BUFLEN + EVP_MAX_BLOCK_LENGTH] = "";//所有算法最长的块长度。
  1633. int infilelen = 0,
  1634. outlen=0;
  1635. BOOL ret = true;
  1636. DWORD dFileLen = 0;//文件长度
  1637. DWORD dFinishLen = 0;//完成长度
  1638. long lReadLen = 0; //每次读取的块长度
  1639. DWORD dReturnLen = 0;//返回加解密结果长度
  1640. CFile inSideFile;//内部文件
  1641. if(0 == dBolckLen)//块长度为0标示要加密
  1642. {
  1643. if(!inSideFile.Open(strFileName, CFile::modeRead | CFile::typeBinary))
  1644. {
  1645. outStr.Format("打开文件%s失败", strFileName);
  1646. return -1;
  1647. }
  1648. dFileLen = inSideFile.GetLength();
  1649. for(;;)
  1650. {                       
  1651. infilelen = inSideFile.Read(inbuf, BUFLEN);
  1652. if(infilelen <= 0) break;
  1653. if(!EVP_CipherUpdate(pCtx, outbuf, &outlen, inbuf, infilelen))//中間過程 
  1654. {
  1655. /* Error */              
  1656. outStr = "Crypt中间过程错误";
  1657. ret = FALSE;
  1658. goto err;
  1659. }
  1660. File.Write(outbuf, outlen);
  1661. dFinishLen += infilelen;
  1662. dReturnLen += outlen;
  1663. DrawProg(dFinishLen*HUNDRED/dFileLen);
  1664. if(!EVP_CipherFinal_ex(pCtx, outbuf, &outlen))    //最終步驟-处理最后(Final)的一段数据
  1665. {   /* Error */                       
  1666. outStr = "Crypt最终过程错误"; 
  1667. ret = FALSE;
  1668. goto err;
  1669. }               
  1670. File.Write(outbuf, outlen);
  1671. }
  1672. else //解密
  1673. {
  1674. if(!inSideFile.Open(strFileName, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary))
  1675. {
  1676. outStr.Format("创建文件%s失败", strFileName);
  1677. return -1;
  1678. }
  1679. dFileLen = dBolckLen;
  1680. for(;;)
  1681. {
  1682. //每次 iblock_size 或实际长度
  1683. lReadLen = (dBolckLen > BUFLEN) ? BUFLEN:dBolckLen;//内存区域长度
  1684. infilelen = File.Read(inbuf, lReadLen);
  1685. if(0 == infilelen)
  1686. break;
  1687. if(!EVP_CipherUpdate(pCtx, outbuf, &outlen, inbuf, infilelen))//中間過程 
  1688. {
  1689. /* Error */              
  1690. outStr = "Crypt中间过程错误";
  1691. ret = FALSE;
  1692. goto err;
  1693. }
  1694. inSideFile.Write(outbuf, outlen);
  1695. dReturnLen += outlen;
  1696. dFinishLen += infilelen;
  1697. DrawProg(dFinishLen*HUNDRED/dFileLen);
  1698. dBolckLen -= infilelen;
  1699. if(dBolckLen <= 0) break;
  1700. }
  1701. if(!EVP_CipherFinal_ex(pCtx, outbuf, &outlen))    //最終步驟-处理最后(Final)的一段数据
  1702. {   /* Error */                       
  1703. outStr = "Crypt最终过程错误"; 
  1704. ret = FALSE;
  1705. goto err;
  1706. }                
  1707. inSideFile.Write(outbuf, outlen);
  1708. }
  1709. dReturnLen += outlen;
  1710. err:
  1711. if(inSideFile.m_hFile != CFile::hFileNull )
  1712. inSideFile.Close();
  1713. if(ret)
  1714. return dReturnLen;
  1715. else return -1;
  1716. }
  1717. BOOL CEvp::InitDigest2(CString strMdName, EVP_MD_CTX & Ctx)
  1718. {
  1719. const EVP_MD *md = NULL;
  1720. if(strMdName.IsEmpty())
  1721. {
  1722. // outStr = "未指定摘要算法";
  1723. return FALSE;
  1724. }
  1725. //使EVP_Digest系列函数支持所有有效的信息摘要算法
  1726. OpenSSL_add_all_digests();
  1727.     
  1728. //根据输入的信息摘要函数的名字得到相应的EVP_MD算法结构
  1729. md = EVP_get_digestbyname(strMdName.GetBuffer(0));  
  1730. strMdName.ReleaseBuffer();
  1731. if(!md) 
  1732. {
  1733. // outStr.Format("未知摘要算法名称 %s",strMdName);
  1734. EVP_cleanup();
  1735. return FALSE;
  1736. }
  1737. //初始化信息摘要结构md_ctx。
  1738. EVP_MD_CTX_init(&Ctx);
  1739. //使用md的算法结构设置mdctx结构,impl为NULL,即使用缺省实现的算法(openssl本身提供的信息摘要算法)
  1740. if(!EVP_DigestInit_ex(&Ctx, md, NULL/*impl*/))
  1741. {
  1742. // outStr.Format("Digest初始化算法结构错误");
  1743. EVP_cleanup();
  1744. return FALSE;
  1745. }
  1746. EVP_cleanup();
  1747. return TRUE;
  1748. }
  1749. void CEvp::CleanDigest2(EVP_MD_CTX & mdCtx)
  1750. {
  1751. if(mdCtx.digest) EVP_MD_CTX_cleanup(&mdCtx);
  1752. CRYPTO_cleanup_all_ex_data();
  1753. }
  1754. /*消息摘要*/ 
  1755. //返回值:摘要后长度,-1标示失败
  1756. //参数 : strMdName - 摘要算法名称
  1757. // strFileName  - 输入文件名称
  1758. // File - 已经打开的结果文件
  1759. // outStr - 返回错误信息
  1760. DWORD CEvp::Digest2(EVP_MD_CTX * pCtx, const CString strFileName,
  1761. CFile & File, CString & outStr)
  1762. {
  1763. if(File.m_hFile == CFile::hFileNull)
  1764. return -1;
  1765. char inbuf[BUFLEN] = "";
  1766. UINT len = 0;
  1767. BOOL ret = true;
  1768. EVP_MD_CTX md_ctx;
  1769. memset(&md_ctx,0,sizeof(md_ctx));
  1770. FILE * infd = NULL;
  1771. long fileLen = 0;//文件长度
  1772. long finishLen = 0;//完成长度
  1773. unsigned char md_value[MAX_MD_SIZE]="";
  1774. UINT md_len = 0;/*摘要长度*/
  1775. if(strFileName.IsEmpty())
  1776. {
  1777. outStr = "未指定输入文件";
  1778. return -1;
  1779. }
  1780. CFile inSideFile;//内部文件
  1781. if(!inSideFile.Open(strFileName, CFile::modeRead | CFile::typeBinary))
  1782. {
  1783. outStr = "不能打开指定文件";
  1784. return -1;
  1785. }
  1786. for(;;)
  1787. {
  1788. len = fread(inbuf, 1, BUFLEN, infd);
  1789. if(len <= 0) break;          
  1790. if(!EVP_DigestUpdate(&md_ctx, inbuf, len))
  1791. {
  1792. outStr.Format("Digest中间过程错误");
  1793. ret=FALSE;
  1794. goto err;
  1795. }
  1796. finishLen+=len;
  1797. DrawProg(finishLen * HUNDRED / fileLen);
  1798. }
  1799. //完成信息摘要计算过程,将完成的摘要信息存储在md_value里面,长度信息存储在md_len里面
  1800. if(!EVP_DigestFinal_ex(&md_ctx, md_value, &md_len))
  1801. {
  1802. outStr.Format("Digest最终过程错误");
  1803. ret=FALSE;
  1804. }
  1805. err:
  1806. //使用该函数释放mdctx占用的资源,如果使用_ex系列函数,这是必须调用的。
  1807. if(ret)
  1808. {
  1809. //记录文件
  1810. File.Write(md_value, md_len);
  1811. return md_len;
  1812. }
  1813. else
  1814. return -1;
  1815. }
  1816. BOOL CEvp::VerifyDigest2(EVP_MD_CTX * mdCtx, const CString strFileName,
  1817. CFile & File, DWORD dBolckLen, CString & outStr)
  1818. {
  1819. if(File.m_hFile == CFile::hFileNull)
  1820. return -1;
  1821. char inbuf[BUFLEN] = "";
  1822. UINT len = 0;
  1823. BOOL ret = true;
  1824. EVP_MD_CTX md_ctx;
  1825. memset(&md_ctx,0,sizeof(md_ctx));
  1826. FILE * infd = NULL;
  1827. long fileLen = 0;//文件长度
  1828. long finishLen = 0;//完成长度
  1829. unsigned char md_value[MAX_MD_SIZE]="";
  1830. UINT md_len = 0;/*摘要长度*/
  1831. if(strFileName.IsEmpty())
  1832. {
  1833. outStr = "未指定输入文件";
  1834. return FALSE;
  1835. }
  1836. CFile inSideFile;//内部文件
  1837. if(!inSideFile.Open(strFileName, CFile::modeRead | CFile::typeBinary))
  1838. {
  1839. outStr.Format("文件%s丢失", strFileName);
  1840. return FALSE;
  1841. }
  1842. for(;;)
  1843. {
  1844. len = fread(inbuf, 1, BUFLEN, infd);
  1845. if(len <= 0) break;          
  1846. if(!EVP_DigestUpdate(&md_ctx, inbuf, len))
  1847. {
  1848. outStr.Format("Digest中间过程错误");
  1849. ret=FALSE;
  1850. goto err;
  1851. }
  1852. finishLen+=len;
  1853. DrawProg(finishLen * HUNDRED / fileLen);
  1854. }
  1855. //完成信息摘要计算过程,将完成的摘要信息存储在md_value里面,长度信息存储在md_len里面
  1856. if(!EVP_DigestFinal_ex(&md_ctx, md_value, &md_len))
  1857. {
  1858. outStr.Format("Digest最终过程错误");
  1859. ret=FALSE;
  1860. }
  1861. err:
  1862. //使用该函数释放mdctx占用的资源,如果使用_ex系列函数,这是必须调用的。
  1863. if(ret)
  1864. {
  1865. //比较文件摘要与结果是否相同
  1866. if(md_len != dBolckLen)
  1867. {
  1868. outStr.Format("摘要校验错误");
  1869. ret=FALSE;
  1870. }
  1871. else
  1872. {
  1873. char * pmdbuf = new char[dBolckLen + 1];
  1874. File.Read(pmdbuf, dBolckLen);
  1875. if(memcmp(pmdbuf, md_value, dBolckLen) == 0)
  1876. {
  1877. outStr.Format("摘要校验正确");
  1878. ret=TRUE;
  1879. }
  1880. else
  1881. {
  1882. outStr.Format("摘要校验错误");
  1883. ret=FALSE;
  1884. }
  1885. delete [] pmdbuf;
  1886. }
  1887. }
  1888. return ret;
  1889. }
  1890. BOOL CEvp::InitSeal2(stuCertLink * pCERT, const CString strCpName,
  1891.   CFile & File, EVP_CIPHER_CTX & eCtx, CString & outStr)
  1892. {
  1893. //对随机数播种(seeded)。
  1894. UCHAR iv[EVP_MAX_IV_LENGTH]="";
  1895. UCHAR * ekey [128]; 
  1896. EVP_PKEY * pubKey[128];
  1897. int ekeylen[128];
  1898. int index = 0;
  1899. const EVP_CIPHER *cipher=NULL;
  1900. BOOL ret=true;
  1901.  // DWORD fileLen=0;//文件长度
  1902. // DWORD finishLen=0;//完成长度
  1903. UINT uCrc16 = 0; //加密后重要信息CRC码
  1904. DWORD dOutLen = 0;//内存文件长度
  1905. BYTE * pOut = NULL; //内存文件缓冲区
  1906. DWORD dFileInfoLen = 0;
  1907. //加载加密公钥
  1908. HRSRC hRsrc = FindResource(NULL,MAKEINTRESOURCE(IDR_FILE_CERT),"CERT");
  1909. DWORD lenCert = SizeofResource(NULL, hRsrc); 
  1910. HGLOBAL hgCert = LoadResource(NULL,hRsrc);
  1911. LPSTR lpCert = (LPSTR)LockResource(hgCert);
  1912. CMemFile MemFile; //用于存放重要信息的内存文件
  1913. DWORD dInLen = 0;
  1914. BYTE * pIn = NULL; //用于MemFile.Dectch();
  1915. // fileLen = filelength(fileno(infd));//得到文件长度
  1916. OpenSSL_add_all_algorithms();
  1917. int nCountCert = 0; //证书个数
  1918. for(stuCertLink * temp = pCERT; temp != NULL; temp=temp->Link, nCountCert++)
  1919. {
  1920. X509 * pX509 = NULL;
  1921. pX509 = CCertKey::LoadCert(temp->pCert, temp->CertLen, NULL, outStr.GetBuffer(255));
  1922. outStr.ReleaseBuffer();
  1923.     if(pX509)
  1924. {
  1925. pubKey[nCountCert] = X509_get_pubkey(pX509);
  1926. if (pubKey[nCountCert] == NULL)
  1927. {
  1928. outStr = "Read Public Key Failed!";
  1929. ret=false;
  1930. goto err;
  1931. }
  1932. ekey[nCountCert] = new unsigned char[EVP_PKEY_size(pubKey[nCountCert])];
  1933. X509_free(pX509);
  1934. }
  1935. else
  1936. {
  1937. outStr.Format("加载第 %d 个证书 %s 失败", nCountCert+1, temp->pCert);
  1938. ret = false;
  1939. goto err;
  1940. }
  1941. }
  1942. cipher = EVP_get_cipherbyname(strCpName);
  1943. if(cipher==NULL)
  1944. {
  1945. outStr.Format("Unknown cipher name %sn",strCpName);
  1946. ret=false;
  1947. goto err;
  1948. }
  1949. if(!EVP_SealInit(&eCtx,cipher,
  1950. ekey,
  1951. ekeylen,//存放所有 ek 長度
  1952. iv,//自动生成
  1953. pubKey,//加密 ek 用的 public key(s)
  1954. nCountCert))
  1955. {
  1956. ret=false;
  1957. goto err;
  1958. }
  1959. MemFile.Write(&nCountCert, sizeof(int)); //1 - 写入公钥个数
  1960. for(index = 0; index < nCountCert; index++)
  1961. {
  1962. MemFile.Write(&ekeylen[index], sizeof(int));
  1963. MemFile.Write(ekey[index], ekeylen[index]);
  1964. }
  1965. MemFile.Write(iv, sizeof(iv));
  1966. //构造加密结果 长度+1 内存
  1967. dFileInfoLen = CEvp::GetEncLen(lpCert, lenCert, MemFile.GetLength());
  1968. dOutLen = dFileInfoLen + 1;
  1969. pOut = new BYTE[dOutLen];
  1970. dInLen = MemFile.GetLength();
  1971. pIn = MemFile.Detach();
  1972. //加密重要信息
  1973. if(!CEvp::RSAPubEnc((BYTE *)lpCert, lenCert, "", pIn, 
  1974. dInLen, pOut, dOutLen, outStr.GetBuffer(255)))
  1975. {
  1976. //加密失败
  1977. ret=false;
  1978. goto err;
  1979. }
  1980. //得到加密后长度的CRC校验
  1981. if(!CRC::GetCrc16((char*)&dOutLen, sizeof(DWORD), uCrc16))
  1982. {
  1983. //加密失败
  1984. ret=false;
  1985. goto err;
  1986. }
  1987. //写入加密后重要信息长度和CRC校验和加密后重要信息内容
  1988. File.Write(&dOutLen, sizeof(DWORD));
  1989. File.Write(&uCrc16, sizeof(UINT));
  1990. File.Write(pOut, dOutLen);
  1991. err:
  1992. outStr.ReleaseBuffer();
  1993. free(pIn);
  1994. delete [] pOut;
  1995. for(int i = 0;i< nCountCert;i++)
  1996. {
  1997. if(pubKey[i]) EVP_PKEY_free(pubKey[i]);
  1998. if(ekey[i]) delete [] ekey[i];
  1999. }
  2000. //if(eCtx.cipher) EVP_CIPHER_CTX_cleanup(&eCtx);
  2001. EVP_cleanup();
  2002. return ret;
  2003. }
  2004. void CEvp::CleanSeal2(EVP_CIPHER_CTX & sealCtx)
  2005. {
  2006. if(sealCtx.cipher) 
  2007. EVP_CIPHER_CTX_cleanup(&sealCtx); //清除所有信息释放内存
  2008. EVP_cleanup();
  2009. CRYPTO_cleanup_all_ex_data();
  2010. }
  2011. DWORD CEvp::Seal2(EVP_CIPHER_CTX * pCtx,const CString strFileName, CFile & File, CString & outStr)
  2012. {
  2013. int readlen = 0;
  2014. int ebuflen = 0;
  2015. UCHAR buf[BUFLEN]="";
  2016. UCHAR ebuf[BUFLEN + EVP_MAX_BLOCK_LENGTH]="";
  2017. BOOL ret = TRUE;
  2018. DWORD finishLen = 0;
  2019. CFile inSideFile;//内部文件
  2020. DWORD dProgLen = 0; //总共需要加密的长度
  2021. DWORD dProgFinshLen = 0;//已经加密的长度
  2022. if(!inSideFile.Open(strFileName, CFile::modeRead | CFile::typeBinary))
  2023. {
  2024. outStr = "不能打开指定文件";
  2025. return -1;
  2026. }
  2027. dProgLen = inSideFile.GetLength();
  2028. for(;;)
  2029. {
  2030. readlen = inSideFile.Read(buf, sizeof(buf));
  2031. if (readlen <= 0)
  2032. {
  2033. break;
  2034. }
  2035. if(!EVP_SealUpdate(pCtx, ebuf, &ebuflen, buf, readlen))
  2036. {
  2037. outStr = "中间过程出错";
  2038. ret=false;
  2039. goto err;
  2040. }
  2041. File.Write(ebuf, ebuflen);
  2042. finishLen += ebuflen;
  2043. dProgFinshLen += readlen;
  2044. DrawProg(dProgFinshLen*HUNDRED/dProgLen);
  2045. }
  2046. if(!EVP_SealFinal(pCtx, ebuf, &ebuflen))
  2047. {
  2048. outStr = "最终过程出错";
  2049. ret = false;
  2050. goto err;
  2051. }
  2052. File.Write(ebuf, ebuflen);
  2053. finishLen += ebuflen;
  2054. err:
  2055. inSideFile.Close();
  2056. if(ret)
  2057. return finishLen;
  2058. else
  2059. return ret;
  2060. }
  2061. BOOL CEvp::InitOpenSeal2(char * key, int keylen, char * pwd, const CString strCpName,
  2062.   CFile & File, EVP_CIPHER_CTX & eCtx, CString & outStr)
  2063. {
  2064. if(File.m_hFile == CFile::hFileNull)
  2065. return FALSE;
  2066. unsigned char iv[EVP_MAX_IV_LENGTH]="";
  2067. const EVP_CIPHER *cipher=NULL;
  2068. int ebuflen=0,readlen=0;
  2069. bool ret=true;
  2070. int nCountCert = 0; //公钥个数
  2071. int index = 0;
  2072. UCHAR * ekey [128] = {0}; 
  2073. int ekeylen[128];
  2074. BOOL bInit = FALSE;//是否初始化成功
  2075. DWORD dFileInfoLen = 0;//加密后重要信息长度
  2076. UINT uCrc16 = 0; //加密后重要信息CRC码
  2077. EVP_PKEY * pkey=NULL;
  2078. CMemFile MemFile;
  2079. HRSRC hRsrc = FindResource(NULL,MAKEINTRESOURCE(IDR_FILE_KEY),"CERT");
  2080. DWORD lenKey = SizeofResource(NULL, hRsrc); 
  2081. HGLOBAL hgKey = LoadResource(NULL,hRsrc);
  2082. LPSTR lpKey = (LPSTR)LockResource(hgKey);
  2083. BYTE * pIn = NULL;
  2084. BYTE * pOut = NULL;
  2085. DWORD dOutLen = 0;
  2086. OpenSSL_add_all_algorithms();//digests   and ciphers
  2087. /* Read private key */
  2088. pkey = CCertKey::LoadKey(key,keylen,pwd,outStr.GetBuffer(255));
  2089. outStr.ReleaseBuffer();
  2090. if (pkey == NULL)
  2091. ret = false;
  2092. goto err;
  2093. }
  2094. //得到重要信息长度和CRC校验码
  2095. readlen = File.Read(&dFileInfoLen, sizeof(DWORD));
  2096. // finishLen += readlen;
  2097. readlen = File.Read(&uCrc16, sizeof(UINT));
  2098. // finishLen += readlen;
  2099. if(!CRC::CheckCrc((char *)&dFileInfoLen, sizeof(DWORD), uCrc16))
  2100. {
  2101. outStr = "文件头CRC校验错误";
  2102. ret = false;
  2103. goto err;
  2104. }
  2105. //开辟缓冲区,容纳加密后的重要文件信息
  2106. pIn = new BYTE[dFileInfoLen + 1];
  2107. dOutLen = dFileInfoLen;
  2108. readlen = File.Read(pIn, dFileInfoLen);
  2109. // finishLen += readlen;
  2110. //开辟缓冲区,容纳加密后的信息体
  2111. pOut = new BYTE[dOutLen];
  2112. if(!CEvp::RSAPrivDec((BYTE *)lpKey, lenKey, "", pIn, 
  2113. dFileInfoLen, pOut, dOutLen, outStr.GetBuffer(255)))
  2114. {
  2115. //解密失败
  2116. outStr.ReleaseBuffer();
  2117. outStr = "重要信息解密失败";
  2118. ret = false;
  2119. goto err;
  2120. }
  2121. outStr.ReleaseBuffer();
  2122. MemFile.Attach(pOut, dOutLen);
  2123. //首先是公钥个数
  2124. MemFile.Read(&nCountCert, sizeof(int));
  2125. for(index = 0; index < nCountCert; index++)
  2126. {
  2127. MemFile.Read(&ekeylen[index], sizeof(int));
  2128. ekey[index] = new unsigned char[ekeylen[index]];
  2129. MemFile.Read(ekey[index], ekeylen[index]);
  2130. }
  2131. MemFile.Read(iv, sizeof(iv));
  2132. MemFile.Close();
  2133. //输入文件已经偏移到加密后的文件
  2134. cipher = EVP_get_cipherbyname(strCpName);
  2135. if(cipher == NULL)
  2136. {
  2137. outStr.Format("Unknown cipher name %sn",strCpName);
  2138. ret = false;
  2139. goto err;
  2140. }
  2141. for(index = 0; index<nCountCert; index++)
  2142. {
  2143. if (ekeylen[index] != EVP_PKEY_size(pkey))
  2144. {
  2145. continue;
  2146. }
  2147. if(EVP_OpenInit(&eCtx,cipher, ekey[index],ekeylen[index],iv,pkey))
  2148. {
  2149. bInit = TRUE;
  2150. break;
  2151. }
  2152. }
  2153. if(!bInit)
  2154. {
  2155. outStr = "指定证书不能解密文件,请确认证书合法性";
  2156. ret=false;
  2157. goto err;
  2158. }
  2159. err:
  2160. delete [] pIn;
  2161. delete [] pOut;
  2162. for(int i = 0;i< nCountCert;i++)
  2163. {
  2164. if(ekey[i]) delete ekey[i];
  2165. }
  2166. if(pkey) EVP_PKEY_free(pkey);
  2167. EVP_cleanup();
  2168. return ret;
  2169. }
  2170. DWORD CEvp::OpenSeal2(EVP_CIPHER_CTX & eCtx, CFile & File, DWORD dBolckLen, const CString strFileName, CString & outStr)
  2171. {
  2172. unsigned char buf[BUFLEN]="";
  2173. unsigned char ebuf[BUFLEN + EVP_MAX_BLOCK_LENGTH]="";
  2174. int ebuflen = 0,
  2175. readlen = 0,
  2176. fileLen = 0,
  2177. finishLen = 0;
  2178. bool ret=true;
  2179. DWORD dProgLen = dBolckLen; //总共需要处理的长度
  2180. DWORD dProgFinshLen = 0;//已经处理的长度
  2181. CFile inSideFile;//内部文件
  2182. if(!inSideFile.Open(strFileName, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary))
  2183. {
  2184. outStr.Format("创建文件%s错误", strFileName);
  2185. return -1;
  2186. }
  2187. for(;;)
  2188. {
  2189. //每次 iblock_size 或实际长度
  2190. fileLen = (dBolckLen > BUFLEN) ? BUFLEN:dBolckLen;//内存区域长度
  2191. readlen = File.Read(buf, fileLen);
  2192. if(readlen == 0)//可能加密时文件长度为0
  2193. break;
  2194. if(!EVP_OpenUpdate(&eCtx, ebuf, &ebuflen, buf, readlen))
  2195. {
  2196. outStr = "中间过程错误";
  2197. ret=false;
  2198. goto err;
  2199. }
  2200. inSideFile.Write(ebuf, ebuflen);
  2201. finishLen += ebuflen;
  2202. dBolckLen -= fileLen;
  2203. dProgFinshLen += readlen;
  2204. DrawProg(dProgFinshLen*HUNDRED/dProgLen);
  2205. if(dBolckLen <= 0) break;
  2206. }
  2207. //DrawProg(finishLen*HUNDRED/fileLen);
  2208. if(!EVP_OpenFinal(&eCtx, ebuf, &ebuflen))
  2209. {
  2210. outStr = "最终过程错误";
  2211. ret=false;
  2212. goto err;
  2213. }
  2214. inSideFile.Write(ebuf, ebuflen);
  2215. finishLen += ebuflen;
  2216. err:
  2217. inSideFile.Close();
  2218. if(ret)
  2219. return finishLen;
  2220. else
  2221. return -1;
  2222. }
  2223. void CEvp::CleanOpenSeal2(EVP_CIPHER_CTX & eCtx)
  2224. {
  2225. if(eCtx.cipher) 
  2226. EVP_CIPHER_CTX_cleanup(&eCtx); //清除所有信息释放内存
  2227. EVP_cleanup();
  2228. CRYPTO_cleanup_all_ex_data();
  2229. }
  2230. BOOL CEvp::GetPubRsa(const BYTE * pCertBuf/*[in]公钥*/, const UINT nCertLen/*[in]公钥长度*/, RSA *& pRsa)
  2231. {
  2232. X509 * x509 = NULL;
  2233. EVP_PKEY * pcert = NULL;
  2234. CString outStr;
  2235. BOOL ret = TRUE;
  2236. x509 = CCertKey::LoadCert((char *)pCertBuf, nCertLen, "", outStr.GetBuffer(255));
  2237. outStr.ReleaseBuffer();
  2238. if (x509 == NULL)
  2239. {
  2240. ret = FALSE;
  2241. goto err;
  2242. }
  2243. pcert = X509_get_pubkey(x509);
  2244. if(pcert==NULL)
  2245. {
  2246. outStr = "取得公钥密钥失败";
  2247. ret = FALSE;
  2248. goto err;
  2249. }
  2250.     if (!(pRsa = EVP_PKEY_get1_RSA(pcert)))
  2251. {
  2252. outStr = "取得RSA密钥失败";
  2253. ret=FALSE;
  2254. goto err;
  2255.     }
  2256. err:
  2257. if(pcert) EVP_PKEY_free(pcert);
  2258.     if(x509) X509_free(x509);
  2259. return ret;
  2260. }
  2261. BOOL CEvp::GetPrivRsa(const BYTE * pKeyBuf/*[in]私钥*/,const UINT nKeyLen/*[in]私钥长度*/,
  2262. const char * pPwd/*[in]私钥密码*/, RSA *& pRsa)
  2263. {
  2264. EVP_PKEY * pkey = NULL;
  2265. CString outStr;
  2266. pkey = CCertKey::LoadKey((char *)pKeyBuf,nKeyLen,(char *)pPwd,outStr.GetBuffer(255));
  2267. outStr.ReleaseBuffer();
  2268. BOOL ret = TRUE;
  2269. if (pkey == NULL)
  2270. outStr = "取得私钥密钥失败";
  2271. ret=FALSE;
  2272. goto err;
  2273. }
  2274.     if (!(pRsa = EVP_PKEY_get1_RSA(pkey)))
  2275. {
  2276. outStr = "取得RSA密钥失败";
  2277. ret=FALSE;
  2278. goto err;
  2279.     }
  2280. err:
  2281. if(pkey) EVP_PKEY_free(pkey);
  2282. return ret;
  2283. }
  2284. void CEvp::FreeRsa(RSA *& pRsa)
  2285. {
  2286. if(pRsa) RSA_free(pRsa);
  2287. CRYPTO_cleanup_all_ex_data();
  2288. }
  2289. //公钥加密
  2290. DWORD CEvp::RSAPubEnc2(RSA * pRsa, const CString strFileName, CFile & File, CString & outStr)
  2291. {
  2292. if(pRsa == NULL)
  2293. {
  2294. outStr = "RSA非法";
  2295. return -1;
  2296. }
  2297. UINT iblock_size = 0, //输入块长度
  2298.  oblock_size = 0; //输出块长度
  2299. unsigned char * bufin=NULL,
  2300.   * bufout=NULL;
  2301. int inlen = 0,
  2302. outlen = 0;
  2303. DWORD dProgLen = 0; //总共需要处理的长度
  2304. DWORD dProgFinshLen = 0;//已经处理的长度
  2305. BOOL ret = TRUE;
  2306. long fileLen = 0;//文件长度
  2307. long finishLen = 0;//完成长度
  2308. DWORD returnLen = 0;//最后返回文件加密后长度
  2309. CFile inSideFile;//内部文件
  2310. if(!inSideFile.Open(strFileName, CFile::modeRead | CFile::typeBinary))
  2311. {
  2312. outStr = "不能打开指定文件";
  2313. return -1;
  2314. }
  2315. dProgLen = inSideFile.GetLength();
  2316. iblock_size = BN_num_bytes(pRsa->n) - 11;//预加密长度,117
  2317. oblock_size = BN_num_bytes(pRsa->n);//加密后长度,128
  2318. bufin = new unsigned char[iblock_size];
  2319. memset(bufin,0,iblock_size);
  2320. bufout = new unsigned char[oblock_size];
  2321. memset(bufout,0,oblock_size);
  2322. for(;;)
  2323. {
  2324. inlen = inSideFile.Read(bufin, iblock_size);
  2325. if(!inlen)
  2326. break;
  2327. outlen = RSA_public_encrypt(inlen,bufin,bufout,pRsa,RSA_PKCS1_PADDING);
  2328. if (outlen == -1)//加密后资料长度
  2329. {
  2330. outStr = "RSA加密失败";
  2331. ret=FALSE;
  2332. goto err;
  2333. }
  2334. File.Write(bufout, outlen);
  2335. returnLen += outlen;
  2336. memset(bufout,0,oblock_size);
  2337. dProgFinshLen += inlen;
  2338. DrawProg(dProgFinshLen*HUNDRED/dProgLen);
  2339. }
  2340. err:
  2341. inSideFile.Close();
  2342. // if(pRsa) RSA_free(pRsa);
  2343. delete [] bufin;
  2344. delete [] bufout;
  2345. if(!ret)
  2346. return -1;
  2347. else
  2348. return returnLen;
  2349. }
  2350. //私钥解密
  2351. DWORD CEvp::RSAPrivDec2(RSA * pRsa, CFile & File, DWORD dBolckLen, const CString strFileName, CString & outStr)
  2352. {
  2353. if(pRsa == NULL)
  2354. {
  2355. outStr = "RSA非法";
  2356. return -1;
  2357. }
  2358. unsigned char * bufin = NULL,
  2359.   * bufout = NULL;
  2360. DWORD dReturnLen = 0;
  2361. UINT iblock_size = 0,
  2362. oblock_size = 0,
  2363. outlen = 0,
  2364. inlen = 0,
  2365. readlen = 0;
  2366. BOOL ret = true;
  2367. long fileLen = 0;//文件长度
  2368. long finishLen = 0;//完成长度
  2369. DWORD dProgLen = dBolckLen; //总共需要处理的长度
  2370. DWORD dProgFinshLen = 0;//已经处理的长度
  2371. CFile inSideFile;//内部文件
  2372. if(!inSideFile.Open(strFileName, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary))
  2373. return -1;
  2374. iblock_size = BN_num_bytes(pRsa->n);//预接密长度 128
  2375. oblock_size = BN_num_bytes(pRsa->n) - 11;//杰密后长度 117
  2376. bufin=new unsigned char[iblock_size];
  2377. bufout=new unsigned char[oblock_size];
  2378. for(;;)
  2379. {
  2380. //每次 iblock_size 或实际长度
  2381. readlen = (dBolckLen > iblock_size) ? iblock_size:dBolckLen;//内存区域长度
  2382. inlen = File.Read(bufin, readlen);
  2383. if(inlen == 0)//可能加密时文件长度为0
  2384. break;
  2385. outlen = RSA_private_decrypt(inlen,bufin,bufout,pRsa,RSA_PKCS1_PADDING);
  2386. if (outlen == -1)//加密后资料长度
  2387. {
  2388. outStr = "RSA解密失败";
  2389. ret=FALSE;
  2390. goto err;
  2391. }
  2392. inSideFile.Write(bufout, outlen);
  2393. dReturnLen += outlen;
  2394. memset(bufout,0,oblock_size);
  2395. dBolckLen -= inlen;
  2396. if(dBolckLen <= 0) break;
  2397. dProgFinshLen += inlen;
  2398. DrawProg(dProgFinshLen*HUNDRED/dProgLen);
  2399. }
  2400. err:
  2401. inSideFile.Close();
  2402. // if(pRsa) RSA_free(pRsa);
  2403. delete [] bufin;
  2404. delete [] bufout;
  2405. if(!ret)
  2406. return -1;
  2407. else return dReturnLen;
  2408. }
  2409. DWORD CEvp::RSAPrivEnc2(RSA * pRsa, const CString strFileName, CFile & File, CString & outStr)
  2410. {
  2411. if(pRsa == NULL)
  2412. {
  2413. outStr = "RSA非法";
  2414. return -1;
  2415. }
  2416. UINT iblock_size = 0, //输入块长度
  2417.  oblock_size = 0; //输出块长度
  2418. unsigned char * bufin=NULL,
  2419.   * bufout=NULL;
  2420. int inlen = 0,
  2421. outlen = 0;
  2422. BOOL ret = TRUE;
  2423. long fileLen = 0;//文件长度
  2424. long finishLen = 0;//完成长度
  2425. DWORD returnLen = 0;//最后返回文件加密后长度
  2426. DWORD dProgLen = 0; //总共需要处理的长度
  2427. DWORD dProgFinshLen = 0;//已经处理的长度
  2428. CFile inSideFile;//内部文件
  2429. if(!inSideFile.Open(strFileName, CFile::modeRead | CFile::typeBinary))
  2430. {
  2431. outStr = "不能打开指定文件";
  2432. return -1;
  2433. }
  2434. dProgLen = inSideFile.GetLength();
  2435. iblock_size = BN_num_bytes(pRsa->n) - 11;//预加密长度,117
  2436. oblock_size = BN_num_bytes(pRsa->n);//加密后长度,128
  2437. bufin = new unsigned char[iblock_size];
  2438. memset(bufin,0,iblock_size);
  2439. bufout = new unsigned char[oblock_size];
  2440. memset(bufout,0,oblock_size);
  2441. for(;;)
  2442. {
  2443. inlen = inSideFile.Read(bufin, iblock_size);
  2444. if(!inlen)
  2445. break;
  2446. outlen = RSA_private_encrypt(inlen,bufin,bufout,pRsa,RSA_PKCS1_PADDING);
  2447. if (outlen == -1)//加密后资料长度
  2448. {
  2449. outStr = "RSA加密失败";
  2450. ret=FALSE;
  2451. goto err;
  2452. }
  2453. File.Write(bufout, outlen);
  2454. returnLen += outlen;
  2455. memset(bufout,0,oblock_size);
  2456. dProgFinshLen += inlen;
  2457. DrawProg(dProgFinshLen*HUNDRED/dProgLen);
  2458. }
  2459. err:
  2460. inSideFile.Close();
  2461. // if(pRsa) RSA_free(pRsa);
  2462. delete [] bufin;
  2463. delete [] bufout;
  2464. if(!ret)
  2465. return -1;
  2466. else
  2467. return returnLen;
  2468. }
  2469. DWORD CEvp::RSAPubDec2(RSA * pRsa, CFile & File, DWORD dBolckLen, const CString strFileName, CString & outStr)
  2470. {
  2471. if(pRsa == NULL)
  2472. {
  2473. outStr = "RSA非法";
  2474. return -1;
  2475. }
  2476. unsigned char * bufin = NULL,
  2477.   * bufout = NULL;
  2478. DWORD dReturnLen = 0;
  2479. UINT iblock_size = 0,
  2480. oblock_size = 0,
  2481. outlen = 0,
  2482. inlen = 0,
  2483. readlen = 0;
  2484. BOOL ret = true;
  2485. long fileLen = 0;//文件长度
  2486. long finishLen = 0;//完成长度
  2487. DWORD dProgLen = dBolckLen; //总共需要处理的长度
  2488. DWORD dProgFinshLen = 0;//已经处理的长度
  2489. CFile inSideFile;//内部文件
  2490. if(!inSideFile.Open(strFileName, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary))
  2491. return -1;
  2492. iblock_size = BN_num_bytes(pRsa->n);//预接密长度 128
  2493. oblock_size = BN_num_bytes(pRsa->n) - 11;//杰密后长度 117
  2494. bufin=new unsigned char[iblock_size];
  2495. bufout=new unsigned char[oblock_size];
  2496. for(;;)
  2497. {
  2498. //每次 iblock_size 或实际长度
  2499. readlen = (dBolckLen > iblock_size) ? iblock_size:dBolckLen;//内存区域长度
  2500. inlen = File.Read(bufin, readlen);
  2501. if(inlen == 0)//可能加密时文件长度为0
  2502. break;
  2503. outlen = RSA_public_decrypt(inlen,bufin,bufout,pRsa,RSA_PKCS1_PADDING);
  2504. if (outlen == -1)//加密后资料长度
  2505. {
  2506. outStr = "RSA解密失败";
  2507. ret=FALSE;
  2508. goto err;
  2509. }
  2510. inSideFile.Write(bufout, outlen);
  2511. dReturnLen += outlen;
  2512. memset(bufout,0,oblock_size);
  2513. dBolckLen -= inlen;
  2514. if(dBolckLen <= 0) break;
  2515. dProgFinshLen += inlen;
  2516. DrawProg(dProgFinshLen*HUNDRED/dProgLen);
  2517. }
  2518. err:
  2519. inSideFile.Close();
  2520. // if(pRsa) RSA_free(pRsa);
  2521. delete [] bufin;
  2522. delete [] bufout;
  2523. if(!ret)
  2524. return -1;
  2525. else return dReturnLen;
  2526. }
  2527. /*数字签名*/
  2528. //功能:初始化对称加密结构
  2529. //支持目录加密
  2530. //返回值 : 成功TRUE
  2531. //    失败FALSE
  2532. //参数 : 
  2533. // strCpName - 算法名称
  2534. // strPwd - 密钥
  2535. // type - 类型 1 - 加密; 0 - 解密
  2536. // Ctx - 返回加密信息体
  2537. //调用时机: 加密前
  2538. BOOL CEvp::InitSign2(CString strMdName, EVP_MD_CTX & md_Ctx, const char * key/*签名时候用私钥,验证时候用公钥*/,
  2539.   const int keylen, const char * pwd/*私钥密码,为空时候标示输入为公钥*/, X509 *& x509, EVP_PKEY *& pkey)
  2540. {
  2541. const EVP_MD *md = NULL;
  2542. if(strMdName.IsEmpty())
  2543. {
  2544. // outStr = "未指定摘要算法";
  2545. return FALSE;
  2546. }
  2547. char outMsg[100] = {0};
  2548. if(pwd != NULL && strlen(pwd) != 0)
  2549. {
  2550. pkey = CCertKey::LoadKey((char *)key,keylen,(char *)pwd,outMsg);
  2551. if (pkey == NULL)
  2552. return FALSE;
  2553. }
  2554. }
  2555. else
  2556. {
  2557. x509 = CCertKey::LoadCert((char *)key,keylen,(char *)pwd,outMsg);
  2558. if (x509 == NULL)
  2559. {
  2560. return FALSE;
  2561. }
  2562. pkey = X509_get_pubkey(x509);
  2563. if (pkey == NULL)
  2564. {
  2565. return FALSE;
  2566. }
  2567. }
  2568. //使EVP_Digest系列函数支持所有有效的信息摘要算法
  2569. OpenSSL_add_all_digests();
  2570.    
  2571. //根据输入的信息摘要函数的名字得到相应的EVP_MD算法结构
  2572. md = EVP_get_digestbyname(strMdName.GetBuffer(0));  
  2573. strMdName.ReleaseBuffer();
  2574. if(!md) 
  2575. {
  2576. // outStr.Format("未知摘要算法名称 %s",strMdName);
  2577. EVP_cleanup();
  2578. return FALSE;
  2579. }
  2580. //初始化信息摘要结构md_ctx。
  2581. EVP_MD_CTX_init(&md_Ctx);
  2582. if(!EVP_SignInit_ex(&md_Ctx,md,NULL))
  2583. {
  2584. EVP_cleanup();
  2585. return FALSE;
  2586. }
  2587. EVP_cleanup();
  2588. return TRUE;
  2589. }
  2590. //功能:清除对称加密结构
  2591. //调用:加密完毕后
  2592. void CEvp::CleanSign2(EVP_MD_CTX & md_Ctx, X509 *& px509, EVP_PKEY *& pkey)
  2593. {
  2594. if(md_Ctx.digest) 
  2595. EVP_MD_CTX_cleanup(&md_Ctx);
  2596. if(px509) X509_free(px509);
  2597. if(pkey) EVP_PKEY_free (pkey);
  2598. EVP_cleanup();
  2599. CRYPTO_cleanup_all_ex_data();
  2600. // CRYPTO_mem_leaks(bio_err);
  2601. }
  2602. DWORD CEvp::Sign2(EVP_MD_CTX * pCtx,
  2603.   EVP_PKEY *& pkey,
  2604.   const CString strFileName,
  2605.   CFile & File, CString & outStr)
  2606. {
  2607. BOOL ret=true;
  2608. unsigned char * sig_buf=NULL;
  2609. unsigned int sig_len,len=0;
  2610. unsigned char inbuf[BUFLEN]="";
  2611. CFile inSideFile;//内部文件
  2612. long fileLen=0;//文件长度
  2613. long finishLen=0;//完成长度
  2614. if(pCtx == NULL)
  2615. {
  2616. outStr = "未初始化加密结构";
  2617. return -1;
  2618. }
  2619. if(pkey == NULL)
  2620. {
  2621. outStr = "私钥非法";
  2622. return -1;
  2623. }
  2624. /* Do the signature */
  2625. if(!inSideFile.Open(strFileName, CFile::modeRead | CFile::typeBinary))
  2626. {
  2627. outStr = "不能打开指定文件";
  2628. return -1;
  2629. }
  2630. for(;;)
  2631. {
  2632. len = inSideFile.Read(inbuf, BUFLEN);
  2633. if(len <= 0) break;
  2634. if(!EVP_SignUpdate(pCtx, inbuf, len))
  2635. {
  2636. outStr = "中间过程出错";
  2637. ret=FALSE;
  2638. goto err;
  2639. }
  2640. finishLen+=len;
  2641. DrawProg(finishLen*HUNDRED/fileLen);
  2642. }
  2643. sig_len = EVP_PKEY_size(pkey);
  2644. sig_buf = new unsigned char[sig_len];
  2645. // 簽名後的結果,必須是個夠大視 private key 長度不同而不同,可以 EVP_PKEY_size() 取得
  2646. if(!EVP_SignFinal (pCtx, sig_buf, &sig_len, pkey))
  2647. {
  2648. outStr = "最终过程出错";
  2649. ret = FALSE;
  2650. }
  2651. File.Write(sig_buf, sig_len);
  2652. err:
  2653. inSideFile.Close();
  2654. delete [] sig_buf;
  2655. if(ret)
  2656. return sig_len;
  2657. else
  2658. return -1;
  2659. }
  2660. BOOL CEvp::VerifySign2(EVP_MD_CTX * pCtx, EVP_PKEY *& pkey, const CString strFileName,
  2661.   CFile & File, DWORD dBolckLen, CString & outStr)
  2662. {
  2663. unsigned char * sig_buf=NULL;
  2664. unsigned int sig_len,len=0;
  2665. unsigned char inbuf[BUFLEN]="";
  2666. BOOL ret = FALSE;
  2667. long fileLen=0;//文件长度
  2668. long finishLen=0;//完成长度
  2669. if(pCtx == NULL)
  2670. {
  2671. outStr = "未初始化加密结构";
  2672. return FALSE;
  2673. }
  2674. if(pkey == NULL)
  2675. {
  2676. outStr = "公钥非法";
  2677. return FALSE;
  2678. }
  2679. CFile inSideFile;
  2680. if(!inSideFile.Open(strFileName, CFile::modeRead | CFile::typeBinary))
  2681. {
  2682. outStr = "不能打开指定文件";
  2683. return FALSE;
  2684. }
  2685. for(;;)
  2686. {
  2687. len = File.Read(inbuf, BUFLEN);                  
  2688. if(len <= 0) break;
  2689. if(!EVP_VerifyUpdate (pCtx, inbuf, len))
  2690. {
  2691. outStr = "中间过程出错";
  2692. ret=FALSE;
  2693. goto err;
  2694. }
  2695. finishLen+=len;
  2696. DrawProg(finishLen*HUNDRED/fileLen);
  2697. }
  2698. sig_len = EVP_PKEY_size(pkey);//这里应该改动
  2699. sig_buf = new unsigned char[sig_len + 1];
  2700. File.Read(sig_buf, sig_len);
  2701. if(!EVP_VerifyFinal (pCtx, sig_buf, sig_len, pkey))
  2702. {
  2703. outStr = "最终过程出错";
  2704. ret=FALSE;
  2705. }
  2706. err:
  2707. delete [] sig_buf;
  2708. return ret;
  2709. }