版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
MicrosoftCryptoAPI加密技术(一)
在这个信息爆炸的时代,我们不得不对信息的安全提高警惕。加密作为保障数据信息安全的一种方式,越来越受到人们的关注。
下面,我将把自己对MicrosoftCryptoAPI的一些肤浅的理解与大家共享,有什么不妥之处望不吝赐教。一、加密方法:
当初,计算机的研究就是为了破解德国人的密码,人们并没有想到计算机给今天带来的信息革命。随着计算机的发展,运算能力的增强,密码学已经取得了巨大的进展。大体来说有以下几种形式。
1、公用密钥加密技术
加密和解密使用不同的密钥,分别叫做“公钥”和“私钥”。顾名思义,“私钥”就是不能让别人知道的,而“公钥”就是可以公开的。这两个必须配对使用,用公钥加密的数据必须用与其对应的私钥才能解开。这种技术安全性高,得到广泛运用,但是效率太低。
2、对称密钥加密技术
要求加密和解密过程使用相同的密钥,这样,密钥必须只能被加解密双方知道,否则就不安全。这种技术安全性不高,但是效率高。
3、结合公用和对称密钥加密技术
公钥加密技术以速度为代价换取了高安全性,而对称加密以低安全换取高性能,所以另一种常见的加密方法就是结合以上两种技术。
用对称加密算法对数据进行加密,然后使用更安全的但效率更低的公钥加密算法对对称密钥进行加密。
4、数字签名和鉴别
就是对已经加密的数据“签名”,这样接收者可以知道加密的数据的来源,以及是否被更改。二、CryptoAPI
微软的CryptoAPI是PKI推荐使用的加密API。其功能是为应用程序开发者提供在Win32环境下使用加密、验证等安全服务时的标准加密接口。CryptoAPI处于应用程序和CSP(cryptographicserviceprovider)之间(见图一)。
CryptoAPI的编程模型同Windows系统的图形设备接口GDI比较类似,其中加密服务提供者CSP等同于图形设备驱动程序,加密硬件(可选)等同于图形硬件,其上层的应用程序也类似,都不需要同设备驱动程序和硬件直接打交道。CryptoAPI共有五部分组成:简单消息函数(SimplifiedMessageFunctions)、低层消息函数(Low-levelMessageFunctions)、基本加密函数(BaseCryptographicFunctions)、证书编解码函数(CertificateEncode/DecodeFunctions)和证书库管理函数(CertificateStoreFunctions)。其中前三者可用于对敏感信息进行加密或签名处理,可保证网络传输信心的私有性;后两者通过对证书的使用,可保证网络信息交流中的认证性。三、CSP
看到这里,大家也许对CSP还比较迷惑。其实CSP是真正实行加密的独立模块,他既可以由软件实现也可以由硬件实现。但是他必须符合CryptoAPI接口的规范。每个CSP都有一个名字和一个类型。每个CSP的名字是唯一的,这样便于CryptoAPI找到对应的CSP。目前已经有9种CSP类型,并且还在增长。下表列出出它们支持的密钥交换算法、签名算法、对称加密算法和Hash算法。
(表一)CSP类型交换算法签名算法对称加密算法Hash算法PROV_RSA_FULLRSARSARC2
RC4MD5
SHAPROV_RSA_SIGnoneRSAnoneMD5
SHAPROV_RSA_SCHANNELRSARSARC4
DES
TripleDESMD5
SHAPROV_DSSDSSnoneDSSMD5
SHAPROV_DSS_DHDHDSSCYLINK_MEKMD5
SHAPROV_DH_SCHANNELDHDSSDES
TripleDESMD5
SHAPROV_FORTEZZAKEADSSSkipjackSHAPROV_MS_EXCHANGERSARSACASTMD5PROV_SSLRSARSAVariesVaries从图一可以看到,每个CSP有一个密钥库,密钥库用于存储密钥。而每个密钥库包括一个或多个密钥容器(keyContainers)。每个密钥容器中含属于一个特定用户的所有密钥对。每个密钥容器被赋予一个唯一的名字。在销毁密钥容器前CSP将永久保存每一个密钥容器,包括保存每个密钥容器中的公/私钥对(见图二)。
四、创建密钥容器,得到CSP句柄
说了这么多只是一些理论性的东西,后面将详细介绍一下MicrosoftCryptoAPI的使用方法。我们已经提过,每一个CSP都有一个名字和一个类型,并且名字保证唯一。所以可以通过名字和类型得到一个CSP。然而,要想加密肯定需要密钥,那么密钥放哪里呢?对了,就放在密钥容器。(有人会问,密码库有什么用?其实密钥库是在安装CSP的时候已经存在了,他与CSP是相对应的。)但是密钥容器并不是一开始就存在的,需要用户去创建。下面的代码实现以上功能(得到CSP即密码容器)。if(CryptAcquireContext(&hCryptProv,//返回CSP句柄UserName,//密码容器名NULL,//NULL时使用默认CSP名(微软RSABaseProvider)PROV_RSA_FULL,//CSP类型0))//Flagvalues{//以UserName为名的密钥容器存在,那么我们已经得到了CSP的句柄printf("Acryptocontextwiththe%skeycontainer\n",UserName);printf("hasbeenacquired.\n\n");}else//如果密钥容器不存在,我们需要创建这个密钥容器{if(CryptAcquireContext(&hCryptProv,UserName,NULL,PROV_RSA_FULL,CRYPT_NEWKEYSET))//创建以UserName为名的密钥容器{//创建密钥容器成功,并得到CSP句柄printf("Anewkeycontainerhasbeencreated.\n");}else{HandleError("Couldnotcreateanewkeycontainer.\n");}}//Endofelse好了,我们已经创建了密钥容器,并得到了CSP的句柄。也可以这样理解,我们得到了一个CSP的句柄,并且它被绑定到以UserName为名的密钥容器上。嘿嘿……
那么,以后的加解密等操作,都将在这个CSP上进行。
可以如下删除密钥容器。
CryptAcquireContext(&hCryptProv,userName,NULL,PROV_RSA_FULL,CRYPT_DELETEKEYSET);五、一个文件加密的例子
看到这里肯定有人开始说了,“这么多废话,还不快讲怎么加密怎么解密!”您先别急,有些原理性的东西还是先了解了比较好,对以后的使用会有很大帮助。言归正传,我们来看一段文件加密的代码。#include#include#include#defineMY_ENCODING_TYPE(PKCS_7_ASN_ENCODING|X509_ASN_ENCODING)#defineKEYLENGTH0x00800000voidHandleError(char*s);//--------------------------------------------------------------------//Theseadditional#definestatementsarerequired.#defineENCRYPT_ALGORITHMCALG_RC4#defineENCRYPT_BLOCK_SIZE8//DeclarethefunctionEncryptFile.Thefunctiondefinition//followsmain.BOOLEncryptFile(PCHARszSource,PCHARszDestination,PCHARszPassword);//--------------------------------------------------------------------//Beginmain.voidmain(void){CHARszSource[100];CHARszDestination[100];CHARszPassword[100];printf("Encryptafile.\n\n");printf("Enterthenameofthefiletobeencrypted:");scanf("%s",szSource);printf("Enterthenameoftheoutputfile:");scanf("%s",szDestination);printf("Enterthepassword:");scanf("%s",szPassword);//--------------------------------------------------------------------//CallEncryptFiletodotheactualencryption.if(EncryptFile(szSource,szDestination,szPassword)){printf("Encryptionofthefile%swasasuccess.\n",szSource);printf("Theencrypteddataisinfile%s.\n",szDestination);}else{HandleError("Errorencryptingfile!");}}//Endofmain//--------------------------------------------------------------------//CodeforthefunctionEncryptFilecalledbymain.staticBOOLEncryptFile(PCHARszSource,PCHARszDestination,PCHARszPassword)//--------------------------------------------------------------------//Parameterspassedare://szSource,thenameoftheinput,aplaintextfile.//szDestination,thenameoftheoutput,anencryptedfiletobe//created.//szPassword,thepassword.{//--------------------------------------------------------------------//Declareandinitializelocalvariables.FILE*hSource;FILE*hDestination;HCRYPTPROVhCryptProv;HCRYPTKEYhKey;HCRYPTHASHhHash;PBYTEpbBuffer;DWORDdwBlockLen;DWORDdwBufferLen;DWORDdwCount;//--------------------------------------------------------------------//Opensourcefile.if(hSource=fopen(szSource,"rb")){printf("Thesourceplaintextfile,%s,isopen.\n",szSource);}else{HandleError("Erroropeningsourceplaintextfile!");}//--------------------------------------------------------------------//Opendestinationfile.if(hDestination=fopen(szDestination,"wb")){printf("Destinationfile%sisopen.\n",szDestination);}else{HandleError("Erroropeningdestinationciphertextfile!");}//以下获得一个CSP句柄if(CryptAcquireContext(&hCryptProv,NULL,//NULL表示使用默认密钥容器,默认密钥容器名//为用户登陆名NULL,PROV_RSA_FULL,0)){printf("Acryptographicproviderhasbeenacquired.\n");}else{if(CryptAcquireContext(&hCryptProv,NULL,NULL,PROV_RSA_FULL,CRYPT_NEWKEYSET))//创建密钥容器{//创建密钥容器成功,并得到CSP句柄printf("Anewkeycontainerhasbeencreated.\n");}else{HandleError("Couldnotcreateanewkeycontainer.\n");}}//--------------------------------------------------------------------//创建一个会话密钥(sessionkey)//会话密钥也叫对称密钥,用于对称加密算法。//(注:一个Session是指从调用函数CryptAcquireContext到调用函数//CryptReleaseContext期间的阶段。会话密钥只能存在于一个会话过程)//--------------------------------------------------------------------//Createahashobject.if(CryptCreateHash(hCryptProv,CALG_MD5,0,0,&hHash)){printf("Ahashobjecthasbeencreated.\n");}else{HandleError("ErrorduringCryptCreateHash!\n");}//--------------------------------------------------------------------//用输入的密码产生一个散列if(CryptHashData(hHash,(BYTE*)szPassword,strlen(szPassword),0)){printf("Thepasswordhasbeenaddedtothehash.\n");}else{HandleError("ErrorduringCryptHashData.\n");}//--------------------------------------------------------------------//通过散列生成会话密钥if(CryptDeriveKey(hCryptProv,ENCRYPT_ALGORITHM,hHash,KEYLENGTH,&hKey)){printf("Anencryptionkeyisderivedfromthepasswordhash.\n");}else{HandleError("ErrorduringCryptDeriveKey!\n");}//--------------------------------------------------------------------//Destroythehashobject.CryptDestroyHash(hHash);hHash=NULL;//--------------------------------------------------------------------//Thesessionkeyisnowready.//--------------------------------------------------------------------//因为加密算法是按ENCRYPT_BLOCK_SIZE大小的块加密的,所以被加密的//数据长度必须是ENCRYPT_BLOCK_SIZE的整数倍。下面计算一次加密的//数据长度。dwBlockLen=1000-1000%ENCRYPT_BLOCK_SIZE;//--------------------------------------------------------------------//Determinetheblocksize.Ifablockcipherisused,//itmusthaveroomforanextrablock.if(ENCRYPT_BLOCK_SIZE>1)dwBufferLen=dwBlockLen+ENCRYPT_BLOCK_SIZE;elsedwBufferLen=dwBlockLen;//--------------------------------------------------------------------//Allocatememory.if(pbBuffer=(BYTE*)malloc(dwBufferLen)){printf("Memoryhasbeenallocatedforthebuffer.\n");}else{HandleError("Outofmemory.\n");}//--------------------------------------------------------------------//Inadoloop,encryptthesourcefileandwritetothesourcefile.do{//--------------------------------------------------------------------//ReaduptodwBlockLenbytesfromthesourcefile.dwCount=fread(pbBuffer,1,dwBlockLen,hSource);if(ferror(hSource)){HandleError("Errorreadingplaintext!\n");}//--------------------------------------------------------------------//加密数据if(!CryptEncrypt(hKey,//密钥0,//如果数据同时进行散列和加密,这里传入一个//散列对象feof(hSource),//如果是最后一个被加密的块,输入TRUE.如果不是输.//入FALSE这里通过判断是否到文件尾来决定是否为//最后一块。0,//保留pbBuffer,//输入被加密数据,输出加密后的数据&dwCount,//输入被加密数据实际长度,输出加密后数据长度dwBufferLen))//pbBuffer的大小。{HandleError("ErrorduringCryptEncrypt.\n");}//--------------------------------------------------------------------//Writedatatothedestinationfile.fwrite(pbBuffer,1,dwCount,hDestination);if(ferror(hDestination)){HandleError("Errorwritingciphertext.");}}while(!feof(hSource));//--------------------------------------------------------------------//Endthedoloopwhenthelastblockofthesourcefilehasbeen//read,encrypted,andwrittentothedestinationfile.//--------------------------------------------------------------------//Closefiles.if(hSource)fclose(hSource);if(hDestination)fclose(hDestination);//--------------------------------------------------------------------//Freememory.if(pbBuffer)free(pbBuffer);//--------------------------------------------------------------------/
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 公共政策分析 第四章 政策工具 习题
- 2024年03月中国银行随州分行春季招考笔试历年参考题库附带答案详解
- 2025版公积金贷款二手房产买卖合同样本3篇
- 2025版电力系统建设电力材料采购及技术指导合同2篇
- 2024年版机动车质押借款担保协议版B版
- 2025板材市场占有率提升战略合作合同3篇
- 2024年03月黑龙江中国邮政储蓄银行黑龙江省分行春季社会招考信息笔试历年参考题库附带答案详解
- 2025年度快递行业包装减量减排合作合同3篇
- 2024年金融产品抵押借款协议3篇
- 2024年销售业务标准协议格式版B版
- 《八年级下学期语文教学个人工作总结》
- 电仪工段工段长职位说明书
- 铝合金门窗制作工艺卡片 - 修改
- 恒亚水泥厂电工基础试题
- 简易送货单EXCEL打印模板
- 4s店信息员岗位工作职责
- 旋转导向+地质导向+水平井工具仪器介绍
- 无心磨的导轮及心高调整讲解
- 乳腺癌化疗的不良反应级处理ppt课件
- 艾灸疗法(课堂PPT)
- 给水管网设计计算说明书
评论
0/150
提交评论