#if defined(_WIN32) && !defined(RBX_PLATFORM_DURANGO) #include "rbx/Crypt.h" #include "rbxFormat.h" #include #include #include #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