CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  基础类

怎么使用CryptoAPI?

楼主OKzhou()2002-09-18 16:21:26 在 VC/MFC / 基础类 提问

如题 问题点数:100、回复次数:2Top

1 楼mfkzj(鹰翔)回复于 2002-09-18 16:23:26 得分 100

用CryptoAPI进行数据加密  
   
   
  南京理工大学计算机系   胡静   李蔚清  
   
     
   
  由于过于复杂的加密算法实现起来非常困难,所以在过去,许多应用程序只能使用非常简单的加密技术,这样做的结果就是加密的数据很容易被人破译。而使用Microsoft提供的加密应用程序接口(即Cryptography   API),或称CryptoAPI,可以方便地在应用程序中加入强大的加密功能,而不必考虑基本的算法。本文将对CryptoAPI及其使用的数据加密原理作一简单的介绍,然后给出了用CryptoAPI编写加密程序的大致步骤,最后以一个文件的加密、解密程序为例演示CryptoAPI的部分功能。  
   
  1.   CryptoAPI简介  
   
  CryptoAPI是一组函数,为了完成数学计算,必须具有密码服务提供者模块(CSP)。Microsoft通过捆绑RSA   Base   Provider在操作系统级提供一个CSP,使用RSA公司的公钥加密算法,更多的CSP可以根据需要增加到应用中。事实上,CSP有可能与特殊硬件设备(如智能卡)一起来进行数据加密。CryptoAPI接口允许简单的函数调用来加密数据,交换公钥,散列一个消息来建立摘要以及生成数字签名。它还提供高级的管理操作,如从一组可能的CSP中使用一个CSP。此外,CryptoAPI还为许多高级安全性服务提供了基础,包括用于电子商务的SET,用于加密客户机/服务器消息的PCT,用于在各个平台之间来回传递机密数据和密钥的PFX,代码签名等等。CryptoAPI的体系结构如图1。图1   CryptoAPI体系结构  
   
  目前支持CryptoAPI的Windows系统有:Windows   95   OSR2、Windows   NT   SP3及后续版本、Windows   98、Windows   2000等。CryptoAPI的配置信息存储在注册表中,包括如下密钥:  
   
  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft   \   Cryptography   \Defaults  
   
  HKEY_CURRENT_USER\   Software   \   Microsoft   \   Cryptography   \Providers  
   
  2.   数据加密原理  
   
  数据加密流程如图2所示。  
   
  图2   数据加密流程  
   
  CryptoAPI使用两种密钥:会话密钥与公共/私人密钥对。会话密钥使用相同的加密和解密密钥,这种算法较快,但必须保证密钥的安全传递。公共/私人密钥对使用一个公共密钥和一个私人密钥,私人密钥只有专人才能使用,公共密钥可以广泛传播。如果密钥对中的一个用于加密,另一个一定用于解密。公共/私人密钥对算法很慢,一般只用于加密小批量数据,例如用于加密会话密钥。  
   
  CryptoAPI支持两种基本的编码方法:流式编码和块编码。流式编码在明码文本的每一位上创建编码位,速度较快,但安全性较低。块编码在一个完整的块上(一般为64位)工作,需要使用填充的方法对要编码的数据进行舍入,以组成多个完整的块。这种算法速度较慢,但更安全。  
   
  3.   应用举例  
   
  下面以两个文件加密与解密的C程序片断为例,演示一下CryptoAPI的强大功能。这两个程序均为Win32控制台应用,程序省略了出错处理,实际运行时请加入。  
   
  1   文件加密  
   
  #include   <windows.h>  
   
  #include   <stdio.h>  
   
  #include   <stdlib.h>  
   
  #include   <wincrypt.h>  
   
  //确定使用RC2块编码或是RC4流式编码  
   
  #ifdef   USE_BLOCK_CIPHER  
   
  #define   ENCRYPT_ALGORITHM   CALG_RC2  
   
  #define   ENCRYPT_BLOCK_SIZE   8  
   
  #else  
   
  #define   ENCRYPT_ALGORITHM   CALG_RC4  
   
  #define   ENCRYPT_BLOCK_SIZE   1  
   
  #endif  
   
  void   CAPIDecryptFile(PCHAR   szSource,   PCHAR   szDestination,   PCHAR   szPassword);  
   
  void   _cdecl   main(int   argc,   char   *argv[])  
   
  {  
   
  PCHAR   szSource   =   NULL;  
   
  PCHAR   szDestination   =   NULL;  
   
  PCHAR   szPassword   =   NULL;  
   
  //   验证参数个数  
   
  if(argc   !=   3   &&   argc   !=   4)   {  
   
  printf("USAGE:   decrypt   <source   file>   <dest   file>   [   <password>   ]\n");  
   
  exit(1);  
   
  }  
   
  //读取参数.  
   
  szSource   =   argv[1];  
   
  szDestination   =   argv[2];  
   
  if(argc   ==   4)   {  
   
  szPassword   =   argv[3];  
   
  }  
   
  CAPIDecryptFile(szSource,   szDestination,   szPassword);  
   
  }  
   
  /*szSource为要加密的文件名称,szDestination为加密过的文件名称,szPassword为加密口令*/  
   
  void   CAPIEncryptFile(PCHAR   szSource,   PCHAR   szDestination,   PCHAR   szPassword){  
   
  FILE   *hSource   =   NULL;  
   
  FILE   *hDestination   =   NULL;  
   
  INT   eof   =   0;  
   
  HCRYPTPROV   hProv   =   0;  
   
  HCRYPTKEY   hKey   =   0;  
   
  HCRYPTKEY   hXchgKey   =   0;  
   
  HCRYPTHASH   hHash   =   0;  
   
  PBYTE   pbKeyBlob   =   NULL;  
   
  DWORD   dwKeyBlobLen;  
   
  PBYTE   pbBuffer   =   NULL;  
   
  DWORD   dwBlockLen;  
   
  DWORD   dwBufferLen;  
   
  DWORD   dwCount;  
   
  hSource=   fopen(szSource,"rb"));//   打开源文件  
   
  hDestination   =   fopen(szDestination,"wb")   ;//.打开目标文件  
   
  //   连接缺省的CSP  
   
  CryptAcquireContext(&hProv,   NULL,   NULL,   PROV_RSA_FULL,   0));  
   
  if(szPassword   ==   NULL)   {  
   
  //口令为空,使用随机产生的会话密钥加密  
   
  //   产生随机会话密钥。  
   
  CryptGenKey(hProv,   ENCRYPT_ALGORITHM,   CRYPT_EXPORTABLE,   &hKey)  
   
  //   取得密钥交换对的公共密钥  
   
  CryptGetUserKey(hProv,   AT_KEYEXCHANGE,   &hXchgKey);  
   
  //   计算隐码长度并分配缓冲区  
   
  CryptExportKey(hKey,   hXchgKey,   SIMPLEBLOB,   0,   NULL,   &dwKeyBlobLen);  
   
  pbKeyBlob=malloc(dwKeyBlobLen))   ==   NULL)   ;  
   
  //   将会话密钥输出至隐码  
   
  CryptExportKey(hKey,   hXchgKey,   SIMPLEBLOB,   0,   pbKeyBlob,   &dwKeyBlobLen))  
   
  //   释放密钥交换对的句柄  
   
  CryptDestroyKey(hXchgKey);  
   
  hXchgKey   =   0;  
   
  //   将隐码长度写入目标文件  
   
  fwrite(&dwKeyBlobLen,   sizeof(DWORD),   1,   hDestination);  
   
  //将隐码长度写入目标文件  
   
  fwrite(pbKeyBlob,1,dwKeyBlobLen,   hDestination);  
   
  }   else   {  
   
  Top

2 楼mfkzj(鹰翔)回复于 2002-09-18 16:24:13 得分 0

//口令不为空,   使用从口令派生出的密钥加密文件  
   
  CryptCreateHash(hProv,   CALG_MD5,   0,   0,   &hHash);//   建立散列表  
   
  CryptHashData(hHash,   szPassword,  
   
  strlen(szPassword),   0);   //散列口令  
   
  //   从散列表中派生密钥  
   
  CryptDeriveKey(hProv,   ENCRYPT_ALGORITHM,   hHash,   0,   &hKey);  
   
  //   删除散列表  
   
  CryptDestroyHash(hHash);  
   
  hHash   =   0;  
   
  }  
   
  //计算一次加密的数据字节数,必须为ENCRYPT_BLOCK_SIZE的整数倍dwBlockLen   =   1000   -   1000   %   ENCRYPT_BLOCK_SIZE;  
   
  //如果使用块编码,则需要额外空间  
   
  if(ENCRYPT_BLOCK_SIZE   >   1)   {  
   
  dwBufferLen=dwBlockLen   +   ENCRYPT_BLOCK_SIZE;  
   
  }   else   {  
   
  dwBufferLen   =   dwBlockLen;  
   
  }  
   
  //分配缓冲区  
   
  pbBuffer   =   malloc(dwBufferLen);  
   
  //加密源文件并写入目标文件  
   
  do   {  
   
  //   从源文件中读出dwBlockLen个字节  
   
  dwCount   =   fread(pbBuffer,   1,   dwBlockLen,   hSource);  
   
  eof   =   feof(hSource);  
   
  //加密数据  
   
  CryptEncrypt(hKey,   0,   eof,   0,   pbBuffer,   &dwCount,   dwBufferLen);  
   
  //   将加密过的数据写入目标文件  
   
  fwrite(pbBuffer,   1,   dwCount,   hDestination);  
   
  }   while(!feof(hSource));  
   
  printf("OK\n");  
   
  ......//关闭文件、释放内存  
   
  }  
   
  2   文件解密  
   
  void   CAPIDecryptFile(PCHAR   szSource,   PCHAR   szDestination,   PCHAR   szPassword)  
   
  {  
   
  ......//变量声明、文件操作同文件加密程序  
   
  CryptAcquireContext(&hProv,   NULL,   NULL,   PROV_RSA_FULL,   0);  
   
  if(szPassword   ==   NULL)   {  
   
  //   口令为空,使用存储在加密文件中的会话密钥解密  
   
  //   读隐码的长度并分配内存  
   
  fread(&dwKeyBlobLen,sizeof(DWORD),1,hSource);  
   
  pbKeyBlob=malloc(dwKeyBlobLen))==   NULL);  
   
  //   从源文件中读隐码.  
   
  fread(pbKeyBlob,   1,   dwKeyBlobLen,   hSource);  
   
  //   将隐码输入CSP  
   
  CryptImportKey(hProv,   pbKeyBlob,   dwKeyBlobLen,   0,   0,   &hKey);  
   
  }   else   {  
   
  //   口令不为空,   使用从口令派生出的密钥解密文件  
   
  CryptCreateHash(hProv,   CALG_MD5,   0,   0,   &hHash);  
   
  CryptHashData(hHash,   szPassword,   strlen(szPassword),   0);  
   
  CryptDeriveKey(hProv,   ENCRYPT_ALGORITHM,hHash,   0,   &hKey);  
   
  CryptDestroyHash(hHash);  
   
  hHash   =   0;  
   
  }  
   
  dwBlockLen=1000-1000%ENCRYPT_BLOCK_SIZE;  
   
  if(ENCRYPT_BLOCK_SIZE   >   1)   {  
   
  dwBufferLen   =   dwBlockLen   +   ENCRYPT_BLOCK_SIZE;  
   
  }   else   {  
   
  dwBufferLen   =   dwBlockLen;  
   
  }  
   
  pbBuffer   =   malloc(dwBufferLen);  
   
  //解密源文件并写入目标文件  
   
  do   {  
   
  dwCount   =   fread(pbBuffer,   1,   dwBlockLen,hSource);  
   
  eof   =   feof(hSource);  
   
  //   解密数据  
   
  CryptDecrypt(hKey,   0,   eof,   0,   pbBuffer,   &dwCount);  
   
  //   将解密过的数据写入目标文件  
   
  fwrite(pbBuffer,   1,   dwCount,   hDestination);  
   
  }   while(!feof(hSource));  
   
  printf("OK\n");  
   
  ......//关闭文件、释放内存}  
   
  以上代码在Windows   NT4.0、Visual   C++6.0环境中编译通过。除直接用于加密数据外,CryptoAPI还广泛用于产生并确认数字签名,这里就不一一举例说明了,有兴趣的读者可以参考MSDN文档。  
  Top

相关问题

  • 在cryptoapi里面怎么使用MD5
  • 使用CryptoApi对称加密后怎么不能用它来解密呀?
  • tomcat怎么使用?
  • ghost怎么使用?
  • fsockopen()怎么使用?
  • DBComboBox怎么使用
  • _variant怎么使用?
  • 怎么使用TerminateThread?
  • 怎么使用RegQueryValue?
  • OnCtlColor怎么使用??

关键词

  • 加密
  • 编码
  • 数据
  • 算法
  • 解密
  • 文件
  • 应用程序
  • rsa
  • algorithm
  • cryptoapi

得分解答快速导航

  • 帖主:OKzhou
  • mfkzj

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo