前言
看见一个Demo中有使用CryptAPI加密的代码.
查了资料,先写一个能用的CryptAPI加密例子, 预测一下Demo中的CryptAPI的调用流程.
等还原完,如果Demo写的有特色, 再整理一个Demo玩.
试验
// @file rsaEncrypt\hw.cpp
//#include "stdafx.h"#ifndef _WIN32_WINNT // Allow use of features specific to Windows 2000 or later.
#define _WIN32_WINNT 0x0500 // Change this to the appropriate value to target other versions of Windows.
#endif#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
#include <math.h>#include <wincrypt.h>
#pragma comment(lib, "Crypt32")static BYTE PrivateKeyWithExponentOfOne[] = {0x07, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00,0x52, 0x53, 0x41, 0x32, 0x00, 0x02, 0x00, 0x00,0x01, 0x00, 0x00, 0x00, 0xAB, 0xEF, 0xFA, 0xC6,0x7D, 0xE8, 0xDE, 0xFB, 0x68, 0x38, 0x09, 0x92,0xD9, 0x42, 0x7E, 0x6B, 0x89, 0x9E, 0x21, 0xD7,0x52, 0x1C, 0x99, 0x3C, 0x17, 0x48, 0x4E, 0x3A,0x44, 0x02, 0xF2, 0xFA, 0x74, 0x57, 0xDA, 0xE4,0xD3, 0xC0, 0x35, 0x67, 0xFA, 0x6E, 0xDF, 0x78,0x4C, 0x75, 0x35, 0x1C, 0xA0, 0x74, 0x49, 0xE3,0x20, 0x13, 0x71, 0x35, 0x65, 0xDF, 0x12, 0x20,0xF5, 0xF5, 0xF5, 0xC1, 0xED, 0x5C, 0x91, 0x36,0x75, 0xB0, 0xA9, 0x9C, 0x04, 0xDB, 0x0C, 0x8C,0xBF, 0x99, 0x75, 0x13, 0x7E, 0x87, 0x80, 0x4B,0x71, 0x94, 0xB8, 0x00, 0xA0, 0x7D, 0xB7, 0x53,0xDD, 0x20, 0x63, 0xEE, 0xF7, 0x83, 0x41, 0xFE,0x16, 0xA7, 0x6E, 0xDF, 0x21, 0x7D, 0x76, 0xC0,0x85, 0xD5, 0x65, 0x7F, 0x00, 0x23, 0x57, 0x45,0x52, 0x02, 0x9D, 0xEA, 0x69, 0xAC, 0x1F, 0xFD,0x3F, 0x8C, 0x4A, 0xD0,0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x64, 0xD5, 0xAA, 0xB1,0xA6, 0x03, 0x18, 0x92, 0x03, 0xAA, 0x31, 0x2E,0x48, 0x4B, 0x65, 0x20, 0x99, 0xCD, 0xC6, 0x0C,0x15, 0x0C, 0xBF, 0x3E, 0xFF, 0x78, 0x95, 0x67,0xB1, 0x74, 0x5B, 0x60,0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};int _tmain(int argc, _TCHAR* argv[])
{HCRYPTPROV hProv = NULL;HCRYPTKEY hPrivateKey = NULL;HCRYPTKEY hPublicKey = NULL;HCRYPTKEY hSessionKey = NULL;BOOL bStatus = FALSE;const char* szPassword = "password";DWORD dwPasswordLen = (DWORD) strlen(szPassword);LPBYTE pEncryptedData = NULL;DWORD i, dwKeyLen = 0, dwValLen = 0;DWORD dwEncryptedDataLen = 0;/** We suppose here that the default container exists and* that it contains an RSA exchange key pair .*/bStatus = CryptAcquireContext(&hProv,NULL, /* default container */MS_DEF_PROV,PROV_RSA_FULL,0);if (!bStatus) {printf("CryptAcquireContext failed with error 0x%.8X\n", GetLastError());goto error;}// 导入密钥if (!CryptImportKey(hProv, PrivateKeyWithExponentOfOne, sizeof(PrivateKeyWithExponentOfOne), 0, 0, &hPrivateKey)) {printf("Error CryptImportKey() failed. 0x%.8X\n", GetLastError());goto error;}/*// 产生会话密钥if (!CryptGenKey(hProv, CALG_RSA_KEYX, CRYPT_EXPORTABLE, &hSessionKey)) {printf("Error CryptGenKey() failed. 0x%.8X\n", GetLastError());goto error;}*/// 得到公钥bStatus = CryptGetUserKey(hProv,AT_KEYEXCHANGE,&hPublicKey);if (!bStatus) {printf("CryptGetUserKey failed with error 0x%.8X\n", GetLastError());goto error;}/** get the size of the key*/dwValLen = sizeof(DWORD);bStatus = CryptGetKeyParam(hPublicKey,KP_KEYLEN,(LPBYTE) &dwKeyLen,&dwValLen,0);if (!bStatus) {printf("CryptGetKeyParam failed with error 0x%.8X\n", GetLastError());goto error;}/** Allocate input/output buffer*/dwKeyLen = (dwKeyLen + 7) / 8; /* tranform to bytes length */pEncryptedData = (LPBYTE) LocalAlloc(0, dwKeyLen);if (!pEncryptedData) {printf("LocalAlloc failed with error 0x%.8X\n", GetLastError());goto error;}/** copy password to the buffer*/ZeroMemory(pEncryptedData, dwKeyLen);CopyMemory(pEncryptedData, szPassword, dwPasswordLen);dwEncryptedDataLen = dwPasswordLen;bStatus = CryptEncrypt(hPublicKey,NULL,TRUE,0,pEncryptedData,&dwEncryptedDataLen,dwKeyLen);if (!bStatus) {printf("CryptEncrypt failed with error 0x%.8X\n", GetLastError());goto error;}printf("Password encrypted successfully :\n\tlength = %d bytes.\n\tValue = ", (int) dwEncryptedDataLen);for (i = 0; i < dwEncryptedDataLen; i++) {printf("%.2X", pEncryptedData[i]);}printf("\n\n");/** verifying encryption result*/printf("Verifying encryption result...\r\n");// 换成 hPublicKey 也能解开, 堆成加密么?bStatus = CryptDecrypt(hPrivateKey,NULL,TRUE,0,pEncryptedData,&dwEncryptedDataLen);if (!bStatus) {printf("CryptDecrypt failed with error 0x%.8X\n", GetLastError());goto error;}if ((dwEncryptedDataLen != dwPasswordLen) ||(0 != memcmp(pEncryptedData, szPassword, dwPasswordLen))) {printf("\nVerification failed!!\n");} else {printf("Decrypt result = %s\r\n", (char*)pEncryptedData);printf("\nSucess.\n");}error:if (NULL != pEncryptedData) {LocalFree(pEncryptedData);pEncryptedData = NULL;}if (NULL != hPublicKey) {CryptDestroyKey(hPublicKey);hPublicKey = NULL;}if (NULL != hPrivateKey) {CryptDestroyKey(hPrivateKey);hPrivateKey = NULL;}if (NULL != hProv) {CryptReleaseContext(hProv, 0);hProv = NULL;}/** run resultPassword encrypted successfully :length = 64 bytes.Value = 64726F777373617000E030312B9C252536C83F34F7EC3E47D554E9B188DD25E81BDAF9CB18F3ABE3693389BCDB1C224741A858E35954170115E82FC16C530200Verifying encryption result...Decrypt result = passwordSucess.请按任意键继续. . .*/system("pause");return 0;
}