CSP学习笔记.doc_第1页
CSP学习笔记.doc_第2页
CSP学习笔记.doc_第3页
CSP学习笔记.doc_第4页
CSP学习笔记.doc_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

CryptoAPI学习笔记一微软公司在NT4.0以上版本中提供了一套完整的CryptoAPI的函数,支持密钥交换,数据加密解密,数字签名,给程序员带来了很大方便,用户在对软件进行保护的时候可以直接利用CryptoAPI来完成这些工作,比如计算注册码,检查程序的完整性等。我们在用这些的API进行加密解密的时候,只需要知道如何去应用它们,而不必知道它们的底层实现。如果想知道它们更为详尽的资料,可以查找相关的资料。对CryptoAPI只是业余型的感兴趣,想通过写学习笔记,一是让自己记的更牢固些,二是想把自己的学的跟大家探讨一下。写的不好,大家多多原谅。我主要通过MSDN来学习,例子也是完全取自MSDN。首先,是CryptoAPI运行的环境。首先需要Crypt32.lib,将它加到projectsetting-link下面,当然你也可以在程序中用#pragmacomment(lib,crypt32.lib)加入。在程序开头,你要加入两个头文件windows.h和Wincrypt.h,和一个#defineMY_ENCODING_TYPE(PKCS_7_ASN_ENCODING|X509_ASN_ENCODING)在正式应用API进行一系列的加密解密的时候,需要有一些准备工作,下面是介绍一些在正式开始时所需要了解和做的工作。生成密钥和密钥容器我们知道,在进行加密解密的时候,我们需要一个密钥进行加密,和一个密钥进行解密,加密密钥和解密密钥可能相同,也可能不同。于是在我们进行加密解密的开始时,我们首先需要有密钥。下面这个程序,完成了三个任务,并且介绍了一些函数的用法。任务一:获取一个指定的密钥容器,如果这个容器不存在,创建一个。任务二:如果容器中不存在一个签名密钥对,创建一个任务三:如果容器中不存在一个交换密钥对,创建一个/-下面这段程序使用到了这几个函数CryptAcquireContextCryptDestroyKeyCryptGenKeyCryptGetUserKey/Copyright(c)MicrosoftCorporation.Allrightsreserved.#include#include#include#include/-voidMyHandleError(LPTSTRpsz)_ftprintf(stderr,TEXT(Anerroroccurredintheprogram.n);_ftprintf(stderr,TEXT(%sn),psz);_ftprintf(stderr,TEXT(Errornumber%x.n),GetLastError();_ftprintf(stderr,TEXT(Programterminating.n);exit(1);/EndofMyHandleError.上面这个函数是一个异常处理函数,当出现错误的时候,出现提示,并推出程序。以后的程序中都有这个函数,以后就会将这个函数的实现省去。现在这个函数的实现在后面。voidmain(void)HCRYPTPROVhCryptProv;/定义一个CSP模块的句柄。“CSP模块,请查看加密解密二222页,那里有简单的说明,这里就不说了。LPCTSTRpszContainerName=TEXT(MySampleKeyContainer);/用一个TEXT宏定义一个容器的名字,if(CryptAcquireContext(/这个函数是获取有某个容器的CSP模块的指针,成功返回TRUE。&hCryptProv,/指向一个CSP模块句柄指针,里面用指定的容器pszContainerName,/指定容器的名称NULL,/这个参数这里用的是缺省值,指得是缺省得CSP模块,你也可以传入一个LPCTSTR类型的字符串,指定CSP模块PROV_RSA_FULL,/确定密钥的类型0)/常设为0,还有些其他的类型,请看MSDN_tprintf(TEXT(Acryptocontextwiththe%skeycontainer)TEXT(hasbeenacquired.n),pszContainerName);else/不成功的处理段if(GetLastError()=NTE_BAD_KEYSET)/NTE_BAD_KEYSET意味着密钥/容器不存在,下面就去创建一个/新的密钥容器if(CryptAcquireContext(&hCryptProv,pszContainerName,NULL,PROV_RSA_FULL,CRYPT_NEWKEYSET)/CRYPT_NEWKEYSET意味着当指定容器不存在的时候,去创建一个容器。_tprintf(TEXT(Anewkeycontainerhasbeen)TEXT(created.n);elseMyHandleError(TEXT(Couldnotcreateanewkey)TEXT(container.n);elseMyHandleError(TEXT(CryptAcquireContextfailed.n);HCRYPTKEYhKey;/创建一个密钥句柄if(CryptGetUserKey(/CryptGetUserKey是获取一个密钥/句柄的函数,成功返回TRUEhCryptProv,/指定容器的CSP模块句柄AT_SIGNATURE,/指定私钥的类型&hKey)/原来接收获取的密钥句柄_tprintf(TEXT(Asignaturekeyisavailable.n);else_tprintf(TEXT(Nosignaturekeyisavailable.n);if(GetLastError()=NTE_NO_KEY)/NTE_NO_KEY意味着密钥不存在,下面就生成一个密钥_tprintf(TEXT(Thesignaturekeydoesnotexist.n);_tprintf(TEXT(Createasignaturekeypair.n);if(CryptGenKey(/CryptGenKey生成一个密钥hCryptProv,/指定CSP模块的句柄AT_SIGNATURE,/对于公钥密码系统,生成一个私钥和一个公钥,这个参数指定了这个密钥是公钥,于是生成了一个密码对。如果不是公钥系统,则指定了密码算法,具体看MSDN。0,/指定了生成密钥的类型,这个参数的说明挺多的,想获取更为详尽的资料请看MSDN。&hKey)_tprintf(TEXT(Createdasignaturekeypair.n);elseMyHandleError(TEXT(Erroroccurredcreatinga)TEXT(signaturekey.n);elseMyHandleError(TEXT(AnerrorotherthanNTE_NO_KEY)TEXT(gettingasignaturekey.n);/Endif._tprintf(TEXT(Asignaturekeypairexisted,oronewas)TEXT(created.nn);if(hKey)/将密钥句柄销毁if(!(CryptDestroyKey(hKey)MyHandleError(TEXT(ErrorduringCryptDestroyKey.);hKey=NULL;下面这部分和上面是类似的,只不过密钥类型不相同而已。if(CryptGetUserKey(hCryptProv,AT_KEYEXCHANGE,&hKey)_tprintf(TEXT(Anexchangekeyexists.n);else_tprintf(TEXT(Noexchangekeyisavailable.n);/Checktodeterminewhetheranexchangekey/needstobecreated.if(GetLastError()=NTE_NO_KEY)/Createakeyexchangekeypair._tprintf(TEXT(Theexchangekeydoesnotexist.n);_tprintf(TEXT(Attemptingtocreateanexchangekey)TEXT(pair.n);if(CryptGenKey(hCryptProv,AT_KEYEXCHANGE,0,&hKey)_tprintf(TEXT(Exchangekeypaircreated.n);elseMyHandleError(TEXT(Erroroccurredattemptingto)TEXT(createanexchangekey.n);elseMyHandleError(TEXT(AnerrorotherthanNTE_NO_KEY)TEXT(occurred.n);/Destroytheexchangekey.if(hKey)if(!(CryptDestroyKey(hKey)MyHandleError(TEXT(ErrorduringCryptDestroyKey.);hKey=NULL;/ReleasetheCSP.if(hCryptProv)if(!(CryptReleaseContext(hCryptProv,0)MyHandleError(TEXT(ErrorduringCryptReleaseContext.);_tprintf(TEXT(Everythingisokay.Asignaturekey);_tprintf(TEXT(pairandanexchangekeyexistin);_tprintf(TEXT(the%skeycontainer.n),pszContainerName);/Endmain.下面我们再通过一个程序,用几种不同的方法,将CryptAcquireContext和其他的API函数联系起来,看看它们是如何与一个CSP和容器工作的。这个程序演示了以下内容和几个函数。一用CryptAcquireContext获取一个缺省容器的缺省CSP的句柄。如果缺省容器不存在,用CryptAcquireContext创建一个。二用CryptGetProvParam获取CSP和容器的信息。三用CryptContextAddRef增加CSP的引用计数器的数值。四用CryptAcquireContext创建一个指定的容器五用CryptAcquireContext删除一个容器六用一个新创建的容器获取一个CSP的句柄。#include#include#include#include异常处理函数省略voidmain(void)HCRYPTPROVhCryptProv;/定义CSP句柄if(CryptAcquireContext(&hCryptProv,NULL,/缺省容器NULL,/缺省CSPPROV_RSA_FULL,0)_tprintf(TEXT(CryptAcquireContextsucceeded.n);elseif(GetLastError()=NTE_BAD_KEYSET)/同样,如果当不存在这样的容器的时候,创建一个if(CryptAcquireContext(&hCryptProv,NULL,NULL,PROV_RSA_FULL,CRYPT_NEWKEYSET)_tprintf(TEXT(CryptAcquireContextsucceeded.n);elseMyHandleError(TEXT(Couldnotcreatethedefault)TEXT(keycontainer.n);elseMyHandleError(TEXT(Ageneralerrorrunning)TEXT(CryptAcquireContext.);CHARpszName1000;DWORDcbName;cbName=1000;if(CryptGetProvParam(hCryptProv,/CSP模块句柄PP_NAME,/指定获取哪些信息,这里是指定获取CSP名字的信息(BYTE*)pszName,/缓冲区接受信息返回值&cbName,0)_tprintf(TEXT(CryptGetProvParamsucceeded.n);printf(Providername:%sn,pszName);elseMyHandleError(TEXT(ErrorreadingCSPname.n);/-/Readthenameofthekeycontainer.cbName=1000;if(CryptGetProvParam(hCryptProv,PP_CONTAINER,/获取容器名字(BYTE*)pszName,&cbName,0)_tprintf(TEXT(CryptGetProvParamsucceeded.n);printf(KeyContainername:%sn,pszName);elseMyHandleError(TEXT(Errorreadingkeycontainername.n);if(CryptContextAddRef(/CryptContextAddRef是向一个CSP的引用计数器增加一个值的函数hCryptProv,NULL,/保留值,必须为NULL0)/保留值,必须为0_tprintf(TEXT(CryptcontextAddRefsucceeded.n);elseMyHandleError(TEXT(ErrorduringCryptContextAddRef!n);/-/ThereferencecountonhCryptProvisnowgreaterthanone./ThefirstcalltoCryptReleaseContextwillnotreleasethe/providerhandle./-/Releasethecontextonce.if(CryptReleaseContext(hCryptProv,0)/CryptReleaseContext是用来释放CSP句柄的,当这个函数调用一次的时候,CSP里面的引用计数就减少一,当引用计数减少的0的时候。CSP将不能再被这个程序中的任何函数调用了。_tprintf(TEXT(ThefirstcalltoCryptReleaseContext)TEXT(succeeded.n);elseMyHandleError(TEXT(Errorduring)TEXT(CryptReleaseContext#1!n);if(CryptReleaseContext(hCryptProv,0)/再次释放CSP模块_tprintf(TEXT(ThesecondcalltoCryptReleaseContext)TEXT(succeeded.n);elseMyHandleError(TEXT(Errorduring)TEXT(CryptReleaseContext#2!n);下面是从PROV_RSA_FULL的CSP模块中创建一个自己的容器LPCTSTRpszContainerName=TEXT(MySampleKeyContainer);hCryptProv=NULL;if(CryptAcquireContext(&hCryptProv,pszContainerName,NULL,PROV_RSA_FULL,CRYPT_NEWKEYSET)_tprintf(TEXT(CryptAcquireContextsucceeded.n);_tprintf(TEXT(Newkeysetcreated.n);/-/Releasetheproviderhandleandthekeycontainer.if(hCryptProv)if(CryptReleaseContext(hCryptProv,0)hCryptProv=NULL;_tprintf(TEXT(CryptReleaseContextsucceeded.n);elseMyHandleError(TEXT(Errorduring)TEXT(CryptReleaseContext!n);elseif(GetLastError()=NTE_EXISTS)_tprintf(TEXT(Thenamedkeycontainercouldnotbe)TEXT(createdbecauseitalreadyexists.n);elseMyHandleError(TEXT(ErrorduringCryptAcquireContext)TEXT(foranewkeycontainer.);if(CryptAcquireContext(&hCryptProv,pszContainerName,NULL,PROV_RSA_FULL,0)_tprintf(TEXT(Acquiredthekeysetjustcreated.n);elseMyHandleError(TEXT(ErrorduringCryptAcquireContext!n);/-/Performcryptographicoperations./-if(CryptReleaseContext(hCryptProv,0)_tprintf(TEXT(CryptReleaseContextsucceeded.n);elseMyHandleError(TEXT(ErrorduringCryptReleaseContext!n);if(CryptAcquireContext(&hCryptProv,pszContainerName,NULL,PROV_RSA_FULL,CRYPT_DELETEKEYSET)/CRYPT_DELETEKEYSET意味着CryptAcquireContex删除一个指定的容器_tprintf(TEXT(Deletedthekeycontainerjustcreated.n);elseMyHandleError(TEXT(ErrorduringCryptAcquireContext!n);CryptographyAPI学习笔记二前面学习了密钥容器的建立的一些知识,现在我们接下来自然是学习如何获取一个密钥,首先是获取一个sessionkey,即对话密钥,是对称密钥。这些学习笔记主要是从MSDN中的例子中,学习基本的CryptographyAPI的用法,了解一些用法的过程。欢迎大家多提宝贵意见。下面依旧是从一个小程序开始。这个程序的学习任务有以下几个:任务一:调用CryptAcquireContext,获取一个缺省CSP和缺省密钥容器的句柄任务二:用CryptCreateHash去创建一个空的哈希对象任务三:用CryptHashData.哈希密码任务四:调用CryptDeriveKey获取一个对话密钥任务五:销毁密码和哈希后的数据任务六:释放CSP#include#include#include#include#include#defineMY_ENCODING_TYPE(PKCS_7_ASN_ENCODING|X509_ASN_ENCODING)voidMyHandleError(char*s);voidGetConsoleInput(char*,int);voidmain()HCRYPTPROVhCryptProv;定义CSP句柄HCRYPTKEYhKey;定义密钥句柄HCRYPTHASHhHash;定义一个HASH对象的句柄CHARszPassword512=;定义512大小的字符数组,用来保存密码DWORDdwLength;保存密码长度fprintf(stderr,Enterapasswordtobeusedtocreateakey:);GetConsoleInput(szPassword,512);获取密码,这个是自己写的函数,目的是在屏幕上显示的是*。printf(Thepasswordhasbeenstored.n);dwLength=strlen(szPassword);if(CryptAcquireContext(以下是获取一个缺省的PROV_RSA_FULLCSP句柄&hCryptProv,NULL,NULL,PROV_RSA_FULL,0)printf(Acontexthasbeenacquired.n);elseMyHandleError(ErrorduringCryptAcquireContext!);/-if(CryptCreateHash(调用CryptCreateHash创建一个HASH对象hCryptProv,一个CSP句柄CALG_MD5,确定哈希算法0,对于非密钥算法,这个参数一定是0,如果是密钥算法,那么这个参数就是密钥0,保留参数,为0&hHash)一个哈希对象的指针printf(Anemptyhashobjecthasbeencreated.n);elseMyHandleError(ErrorduringCryptCreateHash!);/-if(CryptHashData(调用CryptHashData哈希密码hHash,哈希对象(BYTE*)szPassword,指向缓冲区的地址dwLength,密码长度0)printf(Thepasswordhasbeenhashed.n);elseMyHandleError(ErrorduringCryptHashData!);/-if(CryptDeriveKey(调用CryptDeriveKey获取对话密码hCryptProv,CSP句柄CALG_RC2,一个ALG_ID结构,用来指定对称密钥生成的算法hHash,哈希对象CRYPT_EXPORTABLE,指定生成密钥的类型,CRYPT_EXPORTABLE意味着这个程序生成的密钥可以被其它程序调用,而不是仅仅限于这个程序当中。但是它不能用于非对称密码中。&hKey)printf(Thekeyhasbeenderived.n);elseMyHandleError(ErrorduringCryptDeriveKey!);if(hHash)销毁哈希对象if(!(CryptDestroyHash(hHash)MyHandleError(ErrorduringCryptDestroyHash);if(hKey)销毁密钥句柄if(!(CryptDestroyKey(hKey)MyHandleError(ErrorduringCryptDestroyKey);if(hCryptProv)销毁CSP句柄if(!(CryptReleaseContext(hCryptProv,0)MyHandleError(ErrorduringCryptReleaseContext);printf(Theprogramtoderiveakeycompletedwithouterror.n);/endmainvoidMyHandleError函数的实现省略,在上一篇中有voidGetConsoleInput(char*strInput,intintMaxChars)charch;charminChar=;minChar+;ch=getch();while(ch!=r)if(ch=b&strlen(strInput)0)strInputstrlen(strInput)-1=0;printf(bb);elseif(ch=minChar&strlen(strInput)intMaxChars)strInputstrlen(strInput)+1=0;strInputstrlen(strInput)=ch;putch(*);ch=getch();putch(n);下面讲讲如何复制一个对话密钥,照例是从一个程序讲起,完成以下任务。获取一个CSP句柄,创建一个对话密钥,复制密钥。改变密钥生成过程,随机填充一个缓冲区,销毁密钥句柄,释放CSP句柄。#include#include#include#defineMY_ENCODING_TYPE(PKCS_7_ASN_ENCODING|X509_ASN_ENCODING)voidMyHandleError(char*s);voidmain

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论