本文由网上各类汇总····
加密与解密第二版 222 页查看 学习:
下面的实验顺序颠倒,便于复习```````````````````````````````````````````
实验9`````````````````````````````
CALG_AES_128 但是发现好像加密解密出来不对的感觉
#include "stdafx.h" #include <stdio.h> #include <string> #include <iostream> #include <windows.h> #include <Wincrypt.h> #pragma comment (lib, "crypt32.lib") using namespace std; void cryptoAPI_encrypt(string text, unsigned char* pwd, unsigned char** encryptText, int &out_len) { HCRYPTPROV hCryptProv = NULL; HCRYPTKEY hKey = 0; HCRYPTHASH hHash = 0; int dwLength = 0; OSVERSIONINFOW VersionInformation = {sizeof(OSVERSIONINFOW)}; GetVersionExW(&VersionInformation); LPCWSTR CSP_NAME = MS_ENH_RSA_AES_PROV_XP_W; if ( VersionInformation.dwMajorVersion != 5 ) CSP_NAME = MS_ENH_RSA_AES_PROV_W; if(!CryptAcquireContext(&hCryptProv, NULL, CSP_NAME,//CSP_NAME PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { DWORD dwLastErr = GetLastError(); if(NTE_BAD_KEYSET == dwLastErr) { return; } else{ if(!CryptAcquireContext(&hCryptProv, NULL, CSP_NAME, PROV_RSA_AES, CRYPT_NEWKEYSET)) { return; } } } if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash)) { return; } BYTE *pPwd = pwd; if(!CryptHashData(hHash, pPwd, 16, 0)) { return; } //CRYPT_EXPORTABLE if(!CryptDeriveKey(hCryptProv, CALG_AES_128, hHash,0x800000 , &hKey))//得到最后用来加密的密钥 { return; } int len = text.length(); BYTE *pData ; pData = (BYTE*)malloc(len*4); memcpy(pData,text.c_str(),len); DWORD dwLen = len; if(!CryptEncrypt(hKey, NULL, true, 0, pData, &dwLen, len*4)) { return; } cout <<" -------------------------- " << endl << "cryptoAPI encrypt"<<endl; for (int i=0;i<dwLen;i++) { _tprintf(_T("%02x"), pData[i]); //Ciphertext[i] = pData[i]; } ; *encryptText = pData; out_len = dwLen; CryptDestroyHash(hHash); CryptDestroyKey(hKey); CryptReleaseContext(hCryptProv,0); } void cryptAPI_decrypt(unsigned char* text,int len,unsigned char* pwd) { HCRYPTPROV hCryptProv = NULL; HCRYPTKEY hKey = 0; HCRYPTHASH hHash = 0; int dwLength = 0; OSVERSIONINFOW VersionInformation = {sizeof(OSVERSIONINFOW)}; GetVersionExW(&VersionInformation); LPCWSTR CSP_NAME = MS_ENH_RSA_AES_PROV_XP_W; if ( VersionInformation.dwMajorVersion != 5 ) CSP_NAME = MS_ENH_RSA_AES_PROV_W; if(!CryptAcquireContext(&hCryptProv, NULL, CSP_NAME,//CSP_NAME PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { DWORD dwLastErr = GetLastError(); if(NTE_BAD_KEYSET == dwLastErr) { return; } else{ if(!CryptAcquireContext(&hCryptProv, NULL, CSP_NAME, PROV_RSA_AES, CRYPT_NEWKEYSET)) { return; } } } if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash)) { return; } BYTE *pPwd = pwd; if(!CryptHashData(hHash, pPwd, 16, 0)) { return; } if(!CryptDeriveKey(hCryptProv, CALG_AES_128, hHash, 0x800000, &hKey)) { return; } BYTE *pData = text; DWORD dwLen = len; if(!CryptDecrypt(hKey, NULL, true, 0, pData, &dwLen)) { return; } cout <<" -------------------------- " << endl << "cryptoAPI decrypt"<<endl; char* plainText = (char*)malloc(dwLen + 1); memcpy(plainText,pData,dwLen); plainText[dwLen] = ' '; cout << plainText << endl; CryptDestroyHash(hHash); CryptDestroyKey(hKey); CryptReleaseContext(hCryptProv,0); } void main() { string pdata="abcdefghijklmnop"; BYTE key[] = "1234567890132456"; unsigned char *getstr; int dwread; cryptoAPI_encrypt(pdata,key,&getstr,dwread); cryptAPI_decrypt(getstr,dwread,key); return ; } // end main
实验8`````````````````````````````
DES加密解密
#include "stdafx.h" #include <stdio.h> #include <windows.h> #include <Wincrypt.h> #pragma comment (lib, "crypt32.lib") void main() { struct { BLOBHEADER hdr; DWORD cbKeySize; BYTE rgbKeyData[8]; } keyBlob; keyBlob.hdr.bType = PLAINTEXTKEYBLOB;//The key is a session key. keyBlob.hdr.bVersion = CUR_BLOB_VERSION; keyBlob.hdr.reserved = 0; keyBlob.hdr.aiKeyAlg = CALG_DES; keyBlob.cbKeySize = 8; BYTE Key[8] = {0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31}; BYTE Ciphertext[8]; CopyMemory(keyBlob.rgbKeyData, Key, keyBlob.cbKeySize); BYTE pData[256] = {0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38}; DWORD dwDataLen = 8; HCRYPTPROV hProv; if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0)) { HCRYPTKEY hKey; if (CryptImportKey(hProv, (BYTE*)(&keyBlob), sizeof(keyBlob), 0, 0, &hKey)) { DWORD dwMode = CRYPT_MODE_CBC; CryptSetKeyParam(hKey, KP_MODE, (BYTE*)(&dwMode), 0); CryptEncrypt(hKey, 0, TRUE, 0, pData, &dwDataLen, _countof(pData)); for (int i = 0; i != 8 /*dwDataLen*/; ++i) { _tprintf(_T("%02x "), pData[i]); Ciphertext[i] = pData[i]; } _tprintf(_T(" ")); CryptDestroyKey(hKey); } CryptReleaseContext(hProv, 0); } if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0)) { HCRYPTKEY hKey2; if (CryptImportKey(hProv, (BYTE*)(&keyBlob), sizeof(keyBlob), 0, 0, &hKey2)) { DWORD dwMode = CRYPT_MODE_CBC; CryptSetKeyParam(hKey2, KP_MODE, (BYTE*)(&dwMode), 0); CryptDecrypt(hKey2, 0, TRUE, 0, pData, &dwDataLen); for (int i = 0; i != 8 /*dwDataLen*/; ++i) { _tprintf(_T("%02x "), pData[i]); Ciphertext[i] = pData[i]; } _tprintf(_T(" ")); CryptDestroyKey(hKey2); } CryptReleaseContext(hProv, 0); } return ; } // end main
实验7`````````````````````````````
/* 下面我们来看看如何哈希一个对话密钥,这个密钥可以用来对一个消息,文件进行加密。我们依旧从一个程序开始。 */ #include "stdafx.h" #include <stdio.h> #include <windows.h> #include <Wincrypt.h> #pragma comment (lib, "crypt32.lib") #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) void MyHandleError(LPTSTR psz) { _ftprintf(stderr, TEXT("An error occurred in the program. ")); _ftprintf(stderr, TEXT("%s "), psz); _ftprintf(stderr, TEXT("Error number %x. "), GetLastError()); _ftprintf(stderr, TEXT("Program terminating. ")); exit(1); } // End of MyHandleError. void main() { //-------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. // Declare variables. HCRYPTPROV hCryptProv; HCRYPTHASH hHash; HCRYPTKEY hKey; //-------------------------------------------------------------------- // Begin processing. printf("Process beginning. Creating a session key. "); BYTE pData[11]="1234567890"; if(CryptAcquireContext( // 首先依旧是获取一个缺省的CSP句柄 &hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) { printf("CryptAcquireContext complete. "); } else { MyHandleError(TEXT("Acquisition of context failed.")); } if(CryptCreateHash( // 创建一个CALG_MD5算法的HASH对象,这个hash对象用的是MD5算法 hCryptProv, // 指定一个CSP句柄 CALG_MD5, // 指定算法 0, 0, &hHash)) { printf("An empty hash object has been created. "); } else { MyHandleError(TEXT("Error during CryptBeginHash! ")); } if(CryptGenKey( // 创建密钥 hCryptProv, // 传入一个CSP句柄 CALG_RC2, // 指明密钥身成所用算法 CRYPT_EXPORTABLE, // 说明密钥是可以导出到CSP,用于这个应用程序外的 &hKey)) { printf("A random session key has been created. "); } else { MyHandleError(TEXT("Error during CryptGenKey! ")); } if(CryptHashSessionKey( //对生成的密钥进行hash hHash, hKey, 0)) { printf("The session key has been hashed. "); } else { MyHandleError(TEXT("Error during CryptHashSessionKey! ")); } DWORD dwRead; //在这里就可以添加代码,用生成的密钥进行加密 if(hHash) { if(!(CryptDestroyHash(hHash))) MyHandleError(TEXT("Error during CryptDestroyHash")); } if(hKey) { if(!(CryptDestroyKey(hKey))) MyHandleError(TEXT("Error during CryptDestroyKey")); } // Release the CSP. if(hCryptProv) { if(!(CryptReleaseContext(hCryptProv,0))) MyHandleError(TEXT("Error during CryptReleaseContext")); } printf("Create random session key completed without error. "); } // end main
实验6`````````````````````````````
/* 下面逐渐进入主题了,现在来讲讲是如何对数据进行Encoding and Decoding的。依旧是从一段程序中开始。 */ #include "stdafx.h" #include <stdio.h> #include <windows.h> #include <Wincrypt.h> #pragma comment (lib, "crypt32.lib") #define MY_ENCODING_TYPE (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) void MyHandleError(LPTSTR psz) { _ftprintf(stderr, TEXT("An error occurred in the program. ")); _ftprintf(stderr, TEXT("%s "), psz); _ftprintf(stderr, TEXT("Error number %x. "), GetLastError()); _ftprintf(stderr, TEXT("Program terminating. ")); exit(1); } // End of MyHandleError. void main(void) { HCRYPTMSG hMsg; //指向一个消息句柄 BYTE* pbContent; //一个BYTE指针指向消息 DWORD cbContent; //消息长度 DWORD cbEncodedBlob; //ECODE的BLOB的大小 BYTE *pbEncodedBlob; //一个BYTE指针指向ENCODE BLOB DWORD cbData = sizeof(DWORD); //数据大小 DWORD cbDecoded; //Decode内容大小 BYTE *pbDecoded; //指向Decode的指针 pbContent = (BYTE*)"Security is our only business"; cbContent = strlen((char *) pbContent)+1; printf("The original message => %s ",pbContent); if(cbEncodedBlob = CryptMsgCalculateEncodedLength( MY_ENCODING_TYPE, //指定Encode类型,在程序的开头已经预定义了,MY_ENCODING_TYPE 就是 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING 0, //Flags CMSG_DATA, // 定义了数据的类型,这里指定为BYTE型的字符串 NULL, NULL, cbContent)) // 内容的大小 //这里的的函数的作用是计算指定消息Encode所需要的最大的长度,通过计算,为一个BLOB分配内存空间。 { printf("The length of the data has been calculated. "); } else { MyHandleError(TEXT("Getting cbEncodedBlob length failed")); } //为encode blob分配内存空间 if(pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob)) { printf("Memory has been allocated for the signed message. "); } else { MyHandleError(TEXT("Memory allocation failed")); } if(hMsg = CryptMsgOpenToEncode( //CryptMsgOpenToEncode为Encode,开一个消息 MY_ENCODING_TYPE, // Encode类型,文件开始有说明 0, // Flags CMSG_DATA, // 指定Message的类型,CMSG_DATA说明类型没用到 NULL, // 现在没有到,为NULL NULL, // 同上 NULL)) // 不是流加密,这个参数为NULL { printf("The message to be encoded has been opened. "); } else { MyHandleError(TEXT("OpenToEncode failed")); } if(CryptMsgUpdate( // CryptMsgUpdate将数据加到消息中,可以通过循环,将数据一段段的加得到消息中 hMsg, // 一个小心句柄 pbContent, // 指向数据的指针 cbContent, // 数据的大小 TRUE)) // TRUE表明这个是最后一段数据,在开个消息的时候,如果CMSG_DETACHED_FLAG有使用到,这设为FALSE,否则为TRUE。 { printf("Content has been added to the encoded message. "); } else { MyHandleError(TEXT("MsgUpdate failed")); } if(CryptMsgGetParam( // CryptMsgGetParam是获取一个消息中的参数 hMsg, // 一个消息句柄 CMSG_BARE_CONTENT_PARAM, //指定要获取的参数的类型 0, pbEncodedBlob, // 一个接受数据的内存地址 &cbEncodedBlob)) // BLOB的大小,即是上面接受的数据的大小 { printf("Message encoded successfully. encoded"); printf("The message is %s. ",(LPSTR)pbEncodedBlob); } else { MyHandleError(TEXT("MsgGetParam failed")); } //释放消息句柄 if(hMsg) CryptMsgClose(hMsg); ////////////////////////////////////////////////////////////////////////////////////////////// if(hMsg = CryptMsgOpenToDecode( //开个Decode的小心句柄,参数和上面的Encode一样 MY_ENCODING_TYPE, 0, CMSG_DATA, NULL, NULL, NULL)) { printf("The message to decode is open. "); } else { MyHandleError(TEXT("OpenToDecode failed")); } //下面的过程和Encode类似,调用的函数和上面相同,只不过是过程逆向 printf(" The length of the encoded message is %d. ", cbEncodedBlob); if(CryptMsgUpdate( hMsg, // Handle to the message pbEncodedBlob, // Pointer to the encoded BLOB cbEncodedBlob, // Size of the encoded BLOB TRUE)) // Last call { printf("The encoded BLOB has been added to the message. "); } else { MyHandleError(TEXT("Decode MsgUpdate failed")); } if(CryptMsgGetParam( // CryptMsgGetParam的调用和上面有所不同,这里一共是调用两次,第一次的作用主要是得到消息的大小,第二次是得到消息所在的内存地址 hMsg, //消息句柄 CMSG_CONTENT_PARAM, // Parameter type 0, NULL, // Address for returned // information &cbDecoded)) // Size of the returned // information { printf("The decoded message size is %d. ", cbDecoded); } else { MyHandleError(TEXT("Decode CMSG_CONTENT_PARAM failed")); } if(pbDecoded = (BYTE *) malloc(cbDecoded)) { printf("Memory has been allocated for the decoded message. "); } else { MyHandleError(TEXT("Decoding memory allocation failed.")); } if(CryptMsgGetParam( hMsg, // Handle to the message CMSG_CONTENT_PARAM, // Parameter type 0, // Index pbDecoded, // Address for returned // information &cbDecoded)) // Size of the returned // information { printf("The message is %s. ",(LPSTR)pbDecoded); } else { MyHandleError(TEXT("Decode CMSG_CONTENT_PARAM #2 failed")); } if(pbEncodedBlob) free(pbEncodedBlob); if(pbDecoded) free(pbDecoded); if(hMsg) CryptMsgClose(hMsg); printf("This program ran to completion without error. "); } // End of main
实验5`````````````````````````````
/* 当我们已经生成了一个密钥,我们下面要做的是如何保存,导出,导入一个对话密钥。将一个密钥保存起来,导出,保存到硬盘上。这样,这个密钥就可以在其它应用程序上使用,而不会随着生成密钥程序的关闭而丢失了。 下面这段程序就是用来演示如何保存,导出一个对话密钥的。 */ #include "stdafx.h" #include <stdio.h> #include <windows.h> #include <Wincrypt.h> #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) void MyHandleError(LPTSTR psz) { _ftprintf(stderr, TEXT("An error occurred in the program. ")); _ftprintf(stderr, TEXT("%s "), psz); _ftprintf(stderr, TEXT("Error number %x. "), GetLastError()); _ftprintf(stderr, TEXT("Program terminating. ")); exit(1); } // End of MyHandleError. void main(void) { //-------------------------------------------------------------------- // Declare and initialize variables. HCRYPTPROV hProv; // CSP handle HCRYPTKEY hSignKey; // Signature key pair handle HCRYPTKEY hXchgKey; // Exchange key pair handle HCRYPTKEY hKey; // Session key handle BYTE *pbKeyBlob; // Pointer to a simple key BLOB DWORD dwBlobLen; // The length of the key BLOB //-------------------------------------------------------------------- // Acquire a cryptographic provider context handle. if(CryptAcquireContext( // 获取一个缺省容器的CSP句柄 &hProv, NULL, NULL, PROV_RSA_FULL, 0)) { printf("The CSP has been acquired. "); } else { MyHandleError(TEXT("Error during CryptAcquireContext.")); } if(CryptGetUserKey( // CryptGetUserKey是获取一个密钥//句柄的函数,成功返回TRUE hProv, //指定容器的CSP模块句柄 AT_SIGNATURE, //指定私钥的类型 &hSignKey)) //原来接收获取的密钥句柄 { _tprintf(TEXT("A signature key is available. ")); } else { _tprintf(TEXT("No signature key is available. ")); if(GetLastError() == NTE_NO_KEY) // NTE_NO_KEY意味着密钥不存在,下面就生成一个密钥 { _tprintf(TEXT("The signature key does not exist. ")); _tprintf(TEXT("Create a signature key pair. ")); if(CryptGenKey( // CryptGenKey生成一个密钥 hProv, //指定CSP模块的句柄 AT_SIGNATURE, //对于公钥密码系统,生成一个私钥和一个公钥,这个参数指定了这个密钥是公钥,于是生成了一个密码对。如果不是公钥系统,则指定了密码算法,具体看MSDN。 0, //指定了生成密钥的类型,这个参数的说明挺多的,想获取更为详尽的资料请看MSDN。 &hSignKey)) { _tprintf(TEXT("Created a signature key pair. ")); } else { MyHandleError(TEXT("Error occurred creating a ") TEXT("signature key. ")); } } else { MyHandleError(TEXT("An error other than NTE_NO_KEY ") TEXT("getting a signature key. ")); } } // End if. //-------------------------------------------------------------------- if(CryptGetUserKey( // 获取一个AT_KEYEXCHANGE,类型的密钥句柄,保存在hXchgKey中 hProv, AT_KEYEXCHANGE, &hXchgKey)) { printf("The key exchange key has been acquired. "); } else { printf("Error during CryptGetUserKey exchange key."); } // Generate a session key. if (CryptGenKey( //生成一个CRYPT_EXPORTABLE(可导出的),CALG_RC4(指定算法)的密钥,保存在hKey hProv, CALG_RC4, CRYPT_EXPORTABLE, &hKey)) { printf("Original session key is created. "); } else { MyHandleError(TEXT("ERROR -- CryptGenKey.")); } if(CryptExportKey( // CryptExportKey导出一个密钥 hKey, // 将要导出的密钥的句柄 hXchgKey, //用户最终使用到的密钥的句柄 SIMPLEBLOB, // 指定BLOB的类型,SIMPLEBLOB说明是 用来导出对话密钥的 0, // 指定密钥的附加属性 NULL, &dwBlobLen)) // 当时这个函数在这里的主要 //目的是得到这个BLOB的长度 { printf("Size of the BLOB for the session key determined. "); } else { MyHandleError(TEXT("Error computing BLOB length.")); } if(pbKeyBlob = (BYTE*)malloc(dwBlobLen)) { printf("Memory has been allocated for the BLOB. "); } else { MyHandleError(TEXT("Out of memory. ")); } if(CryptExportKey( //这是这个函数才是真正的导出密钥 hKey, hXchgKey, SIMPLEBLOB, 0, pbKeyBlob, &dwBlobLen)) { printf("Contents have been written to the BLOB. "); } else { MyHandleError(TEXT("Error during CryptExportKey.")); } free(pbKeyBlob); //释放内存 // Destroy the session key. if(hKey) CryptDestroyKey(hKey); // Destroy the signature key handle. if(hSignKey) CryptDestroyKey(hSignKey); // Destroy the key exchange key handle. if(hXchgKey) CryptDestroyKey(hXchgKey); // Release the provider handle. if(hProv) CryptReleaseContext(hProv, 0); printf("The program ran to completion without error. "); }
实验4`````````````````````````````
/* 讲如何复制一个对话密钥,照例是从一个程序讲起,完成以下任务。获取一个CSP句柄, 创建一个对话密钥,复制密钥。改变密钥生成过程,随机填充一个缓冲区,销毁密钥句柄,释放CSP句柄 */ #include "stdafx.h" #include <stdio.h> #include <tchar.h> #include <string.h> #include <conio.h> #include <windows.h> #include <Wincrypt.h> #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) void MyHandleError(LPTSTR psz) { _ftprintf(stderr, TEXT("An error occurred in the program. ")); _ftprintf(stderr, TEXT("%s "), psz); _ftprintf(stderr, TEXT("Error number %x. "), GetLastError()); _ftprintf(stderr, TEXT("Program terminating. ")); exit(1); } // End of MyHandleError. void GetConsoleInput(char* strInput, int intMaxChars) { char ch; char minChar = ' '; minChar++; ch = getch(); while (ch != ' ') { if (ch == '' && strlen(strInput) > 0) { strInput[strlen(strInput)-1] = ' '; printf(" "); } else if (ch >= minChar && strlen(strInput) < intMaxChars) { strInput[strlen(strInput)+1] = ' '; strInput[strlen(strInput)] = ch; putch('*'); } ch = getch(); } putch(' '); } void main() { //------------------------------------------------------------------- // Declare and initialize variables. HCRYPTPROV hCryptProv; // CSP句柄 HCRYPTKEY hOriginalKey; // 源密钥句柄 HCRYPTKEY hDuplicateKey; // 复制后的密钥句柄 DWORD dwMode; BYTE pbData[16]; printf("This program creates a session key and duplicates "); printf("that key. Next, parameters are added to the original "); printf("key. Finally, both keys are destroyed. "); if(CryptAcquireContext( // 获取CSP句柄,前面叙述过了,这里就不叙述了 &hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) { printf("CryptAcquireContext succeeded. "); } else { MyHandleError(TEXT("Error during CryptAcquireContext! ")); } //------------------------------------------------------------------- if (CryptGenKey( // 生成一个CALG_RC4算法生成的密钥,保存在hOriginalKey中 hCryptProv, CALG_RC4, // ALG_ID结构,指定生成这个密钥使用的算法 0, &hOriginalKey)) { printf("Original session key is created. "); } else { MyHandleError(TEXT("ERROR - CryptGenKey.")); } if (CryptDuplicateKey( // 复制密钥 hOriginalKey, // 源密钥 NULL, // 保留参数,必须为NULL 0, // 保留参数,必须为0 &hDuplicateKey)) // 副本密钥 { printf("The session key has been duplicated. "); } else { MyHandleError(TEXT("ERROR - CryptDuplicateKey")); } // 给源密钥设置附加参数 dwMode = CRYPT_MODE_ECB; //CRYPT_MODE_ECB是一个没有反馈的块加密模式 if(CryptSetKeyParam( hOriginalKey, KP_MODE, // KP_MODE指定密钥的某种属性被改变, // 意味着改变的是加密模式 (BYTE*)&dwMode, // 指向一个已经被初始化的缓冲区 0)) { printf("Key Parameters set. "); } else { MyHandleError(TEXT("Error during CryptSetKeyParam.")); } if(CryptGenRandom( // 随机填充一块缓冲区 hCryptProv, // CSP句柄 8, // 缓冲区大小 pbData)) // 缓冲区地址 { printf("Random sequence generated. "); } else { MyHandleError(TEXT("Error during CryptGenRandom.")); } if(CryptSetKeyParam( //再次给密钥设置属性 hOriginalKey, KP_IV, // KP_IV意味着,这个函数的第三个参数指向一个BYTE数组,数组大小为块大小/8。 pbData, 0)) { printf("Parameter set with random sequence as " "initialization vector. "); } else { MyHandleError(TEXT("Error during CryptSetKeyParam.")); } //------------------------------------------------------------------- if (hOriginalKey) // 以下依次销毁,释放源密钥句柄,副本句柄,CSP句柄, if (!CryptDestroyKey(hOriginalKey)) MyHandleError(TEXT("Failed CryptDestroyKey ")); if (hDuplicateKey) if (!CryptDestroyKey(hDuplicateKey)) MyHandleError(TEXT("Failed CryptDestroyKey ")); if(hCryptProv) if (!CryptReleaseContext(hCryptProv, 0)) MyHandleError(TEXT("Failed CryptReleaseContext ")); printf(" The program ran to completion without error. "); } // End of main.
实验3`````````````````````````````
/*任务一:调用CryptAcquireContext,获取一个缺省CSP和缺省密钥容器的句柄 任务二:用CryptCreateHash去创建一个空的哈希对象 任务三:用CryptHashData.哈希密码 任务四:调用CryptDeriveKey获取一个对话密钥 任务五:销毁密码和哈希后的数据 任务六:释放CSP */ #include "stdafx.h" #include <stdio.h> #include <tchar.h> #include <string.h> #include <conio.h> #include <windows.h> #include <Wincrypt.h> void MyHandleError(LPTSTR psz) { _ftprintf(stderr, TEXT("An error occurred in the program. ")); _ftprintf(stderr, TEXT("%s "), psz); _ftprintf(stderr, TEXT("Error number %x. "), GetLastError()); _ftprintf(stderr, TEXT("Program terminating. ")); exit(1); } // End of MyHandleError. void GetConsoleInput(char* strInput, int intMaxChars) { char ch; char minChar = ' '; minChar++; ch = getch(); while (ch != ' ') { if (ch == '' && strlen(strInput) > 0) { strInput[strlen(strInput)-1] = ' '; printf(" "); } else if (ch >= minChar && strlen(strInput) < intMaxChars) { strInput[strlen(strInput)+1] = ' '; strInput[strlen(strInput)] = ch; putch('*'); } ch = getch(); } putch(' '); } void main() { HCRYPTPROV hCryptProv; // 定义CSP句柄 HCRYPTKEY hKey; // 定义密钥句柄 HCRYPTHASH hHash; // 定义一个HASH对象的句柄 CHAR szPassword[512] = ""; // 定义512大小的字符数组,用来保存密码 DWORD dwLength; // 保存密码长度 fprintf(stderr,"Enter a password to be used to create a key:"); GetConsoleInput(szPassword, 512); // 获取密码,这个是自己写的函数,目的是在屏幕上显示的是*。 printf("The password has been stored. "); dwLength = strlen(szPassword); if(CryptAcquireContext( //以下是获取一个缺省的PROV_RSA_FULL CSP 句柄 &hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) { printf("A context has been acquired. "); } else { MyHandleError(TEXT("Error during CryptAcquireContext!")); } //-------------------------------------------------------------------- if(CryptCreateHash( // 调用CryptCreateHash创建一个HASH对象 hCryptProv, // 一个CSP句柄 CALG_MD5, // 确定哈希算法 8003h 0, //对于非密钥算法,这个参数一定是0,如果是密钥算法,那么这个参数就是密钥 0, // 保留参数,为0 &hHash)) // 一个哈希对象的指针 { printf("An empty hash object has been created. "); } else { MyHandleError(TEXT("Error during CryptCreateHash!")); } //-------------------------------------------------------------------- if(CryptHashData( // 调用CryptHashData哈希密码 hHash, // 哈希对象 (BYTE *)szPassword, // 指向缓冲区的地址 dwLength, // 密码长度 0)) { printf("The password has been hashed. "); } else { MyHandleError(TEXT("Error during CryptHashData!")); } //-------------------------------------------------------------------- if(CryptDeriveKey( //调用CryptDeriveKey获取对话密码 hCryptProv, // CSP句柄 CALG_RC2, // 6602h 一个ALG_ID结构,用来指定对称密钥生成的算法 hHash, // 哈希对象 CRYPT_EXPORTABLE, //指定生成密钥的类型,CRYPT_EXPORTABLE意味着这个程序生成的密钥可以被其它程序调用,而不是仅仅限于这个程序当中。但是它不能用于非对称密码中。 &hKey)) { printf("The key has been derived. "); } else { MyHandleError(TEXT("Error during CryptDeriveKey!")); } if(hHash) // 销毁哈希对象 { if(!(CryptDestroyHash(hHash))) MyHandleError(TEXT("Error during CryptDestroyHash")); } if(hKey) // 销毁密钥句柄 { if(!(CryptDestroyKey(hKey))) MyHandleError(TEXT("Error during CryptDestroyKey")); } if(hCryptProv) // 销毁CSP句柄 { if(!(CryptReleaseContext(hCryptProv, 0))) MyHandleError(TEXT("Error during CryptReleaseContext")); } printf("The program to derive a key completed without error. "); } // end main
实验2`````````````````````````````
/*这个程序演示了以下内容和几个函数。 一. 用CryptAcquireContext获取一个缺省容器的缺省CSP的句柄。如果缺省容器不存在,用CryptAcquireContext创建一个。 二. 用CryptGetProvParam获取CSP和容器的信息。 三. 用CryptContextAddRef增加CSP的引用计数器的数值。 四. 用CryptAcquireContext创建一个指定的容器 五. 用CryptAcquireContext删除一个容器 六. 用一个新创建的容器获取一个CSP的句柄。 */ #include <stdio.h> #include "stdafx.h" #include <tchar.h> #include <windows.h> #include <Wincrypt.h> void MyHandleError(LPTSTR psz) { _ftprintf(stderr, TEXT("An error occurred in the program. ")); _ftprintf(stderr, TEXT("%s "), psz); _ftprintf(stderr, TEXT("Error number %x. "), GetLastError()); _ftprintf(stderr, TEXT("Program terminating. ")); exit(1); } // End of MyHandleError. void main(void) { HCRYPTPROV hCryptProv; //定义CSP句柄 if(CryptAcquireContext( &hCryptProv, NULL, //缺省容器 NULL, //缺省CSP PROV_RSA_FULL, 0)) { _tprintf(TEXT("CryptAcquireContext succeeded. ")); } else { if (GetLastError() == NTE_BAD_KEYSET) //同样,如果当不存在这样的容器的时候,创建一个 { if(CryptAcquireContext( &hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { _tprintf(TEXT("CryptAcquireContext succeeded. ")); } else { MyHandleError(TEXT("Could not create the default ") TEXT("key container. ")); } } 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. ")); printf("Provider name: %s ", pszName); } else { MyHandleError(TEXT("Error reading CSP name. ")); } //--------------------------------------------------------------- // Read the name of the key container. cbName = 1000; if(CryptGetProvParam( hCryptProv, PP_CONTAINER, //获取容器名字 (BYTE*)pszName, &cbName, 0)) { _tprintf(TEXT("CryptGetProvParam succeeded. ")); printf("Key Container name: %s ", pszName); } else { MyHandleError(TEXT("Error reading key container name. ")); } //增加CSP的引用计数器的数值。 if(CryptContextAddRef( // CryptContextAddRef是向一个CSP的引用计数器增加一个值的函数 hCryptProv, NULL, //保留值,必须为NULL 0)) //保留值,必须为0 { _tprintf(TEXT("CryptcontextAddRef succeeded. ")); } else { MyHandleError(TEXT("Error during CryptContextAddRef! ")); } //--------------------------------------------------------------- // 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. ")); } else { MyHandleError(TEXT("Error during ") TEXT("CryptReleaseContext #1! ")); } if (CryptReleaseContext(hCryptProv, 0)) //再次释放CSP模块 { _tprintf(TEXT("The second call to CryptReleaseContext ") TEXT("succeeded. ")); } else { MyHandleError(TEXT("Error during ") TEXT("CryptReleaseContext #2! ")); } //下面是从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. ")); _tprintf(TEXT("New key set created. ")); //----------------------------------------------------------- // Release the provider handle and the key container. if(hCryptProv) { if(CryptReleaseContext(hCryptProv, 0)) { hCryptProv = NULL; _tprintf(TEXT("CryptReleaseContext succeeded. ")); } else { MyHandleError(TEXT("Error during ") TEXT("CryptReleaseContext! ")); } } } else { if(GetLastError() == NTE_EXISTS) { _tprintf(TEXT("The named key container could not be ") TEXT("created because it already exists. ")); } 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. ")); } else { MyHandleError(TEXT("Error during CryptAcquireContext! ")); } //--------------------------------------------------------------- // Perform cryptographic operations. //--------------------------------------------------------------- if(CryptReleaseContext( hCryptProv, 0)) { _tprintf(TEXT("CryptReleaseContext succeeded. ")); } else { MyHandleError(TEXT("Error during CryptReleaseContext! ")); } if(CryptAcquireContext( &hCryptProv, pszContainerName, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET)) //CRYPT_DELETEKEYSET意味着CryptAcquireContex删除一个指定的容器 { _tprintf(TEXT("Deleted the key container just created. ")); } else { MyHandleError(TEXT("Error during CryptAcquireContext! ")); } }
实验1`````````````````````````````
#include "stdafx.h" #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. ")); _ftprintf(stderr, TEXT("%s "), psz); _ftprintf(stderr, TEXT("Error number %x. "), GetLastError()); _ftprintf(stderr, TEXT("Program terminating. ")); exit(1); } // End of MyHandleError. int _tmain(int argc, _TCHAR* argv[]) { 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. "), 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. ")); } else { MyHandleError(TEXT("Could not create a new key ") TEXT("container. ")); } } else { MyHandleError(TEXT("CryptAcquireContext failed. ")); } } HCRYPTKEY hKey; //创建一个密钥句柄 if(CryptGetUserKey( // CryptGetUserKey是获取一个密钥//句柄的函数,成功返回TRUE hCryptProv, //指定容器的CSP模块句柄 AT_SIGNATURE, //指定私钥的类型 &hKey)) //原来接收获取的密钥句柄 { _tprintf(TEXT("A signature key is available. ")); } else { _tprintf(TEXT("No signature key is available. ")); if(GetLastError() == NTE_NO_KEY) // NTE_NO_KEY意味着密钥不存在,下面就生成一个密钥 { _tprintf(TEXT("The signature key does not exist. ")); _tprintf(TEXT("Create a signature key pair. ")); if(CryptGenKey( // CryptGenKey生成一个密钥 hCryptProv, //指定CSP模块的句柄 AT_SIGNATURE, //对于公钥密码系统,生成一个私钥和一个公钥,这个参数指定了这个密钥是公钥,于是生成了一个密码对。如果不是公钥系统,则指定了密码算法,具体看MSDN。 0, //指定了生成密钥的类型,这个参数的说明挺多的,想获取更为详尽的资料请看MSDN。 &hKey)) { _tprintf(TEXT("Created a signature key pair. ")); } else { MyHandleError(TEXT("Error occurred creating a ") TEXT("signature key. ")); } } else { MyHandleError(TEXT("An error other than NTE_NO_KEY ") TEXT("getting a signature key. ")); } } // End if. _tprintf(TEXT("A signature key pair existed, or one was ") TEXT("created. ")); if(hKey) //将密钥句柄销毁 { if(!(CryptDestroyKey(hKey))) { MyHandleError(TEXT("Error during CryptDestroyKey.")); } hKey = NULL; } //下面这部分和上面是类似的,只不过密钥类型不相同而已。 if(CryptGetUserKey( hCryptProv, AT_KEYEXCHANGE, &hKey)) { _tprintf(TEXT("An exchange key exists. ")); } else { _tprintf(TEXT("No exchange key is available. ")); // 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. ")); _tprintf(TEXT("Attempting to create an exchange key ") TEXT("pair. ")); if(CryptGenKey( hCryptProv, AT_KEYEXCHANGE, 0, &hKey)) { _tprintf(TEXT("Exchange key pair created. ")); } else { MyHandleError(TEXT("Error occurred attempting to ") TEXT("create an exchange key. ")); } } else { MyHandleError(TEXT("An error other than NTE_NO_KEY ") TEXT("occurred. ")); } } // 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. "), pszContainerName); return 0; }
转载至: http://bbs.pediy.com/showthread.php?t=31357&highlight=Crypto+API