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
|
#include "stdafx.h"
#pragma comment(lib, "crypt32.lib")
int CSteamProto::RsaEncrypt(const char *pszModulus, DWORD &exponent, const char *data, BYTE *encryptedData, DWORD &encryptedSize)
{
DWORD cchModulus = (DWORD)mir_strlen(pszModulus);
int result;
HCRYPTKEY phKey = 0;
HCRYPTPROV hCSP = 0;
__try {
// convert hex string to byte array
DWORD cbLen = 0, dwSkip = 0, dwFlags = 0;
if (!CryptStringToBinaryA(pszModulus, cchModulus, CRYPT_STRING_HEX, nullptr, &cbLen, &dwSkip, &dwFlags)) {
result = GetLastError();
__leave;
}
// allocate a new buffer.
mir_ptr<BYTE> pbBuffer((BYTE *)mir_alloc(cbLen));
if (!CryptStringToBinaryA(pszModulus, cchModulus, CRYPT_STRING_HEX, pbBuffer, &cbLen, &dwSkip, &dwFlags)) {
result = GetLastError();
__leave;
}
// reverse byte array, because of microsoft
for (int i = 0; i < (int)(cbLen / 2); ++i) {
BYTE temp = pbBuffer[cbLen - i - 1];
pbBuffer[cbLen - i - 1] = pbBuffer[i];
pbBuffer[i] = temp;
}
if (!CryptAcquireContext(&hCSP, nullptr, nullptr, PROV_RSA_AES, CRYPT_SILENT) &&
!CryptAcquireContext(&hCSP, nullptr, nullptr, PROV_RSA_AES, CRYPT_SILENT | CRYPT_NEWKEYSET)) {
result = GetLastError();
__leave;
}
// Move the key into the key container.
DWORD cbKeyBlob = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + cbLen;
mir_ptr<BYTE> pKeyBlob((BYTE *)mir_alloc(cbKeyBlob));
// Fill in the data.
PUBLICKEYSTRUC *pPublicKey = (PUBLICKEYSTRUC *)pKeyBlob.get();
pPublicKey->bType = PUBLICKEYBLOB;
pPublicKey->bVersion = CUR_BLOB_VERSION; // Always use this value.
pPublicKey->reserved = 0; // Must be zero.
pPublicKey->aiKeyAlg = CALG_RSA_KEYX; // RSA public-key key exchange.
// The next block of data is the RSAPUBKEY structure.
RSAPUBKEY *pRsaPubKey = (RSAPUBKEY *)(pKeyBlob + sizeof(PUBLICKEYSTRUC));
pRsaPubKey->magic = 0x31415352; // RSA1 // Use public key
pRsaPubKey->bitlen = cbLen * 8; // Number of bits in the modulus.
pRsaPubKey->pubexp = exponent; // Exponent.
// Copy the modulus into the blob. Put the modulus directly after the
// RSAPUBKEY structure in the blob.
BYTE *pKey = (BYTE *)(((BYTE *)pRsaPubKey) + sizeof(RSAPUBKEY));
memcpy(pKey, pbBuffer, cbLen);
// Now import public key
if (!CryptImportKey(hCSP, pKeyBlob, cbKeyBlob, 0, 0, &phKey)) {
result = GetLastError();
__leave;
}
DWORD dataSize = (DWORD)mir_strlen(data);
// if data is not allocated just renurn size
if (encryptedData == nullptr) {
// get length of encrypted data
if (!CryptEncrypt(phKey, 0, TRUE, 0, nullptr, &encryptedSize, dataSize))
result = GetLastError();
__leave;
}
// encrypt password
memcpy(encryptedData, data, dataSize);
if (!CryptEncrypt(phKey, 0, TRUE, 0, encryptedData, &dataSize, encryptedSize)) {
result = GetLastError();
__leave;
}
// reverse byte array again
for (int i = 0; i < (int)(encryptedSize / 2); ++i) {
BYTE temp = encryptedData[encryptedSize - i - 1];
encryptedData[encryptedSize - i - 1] = encryptedData[i];
encryptedData[i] = temp;
}
}
__finally
{
result = 0;
};
if (phKey)
CryptDestroyKey(phKey);
if (hCSP)
CryptReleaseContext(hCSP, 0);
return 0;
}
|