135 lines
2.5 KiB
C++
135 lines
2.5 KiB
C++
// Copyright (C) 2007 EQ2EMulator Development Team, GPL v3 License
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <mutex>
|
|
#include <cstring>
|
|
#include <iostream>
|
|
|
|
#include "rc4.hpp"
|
|
#include "types.hpp"
|
|
#include "packet/packet_dump.hpp"
|
|
|
|
using namespace std;
|
|
|
|
/**
|
|
* Crypto class handles RSA decryption and RC4 encryption/decryption operations
|
|
* for secure client-server communication in the EQ2 emulator
|
|
*/
|
|
class Crypto
|
|
{
|
|
public:
|
|
/**
|
|
* Default constructor - initializes crypto state to unencrypted
|
|
*/
|
|
Crypto()
|
|
{
|
|
rc4_key = 0;
|
|
encrypted = false;
|
|
client = nullptr;
|
|
server = nullptr;
|
|
}
|
|
|
|
/**
|
|
* Destructor - cleans up RC4 cipher instances
|
|
*/
|
|
~Crypto()
|
|
{
|
|
safe_delete(client);
|
|
safe_delete(server);
|
|
}
|
|
|
|
/**
|
|
* Decrypts RSA-encrypted data by reversing byte order and converting to int64
|
|
*/
|
|
static int64 RSADecrypt(uchar* text, int16 size)
|
|
{
|
|
int64 ret = 0;
|
|
uchar* buffer = new uchar[8];
|
|
|
|
// Reverse byte order for proper endianness
|
|
for (int i = 7; i >= 0; i--) {
|
|
buffer[7 - i] = text[i];
|
|
}
|
|
|
|
memcpy(&ret, buffer, 8);
|
|
safe_delete_array(buffer);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Encrypts data using RC4 server cipher with thread safety
|
|
*/
|
|
void RC4Encrypt(uchar* text, int32 size)
|
|
{
|
|
MCrypto.lock();
|
|
server->Cypher(text, size);
|
|
MCrypto.unlock();
|
|
}
|
|
|
|
/**
|
|
* Decrypts data using RC4 client cipher with thread safety
|
|
*/
|
|
void RC4Decrypt(uchar* text, int32 size)
|
|
{
|
|
MCrypto.lock();
|
|
client->Cypher(text, size);
|
|
MCrypto.unlock();
|
|
}
|
|
|
|
/**
|
|
* Gets the current RC4 encryption key
|
|
*/
|
|
int64 getRC4Key()
|
|
{
|
|
return rc4_key;
|
|
}
|
|
|
|
/**
|
|
* Sets the RC4 encryption key and initializes cipher instances
|
|
*/
|
|
void setRC4Key(int64 key)
|
|
{
|
|
rc4_key = key;
|
|
|
|
if (key > 0) {
|
|
encrypted = true;
|
|
client = new RC4(~key); // Client uses inverted key
|
|
server = new RC4(key); // Server uses original key
|
|
|
|
// Initialize cipher states with dummy data
|
|
uchar temp[20];
|
|
client->Cypher(temp, 20);
|
|
server->Cypher(temp, 20);
|
|
}
|
|
else {
|
|
encrypted = false;
|
|
safe_delete(client);
|
|
safe_delete(server);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if encryption is currently enabled
|
|
*/
|
|
bool isEncrypted()
|
|
{
|
|
return encrypted;
|
|
}
|
|
|
|
/**
|
|
* Manually sets the encryption state
|
|
*/
|
|
void setEncrypted(bool in_val)
|
|
{
|
|
encrypted = in_val;
|
|
}
|
|
|
|
private:
|
|
RC4* server; // Server-side RC4 cipher instance
|
|
RC4* client; // Client-side RC4 cipher instance
|
|
bool encrypted; // Current encryption state flag
|
|
int64 rc4_key; // RC4 encryption key value
|
|
mutex MCrypto; // Mutex for thread-safe cipher operations
|
|
}; |