HASH计算 & AES算法调用

HASH就是把任意长度的输入通过HASH算法变换成固定长度的输出,该输出就是HASH值。HASH值的空间通常远小于输入值的空间,不同的输入可能会得到相同的输出,所以不可能利用HASH值来确定唯 一的输入值。基于这种特性,HASH值常用来执行数据完整性校验。

  • 获取CSP的密钥容器句柄
  • 创建HASH对象、指定算法
  • 计算HASH
  • 从HASH对象查询HASH信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#include<stdio.h>
#include<windows.h>

BOOL GetFileData(char *pszFilePath, BYTE **ppFileData, DWORD *pdwFileDataLength);
BOOL CalculateHash(BYTE *pData, DWORD dwDataLength, ALG_ID algHashType, BYTE **ppHashData, DWORD *pdwHashDataLength);

int main ()
{
BYTE *pData = NULL;
DWORD dwDataLength = 0;
DWORD i = 0;
BYTE *pHashData = NULL;
DWORD dwHashDataLength = 0;

// 读取文件数据
GetFileData("C:\\users\\john\\desktop\\calc.exe", &pData, &dwDataLength);

// MD5
CalculateHash(pData, dwDataLength, CALG_MD5, &pHashData, &dwHashDataLength);
printf("MD5[%d]\n", dwHashDataLength);
for (i = 0; i < dwHashDataLength; i++)
{
printf("%x", pHashData[i]);
}
printf("\n\n", dwHashDataLength);
if (pHashData)
{
delete[]pHashData;
pHashData = NULL;
}

// SHA1
CalculateHash(pData, dwDataLength, CALG_SHA1, &pHashData, &dwHashDataLength);
printf("SHA1[%d]\n", dwHashDataLength);
for (i = 0; i < dwHashDataLength; i++)
{
printf("%x", pHashData[i]);
}
printf("\n\n", dwHashDataLength);
if (pHashData)
{
delete[]pHashData;
pHashData = NULL;
}

// SHA256
CalculateHash(pData, dwDataLength, CALG_SHA_256, &pHashData, &dwHashDataLength);
printf("SHA256[%d]\n", dwHashDataLength);
for (i = 0; i < dwHashDataLength; i++)
{
printf("%x", pHashData[i]);
}
printf("\n\n", dwHashDataLength);
if (pHashData)
{
delete[]pHashData;
pHashData = NULL;
}

system("pause");
return 0;
}
BOOL GetFileData(char *pszFilePath, BYTE **ppFileData, DWORD *pdwFileDataLength)
{
BOOL bRet = TRUE;
BYTE *pFileData = NULL;
DWORD dwFileDataLength = 0;
HANDLE hFile = NULL;
DWORD dwTemp = 0;


hFile = CreateFile(pszFilePath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_ARCHIVE, NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
bRet = FALSE;
return bRet;
}

dwFileDataLength = GetFileSize(hFile, NULL);
pFileData = new BYTE[dwFileDataLength];
if (NULL == pFileData)
{
bRet = FALSE;
return bRet;
}
RtlZeroMemory(pFileData, dwFileDataLength);
ReadFile(hFile, pFileData, dwFileDataLength, &dwTemp, NULL);

// 返回
*ppFileData = pFileData;
*pdwFileDataLength = dwFileDataLength;

if (hFile)
{
CloseHandle(hFile);
}

return bRet;
}

BOOL CalculateHash(BYTE *pData, DWORD dwDataLength, ALG_ID algHashType, BYTE **ppHashData, DWORD *pdwHashDataLength)
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hCryptHash = NULL;
BYTE *pHashData = NULL;
DWORD dwHashDataLength = 0;
DWORD dwTemp = 0;
BOOL bRet = FALSE;


// 获得默认CSP的密钥容器的句柄
bRet = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);//PROV_RSA_AES 支持RSA、AES、HASH
if (FALSE == bRet)
{
bRet = FALSE;
return bRet;
}

// 创建一个HASH对象, 指定HASH算法
bRet = CryptCreateHash(hCryptProv, algHashType, NULL, NULL, &hCryptHash);
if (FALSE == bRet)
{
bRet = FALSE;
return bRet;
}

// 计算HASH数据
bRet = CryptHashData(hCryptHash, pData, dwDataLength, 0);
if (FALSE == bRet)
{
bRet = FALSE;
return bRet;
}

// 获取HASH结果的大小
dwTemp = sizeof(dwHashDataLength);
bRet = CryptGetHashParam(hCryptHash, HP_HASHSIZE, (BYTE *)(&dwHashDataLength), &dwTemp, 0);
if (FALSE == bRet)
{
bRet = FALSE;
return bRet;
}

// 申请内存
pHashData = new BYTE[dwHashDataLength];
if (NULL == pHashData)
{
bRet = FALSE;
return bRet;
}
RtlZeroMemory(pHashData, dwHashDataLength);

// 获取HASH结果数据
bRet = CryptGetHashParam(hCryptHash, HP_HASHVAL, pHashData, &dwHashDataLength, 0);
if (FALSE == bRet)
{
bRet = FALSE;
return bRet;
}

// 返回数据
*ppHashData = pHashData;
*pdwHashDataLength = dwHashDataLength;


// 释放关闭
if (FALSE == bRet)
{
if (pHashData)
{
delete[]pHashData;
pHashData = NULL;
}
}
if (hCryptHash)
{
CryptDestroyHash(hCryptHash);
}
if (hCryptProv)
{
CryptReleaseContext(hCryptProv, 0);
}

return bRet;
}

AES高级加密标准为最常见的对称加密算法,所谓对称加密算法也就是加密和解密使用相同密钥的加 密算法。AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据, 直到加密完整个明文。AES对称加密算法的优势在于算法公开,计算量小,加密效率高。

  • 获取加密服务提供程序的句柄
  • 明文密钥的MD5值作为基础密钥通过调用CryptDeriveKey函数来派生出AES的加密密钥
  • 在计算出明文密码的MD5值后,调用CryptDeriveKey函数来派生密钥。
  • 完成派生密钥后,调用CryptEncrypt函数来根据派生密钥中指定的加密算法进行加密运算。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include<windows.h>
#include<stdio.h>
BOOL AesEncrypt(BYTE *pPassword, DWORD dwPasswordLength, BYTE *pData, DWORD &dwDataLength, DWORD dwBufferLength);
BOOL AesDecrypt(BYTE *pPassword, DWORD dwPasswordLength, BYTE *pData, DWORD &dwDataLength, DWORD dwBufferLength);

int main()
{

BYTE pData[MAX_PATH] = { 0 };
DWORD dwDataLength = 0, dwBufferLength = MAX_PATH;
DWORD i = 0;

RtlZeroMemory(pData, dwBufferLength);
lstrcpy((char *)pData, "AES DemoGan");
dwDataLength = 1 + lstrlen((char *)pData);

printf("Text[%d]\n", dwDataLength);
printf("%s ", pData);
printf("\n\n");

// AES 加密
AesEncrypt((BYTE *)"yeanhoo", 7, pData, dwDataLength, dwBufferLength);

printf("AES Encrypt[%d]\n", dwDataLength);
printf("%s", pData);
printf("\n\n");

// AES 解密
AesDecrypt((BYTE *)"yeanhoo", 7, pData, dwDataLength, dwBufferLength);

printf("AES Decrypt[%d]\n", dwDataLength);
printf("%s ", pData);
printf("\n\n");

system("pause");
return 0;
}

BOOL AesEncrypt(BYTE *pPassword, DWORD dwPasswordLength, BYTE *pData, DWORD &dwDataLength, DWORD dwBufferLength)
{
BOOL bRet = TRUE;
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hCryptHash = NULL;
HCRYPTKEY hCryptKey = NULL;


// 获取CSP句柄
bRet = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
if (FALSE == bRet)
{
return bRet;
}

// 创建HASH对象
bRet = CryptCreateHash(hCryptProv, CALG_MD5, NULL, 0, &hCryptHash);
if (FALSE == bRet)
{
return bRet;
}

// 对密钥进行HASH计算
bRet = CryptHashData(hCryptHash, pPassword, dwPasswordLength, 0);
if (FALSE == bRet)
{
return bRet;
}

// 使用HASH来生成密钥
bRet = CryptDeriveKey(hCryptProv, CALG_AES_128, hCryptHash, CRYPT_EXPORTABLE, &hCryptKey);
if (FALSE == bRet)
{
return bRet;
}

// 加密数据
bRet = CryptEncrypt(hCryptKey, NULL, TRUE, 0, pData, &dwDataLength, dwBufferLength);
if (FALSE == bRet)
{
return bRet;
}


// 关闭释放
if (hCryptKey)
{
CryptDestroyKey(hCryptKey);
}
if (hCryptHash)
{
CryptDestroyHash(hCryptHash);
}
if (hCryptProv)
{
CryptReleaseContext(hCryptProv, 0);
}

return bRet;
}

BOOL AesDecrypt(BYTE *pPassword, DWORD dwPasswordLength, BYTE *pData, DWORD &dwDataLength, DWORD dwBufferLength)
{
BOOL bRet = TRUE;
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hCryptHash = NULL;
HCRYPTKEY hCryptKey = NULL;


// 获取CSP句柄
bRet = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
if (FALSE == bRet)
{
return bRet;
}

// 创建HASH对象
bRet = CryptCreateHash(hCryptProv, CALG_MD5, NULL, 0, &hCryptHash);
if (FALSE == bRet)
{
return bRet;
}

// 对密钥进行HASH计算
bRet = CryptHashData(hCryptHash, pPassword, dwPasswordLength, 0);
if (FALSE == bRet)
{
return bRet;
}

// 使用HASH来生成密钥
bRet = CryptDeriveKey(hCryptProv, CALG_AES_128, hCryptHash, CRYPT_EXPORTABLE, &hCryptKey);
if (FALSE == bRet)
{
return bRet;
}

// 解密数据
bRet = CryptDecrypt(hCryptKey, NULL, TRUE, 0, pData, &dwDataLength);
if (FALSE == bRet)
{
return bRet;
}

// 关闭释放
if (hCryptKey)
{
CryptDestroyKey(hCryptKey);
}
if (hCryptHash)
{
CryptDestroyHash(hCryptHash);
}
if (hCryptProv)
{
CryptReleaseContext(hCryptProv, 0);
}

return bRet;
}