CryptAcquireContext CryptDestroyKey CryptGenKey CryptGetUserKey // Copyright (c) Microsoft Corporation. All rights reserved.#include#include #include #include //-------------------------------------------------------------------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")); exit(1);} // End of MyHandleError.上面这个函数是一个异常处理函数,当出现错误的时候,出现提示,并推出程序。以后的程序中都有这个函数,以后就会将这个函数的实现省去。现在这个函数的实现在后面。void main(void) { HCRYPTPROV hCryptProv; //定义一个CSP模块的句柄。“CSP模块,请查看《加密解密二》222页,那里有简单的说明,这里就不说了。 LPCTSTR pszContainerName = TEXT("My Sample Key Container");//用一个TEXT宏定义一个容器的名字, if(CryptAcquireContext( //这个函数是获取有某个容器的CSP模块的指针,成功返回TRUE。 &hCryptProv, //指向一个CSP模块句柄指针,里面用指定的容器 pszContainerName, //指定容器的名称 NULL, //这个参数这里用的是缺省值,指得是缺省得CSP模块,你也可以传入一个LPCTSTR类型的字符串,指定CSP模块 PROV_RSA_FULL, //确定密钥的类型 0)) //常设为0,还有些其他的类型,请看MSDN { _tprintf( TEXT("A crypto context with the %s key container ") TEXT("has been acquired.\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("A new key container has been ") TEXT("created.\n")); } else { MyHandleError(TEXT("Could not create a new key ") TEXT("container.\n")); } } else { MyHandleError(TEXT("CryptAcquireContext failed.\n")); } } HCRYPTKEY hKey; //创建一个密钥句柄 if(CryptGetUserKey( // CryptGetUserKey是获取一个密钥//句柄的函数,成功返回TRUE hCryptProv, //指定容器的CSP模块句柄 AT_SIGNATURE, //指定私钥的类型 &hKey)) //原来接收获取的密钥句柄 { _tprintf(TEXT("A signature key is available.\n")); } else { _tprintf(TEXT("No signature key is available.\n")); if(GetLastError() == NTE_NO_KEY) // NTE_NO_KEY意味着密钥不存在,下面就生成一个密钥 { _tprintf(TEXT("The signature key does not exist.\n")); _tprintf(TEXT("Create a signature key pair.\n")); if(CryptGenKey( // CryptGenKey生成一个密钥 hCryptProv, //指定CSP模块的句柄 AT_SIGNATURE, //对于公钥密码系统,生成一个私钥和一个公钥,这个参数指定了这个密钥是公钥,于是生成了一个密码对。如果不是公钥系统,则指定了密码算法,具体看MSDN。 0, //指定了生成密钥的类型,这个参数的说明挺多的,想获取更为详尽的资料请看MSDN。 &hKey)) { _tprintf(TEXT("Created a signature key pair.\n")); } else { 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的句柄。如果缺省容器不存在,用CryptAcquireContext创建一个。二. 用CryptGetProvParam获取CSP和容器的信息。三. 用CryptContextAddRef增加CSP的引用计数器的数值。四. 用CryptAcquireContext创建一个指定的容器五. 用CryptAcquireContext删除一个容器六. 用一个新创建的容器获取一个CSP的句柄。#include #include #include #include 异常处理函数省略void main(void){ HCRYPTPROV hCryptProv; //定义CSP句柄 if(CryptAcquireContext( &hCryptProv, NULL, //缺省容器 NULL, //缺省CSP 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")); } 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, //CSP模块句柄 PP_NAME, //指定获取哪些信息,这里是指定获取CSP名字的信息 (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")); printf("Key Container name: %s\n", pszName); } else { MyHandleError(TEXT("Error reading key container name.\n")); } if(CryptContextAddRef( // CryptContextAddRef是向一个CSP的引用计数器增加一个值的函数 hCryptProv, NULL, //保留值,必须为NULL 0)) //保留值,必须为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. if (CryptReleaseContext(hCryptProv, 0)) // CryptReleaseContext是用来释放CSP句柄的,当这个函数调用一次的时候,CSP里面的引用计数就减少一,当引用计数减少的0的时候。CSP将不能再被这个程序中的任何函数调用了。 { _tprintf(TEXT("The first call to CryptReleaseContext ") TEXT("succeeded.\n")); } else { MyHandleError(TEXT("Error during ") TEXT("CryptReleaseContext #1!\n")); } if (CryptReleaseContext(hCryptProv, 0)) //再次释放CSP模块 { _tprintf(TEXT("The second call to CryptReleaseContext ") 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)) //CRYPT_DELETEKEYSET意味着CryptAcquireContex删除一个指定的容器 { _tprintf(TEXT("Deleted the key container just created. \n")); } else { MyHandleError(TEXT("Error during CryptAcquireContext!\n")); }}