-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBcryptWin32ApiExample.c
145 lines (124 loc) · 3.47 KB
/
BcryptWin32ApiExample.c
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
#include <windows.h>
#include <bcrypt.h>
#include <stdio.h>
#pragma comment(lib, "bcrypt.lib")
static NTSTATUS EncryptPassword(PUCHAR password, PUCHAR* hash, DWORD* hashSize, PUCHAR secret, DWORD secretSize)
{
BCRYPT_ALG_HANDLE hAlg = NULL;
BCRYPT_HASH_HANDLE hHash = NULL;
NTSTATUS status = 0;
DWORD cbData = 0, cbHash = 0, cbHashObject = 0;
PBYTE pbHashObject = NULL;
DWORD passwordSize = strlen((char*)password);
status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA512_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG);
if (!(((NTSTATUS)(status)) >= 0))
{
printf_s("BCryptOpenAlgorithmProvider failed with status: 0x%x\n", status);
goto Cleanup;
}
status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbHashObject, sizeof(DWORD), &cbData, 0);
if (!(((NTSTATUS)(status)) >= 0))
{
printf_s("BCryptGetProperty failed with status: 0x%x\n", status);
goto Cleanup;
}
pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
if (NULL == pbHashObject)
{
printf_s("HeapAlloc failed\n");
goto Cleanup;
}
status = BCryptCreateHash(hAlg, &hHash, pbHashObject, cbHashObject, secret, secretSize, 0);
if (!(((NTSTATUS)(status)) >= 0))
{
printf_s("BCryptCreateHash failed with status: 0x%x\n", status);
goto Cleanup;
}
status = BCryptHashData(hHash, password, passwordSize, 0);
if (!(((NTSTATUS)(status)) >= 0))
{
printf_s("BCryptHashData failed with status: 0x%x\n", status);
goto Cleanup;
}
status = BCryptGetProperty(hHash, BCRYPT_HASH_LENGTH, (PBYTE)hashSize, sizeof(DWORD), &cbData, 0);
if (!(((NTSTATUS)(status)) >= 0))
{
printf_s("BCryptGetProperty failed with status: 0x%x\n", status);
goto Cleanup;
}
*hash = (PUCHAR)malloc(*hashSize);
status = BCryptFinishHash(hHash, *hash, *hashSize, NULL);
if (status == STATUS_INVALID_PARAMETER)
{
printf_s("BCryptFinishHash failed with status: 0x%x\n", status);
printf_s("Error code: STATUS_INVALID_PARAMETER\n");
goto Cleanup;
}
else if (status == STATUS_INVALID_HANDLE)
{
printf_s("BCryptFinishHash failed with status: 0x%x\n", status);
printf_s("Error code: STATUS_INVALID_HANDLE\n");
goto Cleanup;
}
Cleanup:
if (hAlg)
{
BCryptCloseAlgorithmProvider(hAlg, 0);
}
if (hHash)
{
BCryptDestroyHash(hHash);
}
if (pbHashObject)
{
HeapFree(GetProcessHeap(), 0, pbHashObject);
}
return status;
}
static NTSTATUS ValidatePassword(PUCHAR inputPassword, PUCHAR storedHash, ULONG hashSize, PUCHAR secret, DWORD secretSize)
{
PUCHAR inputHash;
ULONG inputHashSize;
NTSTATUS status = EncryptPassword(inputPassword, &inputHash, &inputHashSize, secret, secretSize);
if (!(((NTSTATUS)(status)) >= 0))
{
printf_s("EncryptPassword failed with status: 0x%x\n", status);
return status;
}
if (inputHashSize != hashSize)
{
printf_s("Hash size mismatch\n");
return STATUS_INVALID_PARAMETER;
}
if (memcmp(inputHash, storedHash, hashSize) == 0)
{
printf_s("Password is valid\n");
return 1;
}
else
{
printf_s("Password is invalid\n");
return STATUS_INVALID_PARAMETER;
}
}
int main()
{
UCHAR password[] = "password";
UCHAR secret[] = "top_secret";
PUCHAR hash = NULL;
NTSTATUS status = 0;
DWORD hashSize = 0;
status = EncryptPassword(password, &hash, &hashSize, secret, sizeof(UCHAR) * ARRAYSIZE(secret));
if (status == 0)
{
printf_s("Hash: ");
for (int i = 0; i < hashSize; i++)
{
printf_s("%02x", hash[i]);
}
printf_s("\n");
}
status = ValidatePassword(password, hash, hashSize, secret, sizeof(UCHAR) * ARRAYSIZE(secret));
free(hash);
return status;
}