伤城文章网 > 四年级英语 > Crypto API 学习笔记一

Crypto API 学习笔记一


Crypto API 学习笔记一 微软公司在 NT4.0 以上版本中提供了一套完整的 Crypto API 的函数,支持密钥交换,数据加密解密,数字 签名, 给程序员带来了很大方便, 用户在对软件进行保护的时候可以直接利用 Crypto API 来完成这些工作, 比如计算注册码,检查程序的完整性等。 我们在用这些的 API 进行加密解密的时候,只需要知道如何去应用它们,而不必知道它们的底层实现。 如果想知道它们更为详尽的资料,可以查找相关的资料。 对 Crypto API 只是业余型的感兴趣,想通过写学习笔记,一是让自己记的更牢固些,二是想把自己的学 的跟大家探讨一下。写的不好,大家多多原谅。我主要通过 MSDN 来学习,例子也是完全取自 MSDN。 首先,是 Crypto API 运行的环境。 首先需要 Crypt32.lib,将它加到 project->setting->link 下面,当然你也可以在程序中用 #pragma comment (lib, "crypt32.lib")加入。 在程序开头,你要加入两个头文件 windows.h 和 Wincrypt.h,和一个 #define MY_ENCODING_TYPE 需要了解和做的工作。 生成密钥和密钥容器 我们知道,在进行加密解密的时候,我们需要一个密钥进行加密,和一个密钥进行解密,加密密钥和解 密密钥可能相同,也可能不同。于是在我们进行加密解密的开始时,我们首先需要有密钥。下面这个程序, 完成了三个任务,并且介绍了一些函数的用法。 任务一:获取一个指定的密钥容器,如果这个容器不存在,创建一个。 任务二:如果容器中不存在一个签名密钥对,创建一个 任务三:如果容器中不存在一个交换密钥对,创建一个 //------------------------------------------------------------------下面这段程序使用到了这几个函数 CryptAcquireContext CryptDestroyKey CryptGenKey CryptGetUserKey // Copyright (c) Microsoft Corporation. #include <stdio.h> #include <tchar.h> #include <windows.h> #include <Wincrypt.h> //------------------------------------------------------------------void MyHandleError(LPTSTR psz) { _ftprintf(stderr, TEXT("An error occurred in the program. \n")); _ftprintf(stderr, TEXT("%s\n"), psz); _ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError()); _ftprintf(stderr, TEXT("Program terminating. \n")); All rights reserved. (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) 在正式应用 API 进行一系列的加密解密的时候,需要有一些准备工作,下面是介绍一些在正式开始时所

exit(1); } // End of MyHandleError. 上面这个函数是一个异常处理函数,当出现错误的时候,出现提示,并推出程序。以后的程序中都有这个 函数,以后就会将这个函数的实现省去。现在这个函数的实现在后面。 void main(void) { HCRYPTPROV hCryptProv; //定义一个 CSP 模块的句柄。“CSP 模块,请查看《加密解密二》222 页,那里有简单的说明,这里就不说了。 LPCTSTR pszContainerName = TEXT("My Sample Key Container");//用一个 TEXT 宏定义一个容 器的名字,

if(CryptAcquireContext( &hCryptProv, pszContainerName, NULL, PROV_RSA_FULL, 0)) { _tprintf(

//这个函数是获取有某个容器的 CSP 模块的指针,成功返回 TRUE。 //指向一个 CSP 模块句柄指针,里面用指定的容器 //指定容器的名称

//这个参数这里用的是缺省值,指得是缺省得 CSP 模块,你也可以传入一个 //确定密钥的类型 //常设为 0,还有些其他的类型,请看 MSDN

LPCTSTR 类型的字符串,指定 CSP 模块

TEXT("A crypto context with the %s key container ") TEXT("has been acquired.\n"), pszContainerName); } else { //不成功的处理段 if(GetLastError() == NTE_BAD_KEYSET) //容器不存在,下面就去创建一个 //新的密钥容器 { if(CryptAcquireContext( &hCryptProv, pszContainerName, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) 去创建一个容器。 { _tprintf(TEXT("A new key container has been ") TEXT("created.\n")); } // CRYPT_NEWKEYSET 意味着当指定容器不存在的时候, // NTE_BAD_KEYSET 意味着密钥

else { MyHandleError(TEXT("Could not create a new key ") TEXT("container.\n")); } } else { MyHandleError(TEXT("CryptAcquireContext failed.\n")); } }

HCRYPTKEY hKey; if(CryptGetUserKey( 数,成功返回 TRUE hCryptProv, AT_SIGNATURE, &hKey)) {

//创建一个密钥句柄 // CryptGetUserKey 是获取一个密钥//句柄的函 //指定容器的 CSP 模块句柄 //指定私钥的类型 //原来接收获取的密钥句柄

_tprintf(TEXT("A signature key is available.\n")); } else { _tprintf(TEXT("No signature key is available.\n")); if(GetLastError() == NTE_NO_KEY) 生成一个密钥 { _tprintf(TEXT("The signature key does not exist.\n")); _tprintf(TEXT("Create a signature key pair.\n")); if(CryptGenKey( hCryptProv, AT_SIGNATURE, 看 MSDN。 0, 的,想获取更为详尽的资料请看 MSDN。 &hKey)) { _tprintf(TEXT("Created a signature key pair.\n")); } else //指定了生成密钥的类型, 这个参数的说明挺多 // CryptGenKey 生成一个密钥 //指定 CSP 模块的句柄 //对于公钥密码系统,生成一个私钥和一个公钥, // NTE_NO_KEY 意味着密钥不存在,下面就

这个参数指定了这个密钥是公钥,于是生成了一个密码对。如果不是公钥系统,则指定了密码算法,具体

{ MyHandleError(TEXT("Error occurred creating a ") TEXT("signature key.\n")); } } else { MyHandleError(TEXT("An error other than NTE_NO_KEY ") TEXT("getting a signature key.\n")); } } // End if. _tprintf(TEXT("A signature key pair existed, or one was ") TEXT("created.\n\n")); if(hKey) { if(!(CryptDestroyKey(hKey))) { MyHandleError(TEXT("Error during CryptDestroyKey.")); } hKey = NULL; } 下面这部分和上面是类似的,只不过密钥类型不相同而已。 if(CryptGetUserKey( hCryptProv, AT_KEYEXCHANGE, &hKey)) { _tprintf(TEXT("An exchange key exists.\n")); } else { _tprintf(TEXT("No exchange key is available.\n")); // Check to determine whether an exchange key // needs to be created. if(GetLastError() == NTE_NO_KEY) { // Create a key exchange key pair. _tprintf(TEXT("The exchange key does not exist.\n")); _tprintf(TEXT("Attempting to create an exchange key ") //将密钥句柄销毁

TEXT("pair.\n")); if(CryptGenKey( hCryptProv, AT_KEYEXCHANGE, 0, &hKey)) { _tprintf(TEXT("Exchange key pair created.\n")); } else { MyHandleError(TEXT("Error occurred attempting to ") TEXT("create an exchange key.\n")); } } else { MyHandleError(TEXT("An error other than NTE_NO_KEY ") TEXT("occurred.\n")); } } // Destroy the exchange key. if(hKey) { if(!(CryptDestroyKey(hKey))) { MyHandleError(TEXT("Error during CryptDestroyKey.")); } hKey = NULL; } // Release the CSP. if(hCryptProv) { if(!(CryptReleaseContext(hCryptProv, 0))) { MyHandleError(TEXT("Error during CryptReleaseContext.")); } } _tprintf(TEXT("Everything is okay. A signature key ")); _tprintf(TEXT("pair and an exchange key exist in "));

_tprintf(TEXT("the %s key container.\n"), pszContainerName); } // End main. 下面我们再通过一个程序,用几种不同的方法,将 CryptAcquireContext 和其他的 API 函数联系起来, 看看它们是如何与一个 CSP 和容器工作的。这个程序演示了以下内容和几个函数。 一. 二. 三. 四. 五. 六. 用 CryptAcquireContext 获取一个缺省容器的缺省 CSP 的句柄。如果缺省容器不存在,用 用 CryptGetProvParam 获取 CSP 和容器的信息。 用 CryptContextAddRef 增加 CSP 的引用计数器的数值。 用 CryptAcquireContext 创建一个指定的容器 用 CryptAcquireContext 删除一个容器 用一个新创建的容器获取一个 CSP 的句柄。 CryptAcquireContext 创建一个。

#include <stdio.h> #include <tchar.h> #include <windows.h> #include <Wincrypt.h> 异常处理函数省略 void main(void) { HCRYPTPROV hCryptProv; if(CryptAcquireContext( &hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) { _tprintf(TEXT("CryptAcquireContext succeeded.\n")); } else { if (GetLastError() == NTE_BAD_KEYSET) 时候,创建一个 { if(CryptAcquireContext( &hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { _tprintf(TEXT("CryptAcquireContext succeeded.\n")); } //同样,如果当不存在这样的容器的 //缺省容器 //缺省 CSP //定义 CSP 句柄

else { MyHandleError(TEXT("Could not create the default ") TEXT("key container.\n")); } } else { MyHandleError(TEXT("A general error running ") TEXT("CryptAcquireContext.")); } } CHAR pszName[1000]; DWORD cbName; cbName = 1000; if(CryptGetProvParam( hCryptProv, PP_NAME, 字的信息 (BYTE*)pszName, &cbName, 0)) { _tprintf(TEXT("CryptGetProvParam succeeded.\n")); printf("Provider name: %s\n", pszName); } else { MyHandleError(TEXT("Error reading CSP name.\n")); } //--------------------------------------------------------------// Read the name of the key container. cbName = 1000; if(CryptGetProvParam( hCryptProv, PP_CONTAINER, (BYTE*)pszName, &cbName, 0)) { _tprintf(TEXT("CryptGetProvParam succeeded.\n")); //获取容器名字 //缓冲区接受信息返回值 //CSP 模块句柄 //指定获取哪些信息, 这里是指定获取 CSP 名

printf("Key Container name: %s\n", pszName); } else { MyHandleError(TEXT("Error reading key container name.\n")); }

if(CryptContextAddRef( 器增加一个值的函数 hCryptProv, NULL, 0)) {

// CryptContextAddRef 是向一个 CSP 的引用计数

//保留值,必须为 NULL //保留值,必须为 0

_tprintf(TEXT("CryptcontextAddRef succeeded.\n")); } else { MyHandleError(TEXT("Error during CryptContextAddRef!\n")); } //--------------------------------------------------------------// // // The reference count on hCryptProv is now greater than one. The first call to CryptReleaseContext will not release the provider handle.

//--------------------------------------------------------------// Release the context once. // CryptReleaseContext 是用来释放 if (CryptReleaseContext(hCryptProv, 0)) 将不能再被这个程序中的任何函数调用了。 { _tprintf(TEXT("The first call to CryptReleaseContext ") TEXT("succeeded.\n")); } else { MyHandleError(TEXT("Error during ") TEXT("CryptReleaseContext #1!\n")); } if (CryptReleaseContext(hCryptProv, 0)) { _tprintf(TEXT("The second call to CryptReleaseContext ") //再次释放 CSP 模块

CSP 句柄的, 当这个函数调用一次的时候, CSP 里面的引用计数就减少一, 当引用计数减少的 0 的时候。 CSP

TEXT("succeeded.\n")); } else { MyHandleError(TEXT("Error during ") TEXT("CryptReleaseContext #2!\n")); } 下面是从 PROV_RSA_FULL 的 CSP 模块中创建一个自己的容器 LPCTSTR pszContainerName = TEXT("My Sample Key Container"); hCryptProv = NULL; if(CryptAcquireContext( &hCryptProv, pszContainerName, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { _tprintf(TEXT("CryptAcquireContext succeeded. \n")); _tprintf(TEXT("New key set created. \n")); //----------------------------------------------------------// Release the provider handle and the key container. if(hCryptProv) { if(CryptReleaseContext(hCryptProv, 0)) { hCryptProv = NULL; _tprintf(TEXT("CryptReleaseContext succeeded. \n")); } else { MyHandleError(TEXT("Error during ") TEXT("CryptReleaseContext!\n")); } } } else { if(GetLastError() == NTE_EXISTS) { _tprintf(TEXT("The named key container could not be ") TEXT("created because it already exists.\n"));

} else { MyHandleError(TEXT("Error during CryptAcquireContext ") TEXT("for a new key container.")); } }

if(CryptAcquireContext( &hCryptProv, pszContainerName, NULL, PROV_RSA_FULL, 0)) { _tprintf(TEXT("Acquired the key set just created. \n")); } else { MyHandleError(TEXT("Error during CryptAcquireContext!\n")); } //--------------------------------------------------------------// Perform cryptographic operations. //--------------------------------------------------------------if(CryptReleaseContext( hCryptProv, 0)) { _tprintf(TEXT("CryptReleaseContext succeeded. \n")); } else { MyHandleError(TEXT("Error during CryptReleaseContext!\n")); }

if(CryptAcquireContext( &hCryptProv, pszContainerName, NULL,

PROV_RSA_FULL, CRYPT_DELETEKEYSET)) CryptAcquireContex 删除一个指定的容器 { _tprintf(TEXT("Deleted the key container just created. \n")); } else { MyHandleError(TEXT("Error during CryptAcquireContext!\n")); } } 就先写到这,大家多提宝贵意见。附件中有这两个程序编译好的程序,源程序就是文章中的。 单击打开附 件。 //CRYPT_DELETEKEYSET 意味着

?2000-2007 PEdiy.com All rights reserved. PEdiy.com diy By PEDIY


搜索更多“Crypto API 学习笔记一”

网站地图

All rights reserved Powered by 伤城文章网 5xts.com

copyright ©right 2010-2021。
伤城文章网内容来自网络,如有侵犯请联系客服。zhit325@126.com