mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-04 20:57:49 +00:00
120 lines
3.2 KiB
C++
120 lines
3.2 KiB
C++
#if defined(_WIN32) && !defined(RBX_PLATFORM_DURANGO)
|
|
#include "rbx/Crypt.h"
|
|
|
|
#include "rbxFormat.h"
|
|
#include <atlenc.h>
|
|
#include <iomanip>
|
|
#include <sstream>
|
|
|
|
#include "rbx/Debug.h"
|
|
|
|
namespace RBX {
|
|
|
|
Crypt::Crypt()
|
|
{
|
|
static const char* keyB64 = "BgIAAACkAABSU0ExAAQAAAEAAQD1kq9nN7r7A+Smnqx2nhfHnhGs4fh1i+Oqejfsr6CE0dn3vlntBgeFWBAdCjxVJ/8LVfX55MQfoXachmV3KGb77ZzcWmw6IDYOQ7oYJvEZEHpyMm+EtXJvY3etifO+cLYxbmRNRDaWJ3KipuNWrbkKlG/RM0GzW8+BkFzlWc0Xug==";
|
|
char pbKeyBlob[256];
|
|
int dwBlobLen = 256;
|
|
|
|
// http://support.microsoft.com/kb/238187
|
|
if (!CryptAcquireContext(&context, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
|
{
|
|
if (::GetLastError()==NTE_BAD_KEYSET)
|
|
{
|
|
if (!CryptAcquireContext(&context, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET))
|
|
throw RBX::runtime_error("Error %x during CryptAcquireContext 2\n", GetLastError());
|
|
}
|
|
else
|
|
throw RBX::runtime_error("Error %x during CryptAcquireContext\n", GetLastError());
|
|
}
|
|
|
|
|
|
{
|
|
ATL::Base64Decode(keyB64, strlen(keyB64), (BYTE*)pbKeyBlob, &dwBlobLen);
|
|
}
|
|
|
|
if (!CryptImportKey(context, (BYTE*)pbKeyBlob, dwBlobLen, 0, 0, &key))
|
|
throw RBX::runtime_error("Error %x during CryptImportKey", GetLastError());
|
|
}
|
|
|
|
Crypt::~Crypt()
|
|
{
|
|
CryptDestroyKey(key);
|
|
CryptReleaseContext(context, 0);
|
|
}
|
|
|
|
void Crypt::verifySignatureBase64(std::string message, std::string signatureBase64)
|
|
{
|
|
HCRYPTHASH hash;
|
|
if (!CryptCreateHash(context, CALG_SHA1, NULL, 0, &hash))
|
|
#ifdef _DEBUG
|
|
throw RBX::runtime_error("Error %x during CryptCreateHash", GetLastError());
|
|
#else
|
|
throw RBX::runtime_error("");
|
|
#endif
|
|
try
|
|
{
|
|
if (!CryptHashData(hash, (BYTE*)message.c_str(), message.size(), 0))
|
|
#ifdef _DEBUG
|
|
throw RBX::runtime_error("Error %x during CryptHashData", GetLastError());
|
|
#else
|
|
throw RBX::runtime_error("");
|
|
#endif
|
|
int signatureLen = Base64DecodeGetRequiredLength(signatureBase64.size());
|
|
BYTE* signature = (BYTE*)alloca(signatureLen);
|
|
ATL::Base64Decode(signatureBase64.c_str(), signatureBase64.size(), signature, &signatureLen);
|
|
|
|
/*
|
|
The native cryptography API uses little-endian byte order
|
|
while the .NET Framework API uses big-endian byte order.
|
|
If you are verifying a signature generated by using a .NET Framework
|
|
API, you must swap the order of signature bytes before calling the
|
|
CryptVerifySignature function to verify the signature.
|
|
*/
|
|
if (signatureLen > 10240)
|
|
throw RBX::runtime_error("Signature too long");
|
|
|
|
BYTE signatureRev[10240];
|
|
for (int i = 0; i < signatureLen; ++i)
|
|
signatureRev[i] = signature[signatureLen - i - 1];
|
|
|
|
#pragma warning(push)
|
|
#pragma warning(disable: 6309)
|
|
#pragma warning(disable: 6387)
|
|
if (!CryptVerifySignature(hash, signatureRev, signatureLen, key, NULL, 0))
|
|
#ifdef _DEBUG
|
|
throw RBX::runtime_error("CryptVerifySignature Error 0x%x. sigLen=%d sigB64='%s' message='%s'", GetLastError(), signatureLen, signatureBase64.c_str(), message.c_str());
|
|
#else
|
|
throw RBX::runtime_error("");
|
|
#endif
|
|
#pragma warning(pop)
|
|
}
|
|
catch (...)
|
|
{
|
|
::CryptDestroyHash(hash);
|
|
throw;
|
|
}
|
|
|
|
::CryptDestroyHash(hash);
|
|
}
|
|
|
|
} //namespace RBX
|
|
|
|
#else
|
|
|
|
#include "rbx/Crypt.h"
|
|
|
|
namespace RBX
|
|
{
|
|
|
|
Crypt::Crypt() {}
|
|
Crypt::~Crypt() {}
|
|
void Crypt::verifySignatureBase64(std::string message, std::string signatureBase64) {}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|