summaryrefslogtreecommitdiff
path: root/protocols/Steam/src/steam_crypt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Steam/src/steam_crypt.cpp')
-rw-r--r--protocols/Steam/src/steam_crypt.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/protocols/Steam/src/steam_crypt.cpp b/protocols/Steam/src/steam_crypt.cpp
new file mode 100644
index 0000000000..7c7fa07312
--- /dev/null
+++ b/protocols/Steam/src/steam_crypt.cpp
@@ -0,0 +1,114 @@
+#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 = 0;
+ BYTE *pbBuffer = nullptr;
+ BYTE *pKeyBlob = nullptr;
+ HCRYPTKEY phKey = 0;
+ HCRYPTPROV hCSP = 0;
+
+ // 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();
+ goto exit;
+ }
+
+ // allocate a new buffer.
+ pbBuffer = (BYTE*)malloc(cbLen);
+ if (!CryptStringToBinaryA(pszModulus, cchModulus, CRYPT_STRING_HEX, pbBuffer, &cbLen, &dwSkip, &dwFlags))
+ {
+ result = GetLastError();
+ goto exit;
+ }
+
+ // 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();
+ goto exit;
+ }
+
+ // Move the key into the key container.
+ DWORD cbKeyBlob = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + cbLen;
+ pKeyBlob = (BYTE*)malloc(cbKeyBlob);
+
+ // Fill in the data.
+ PUBLICKEYSTRUC *pPublicKey = (PUBLICKEYSTRUC*)pKeyBlob;
+ 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));
+ //pKeyBlob + sizeof(BLOBHEADER)+ sizeof(RSAPUBKEY);
+ memcpy(pKey, pbBuffer, cbLen);
+
+ // Now import public key
+ if (!CryptImportKey(hCSP, pKeyBlob, cbKeyBlob, 0, 0, &phKey))
+ {
+ result = GetLastError();
+ goto exit;
+ }
+
+ 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();
+ goto exit;
+ }
+
+ // encrypt password
+ memcpy(encryptedData, data, dataSize);
+ if (!CryptEncrypt(phKey, 0, TRUE, 0, encryptedData, &dataSize, encryptedSize))
+ {
+ result = GetLastError();
+ goto exit;
+ }
+
+ // 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;
+ }
+
+exit:
+ if (pKeyBlob)
+ free(pKeyBlob);
+ if (phKey)
+ CryptDestroyKey(phKey);
+
+ if (pbBuffer)
+ free(pbBuffer);
+ if (hCSP)
+ CryptReleaseContext(hCSP, 0);
+
+ return 0;
+}