PolarSSL is fully used for 1.3.2 protocol encryption.
This commit is contained in:
parent
9774da8122
commit
5f34c78091
@ -4,6 +4,7 @@ project (MCServer)
|
|||||||
|
|
||||||
include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/")
|
include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/")
|
||||||
include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/jsoncpp/include")
|
include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/jsoncpp/include")
|
||||||
|
include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/polarssl/include")
|
||||||
|
|
||||||
set(FOLDERS OSSupport HTTPServer Bindings Items Blocks Protocol Generating)
|
set(FOLDERS OSSupport HTTPServer Bindings Items Blocks Protocol Generating)
|
||||||
set(FOLDERS ${FOLDERS} WorldStorage Mobs Entities Simulator UI BlockEntities)
|
set(FOLDERS ${FOLDERS} WorldStorage Mobs Entities Simulator UI BlockEntities)
|
||||||
|
401
src/Crypto.cpp
Normal file
401
src/Crypto.cpp
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
|
||||||
|
// Crypto.cpp
|
||||||
|
|
||||||
|
// Implements classes that wrap the cryptographic code library
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "Crypto.h"
|
||||||
|
|
||||||
|
#include "polarssl/pk.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Self-test the hash formatting for known values:
|
||||||
|
// sha1(Notch) : 4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48
|
||||||
|
// sha1(jeb_) : -7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1
|
||||||
|
// sha1(simon) : 88e16a1019277b15d58faf0541e11910eb756f6
|
||||||
|
|
||||||
|
class Test
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Test(void)
|
||||||
|
{
|
||||||
|
AString DigestNotch, DigestJeb, DigestSimon;
|
||||||
|
Byte Digest[20];
|
||||||
|
cSHA1Checksum Checksum;
|
||||||
|
Checksum.Update((const Byte *)"Notch", 5);
|
||||||
|
Checksum.Finalize(Digest);
|
||||||
|
cSHA1Checksum::DigestToJava(Digest, DigestNotch);
|
||||||
|
Checksum.Restart();
|
||||||
|
Checksum.Update((const Byte *)"jeb_", 4);
|
||||||
|
Checksum.Finalize(Digest);
|
||||||
|
cSHA1Checksum::DigestToJava(Digest, DigestJeb);
|
||||||
|
Checksum.Restart();
|
||||||
|
Checksum.Update((const Byte *)"simon", 5);
|
||||||
|
Checksum.Finalize(Digest);
|
||||||
|
cSHA1Checksum::DigestToJava(Digest, DigestSimon);
|
||||||
|
printf("Notch: \"%s\"\n", DigestNotch.c_str());
|
||||||
|
printf("jeb_: \"%s\"\n", DigestJeb.c_str());
|
||||||
|
printf("simon: \"%s\"\n", DigestSimon.c_str());
|
||||||
|
assert(DigestNotch == "4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48");
|
||||||
|
assert(DigestJeb == "-7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1");
|
||||||
|
assert(DigestSimon == "88e16a1019277b15d58faf0541e11910eb756f6");
|
||||||
|
}
|
||||||
|
} test;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cRSAPrivateKey:
|
||||||
|
|
||||||
|
cRSAPrivateKey::cRSAPrivateKey(void)
|
||||||
|
{
|
||||||
|
rsa_init(&m_Rsa, RSA_PKCS_V15, 0);
|
||||||
|
InitRnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cRSAPrivateKey::cRSAPrivateKey(const cRSAPrivateKey & a_Other)
|
||||||
|
{
|
||||||
|
rsa_init(&m_Rsa, RSA_PKCS_V15, 0);
|
||||||
|
rsa_copy(&m_Rsa, &a_Other.m_Rsa);
|
||||||
|
InitRnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cRSAPrivateKey::~cRSAPrivateKey()
|
||||||
|
{
|
||||||
|
entropy_free(&m_Entropy);
|
||||||
|
rsa_free(&m_Rsa);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cRSAPrivateKey::InitRnd(void)
|
||||||
|
{
|
||||||
|
entropy_init(&m_Entropy);
|
||||||
|
const unsigned char pers[] = "rsa_genkey";
|
||||||
|
ctr_drbg_init(&m_Ctr_drbg, entropy_func, &m_Entropy, pers, sizeof(pers) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cRSAPrivateKey::Generate(unsigned a_KeySizeBits)
|
||||||
|
{
|
||||||
|
if (rsa_gen_key(&m_Rsa, ctr_drbg_random, &m_Ctr_drbg, a_KeySizeBits, 65537) != 0)
|
||||||
|
{
|
||||||
|
// Key generation failed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AString cRSAPrivateKey::GetPubKeyDER(void)
|
||||||
|
{
|
||||||
|
class cPubKey
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cPubKey(rsa_context * a_Rsa) :
|
||||||
|
m_IsValid(false)
|
||||||
|
{
|
||||||
|
pk_init(&m_Key);
|
||||||
|
if (pk_init_ctx(&m_Key, pk_info_from_type(POLARSSL_PK_RSA)) != 0)
|
||||||
|
{
|
||||||
|
ASSERT(!"Cannot init PrivKey context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rsa_copy(pk_rsa(m_Key), a_Rsa) != 0)
|
||||||
|
{
|
||||||
|
ASSERT(!"Cannot copy PrivKey to PK context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_IsValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~cPubKey()
|
||||||
|
{
|
||||||
|
if (m_IsValid)
|
||||||
|
{
|
||||||
|
pk_free(&m_Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator pk_context * (void) { return &m_Key; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool m_IsValid;
|
||||||
|
pk_context m_Key;
|
||||||
|
} PkCtx(&m_Rsa);
|
||||||
|
|
||||||
|
unsigned char buf[3000];
|
||||||
|
int res = pk_write_pubkey_der(PkCtx, buf, sizeof(buf));
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
return AString();
|
||||||
|
}
|
||||||
|
return AString((const char *)(buf + sizeof(buf) - res), (size_t)res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cRSAPrivateKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength)
|
||||||
|
{
|
||||||
|
if (a_EncryptedLength < m_Rsa.len)
|
||||||
|
{
|
||||||
|
LOGD("%s: Invalid a_EncryptedLength: got %u, exp at least %u",
|
||||||
|
__FUNCTION__, (unsigned)a_EncryptedLength, (unsigned)(m_Rsa.len)
|
||||||
|
);
|
||||||
|
ASSERT(!"Invalid a_DecryptedMaxLength!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (a_DecryptedMaxLength < m_Rsa.len)
|
||||||
|
{
|
||||||
|
LOGD("%s: Invalid a_DecryptedMaxLength: got %u, exp at least %u",
|
||||||
|
__FUNCTION__, (unsigned)a_EncryptedLength, (unsigned)(m_Rsa.len)
|
||||||
|
);
|
||||||
|
ASSERT(!"Invalid a_DecryptedMaxLength!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
size_t DecryptedLength;
|
||||||
|
int res = rsa_pkcs1_decrypt(
|
||||||
|
&m_Rsa, ctr_drbg_random, &m_Ctr_drbg, RSA_PRIVATE, &DecryptedLength,
|
||||||
|
a_EncryptedData, a_DecryptedData, a_DecryptedMaxLength
|
||||||
|
);
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (int)DecryptedLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cAESCFBDecryptor:
|
||||||
|
|
||||||
|
cAESCFBDecryptor::cAESCFBDecryptor(void) :
|
||||||
|
m_IsValid(false),
|
||||||
|
m_IVOffset(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cAESCFBDecryptor::~cAESCFBDecryptor()
|
||||||
|
{
|
||||||
|
// Clear the leftover in-memory data, so that they can't be accessed by a backdoor
|
||||||
|
memset(&m_Aes, 0, sizeof(m_Aes));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cAESCFBDecryptor::Init(const Byte a_Key[16], const Byte a_IV[16])
|
||||||
|
{
|
||||||
|
ASSERT(!IsValid()); // Cannot Init twice
|
||||||
|
|
||||||
|
memcpy(m_IV, a_IV, 16);
|
||||||
|
aes_setkey_enc(&m_Aes, a_Key, 128);
|
||||||
|
m_IsValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cAESCFBDecryptor::ProcessData(Byte * a_DecryptedOut, const Byte * a_EncryptedIn, size_t a_Length)
|
||||||
|
{
|
||||||
|
ASSERT(IsValid()); // Must Init() first
|
||||||
|
|
||||||
|
// PolarSSL doesn't support AES-CFB8, need to implement it manually:
|
||||||
|
for (size_t i = 0; i < a_Length; i++)
|
||||||
|
{
|
||||||
|
Byte Buffer[sizeof(m_IV)];
|
||||||
|
aes_crypt_ecb(&m_Aes, AES_ENCRYPT, m_IV, Buffer);
|
||||||
|
for (size_t idx = 0; idx < sizeof(m_IV) - 1; idx++)
|
||||||
|
{
|
||||||
|
m_IV[idx] = m_IV[idx + 1];
|
||||||
|
}
|
||||||
|
m_IV[sizeof(m_IV) - 1] = a_EncryptedIn[i];
|
||||||
|
a_DecryptedOut[i] = a_EncryptedIn[i] ^ Buffer[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cAESCFBEncryptor:
|
||||||
|
|
||||||
|
cAESCFBEncryptor::cAESCFBEncryptor(void) :
|
||||||
|
m_IsValid(false),
|
||||||
|
m_IVOffset(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cAESCFBEncryptor::~cAESCFBEncryptor()
|
||||||
|
{
|
||||||
|
// Clear the leftover in-memory data, so that they can't be accessed by a backdoor
|
||||||
|
memset(&m_Aes, 0, sizeof(m_Aes));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cAESCFBEncryptor::Init(const Byte a_Key[16], const Byte a_IV[16])
|
||||||
|
{
|
||||||
|
ASSERT(!IsValid()); // Cannot Init twice
|
||||||
|
ASSERT(m_IVOffset == 0);
|
||||||
|
|
||||||
|
memcpy(m_IV, a_IV, 16);
|
||||||
|
aes_setkey_enc(&m_Aes, a_Key, 128);
|
||||||
|
m_IsValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cAESCFBEncryptor::ProcessData(Byte * a_EncryptedOut, const Byte * a_PlainIn, size_t a_Length)
|
||||||
|
{
|
||||||
|
ASSERT(IsValid()); // Must Init() first
|
||||||
|
|
||||||
|
// PolarSSL doesn't do AES-CFB8, so we need to implement it ourselves:
|
||||||
|
for (size_t i = 0; i < a_Length; i++)
|
||||||
|
{
|
||||||
|
Byte Buffer[sizeof(m_IV)];
|
||||||
|
aes_crypt_ecb(&m_Aes, AES_ENCRYPT, m_IV, Buffer);
|
||||||
|
for (size_t idx = 0; idx < sizeof(m_IV) - 1; idx++)
|
||||||
|
{
|
||||||
|
m_IV[idx] = m_IV[idx + 1];
|
||||||
|
}
|
||||||
|
a_EncryptedOut[i] = a_PlainIn[i] ^ Buffer[0];
|
||||||
|
m_IV[sizeof(m_IV) - 1] = a_EncryptedOut[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cSHA1Checksum:
|
||||||
|
|
||||||
|
cSHA1Checksum::cSHA1Checksum(void) :
|
||||||
|
m_DoesAcceptInput(true)
|
||||||
|
{
|
||||||
|
sha1_starts(&m_Sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSHA1Checksum::Update(const Byte * a_Data, size_t a_Length)
|
||||||
|
{
|
||||||
|
ASSERT(m_DoesAcceptInput); // Not Finalize()-d yet, or Restart()-ed
|
||||||
|
|
||||||
|
sha1_update(&m_Sha1, a_Data, a_Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSHA1Checksum::Finalize(cSHA1Checksum::Checksum & a_Output)
|
||||||
|
{
|
||||||
|
ASSERT(m_DoesAcceptInput); // Not Finalize()-d yet, or Restart()-ed
|
||||||
|
|
||||||
|
sha1_finish(&m_Sha1, a_Output);
|
||||||
|
m_DoesAcceptInput = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSHA1Checksum::DigestToJava(const Checksum & a_Digest, AString & a_Out)
|
||||||
|
{
|
||||||
|
Checksum Digest;
|
||||||
|
memcpy(Digest, a_Digest, sizeof(Digest));
|
||||||
|
|
||||||
|
bool IsNegative = (Digest[0] >= 0x80);
|
||||||
|
if (IsNegative)
|
||||||
|
{
|
||||||
|
// Two's complement:
|
||||||
|
bool carry = true; // Add one to the whole number
|
||||||
|
for (int i = 19; i >= 0; i--)
|
||||||
|
{
|
||||||
|
Digest[i] = ~Digest[i];
|
||||||
|
if (carry)
|
||||||
|
{
|
||||||
|
carry = (Digest[i] == 0xff);
|
||||||
|
Digest[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a_Out.clear();
|
||||||
|
a_Out.reserve(40);
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
AppendPrintf(a_Out, "%02x", Digest[i]);
|
||||||
|
}
|
||||||
|
while ((a_Out.length() > 0) && (a_Out[0] == '0'))
|
||||||
|
{
|
||||||
|
a_Out.erase(0, 1);
|
||||||
|
}
|
||||||
|
if (IsNegative)
|
||||||
|
{
|
||||||
|
a_Out.insert(0, "-");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSHA1Checksum::Restart(void)
|
||||||
|
{
|
||||||
|
sha1_starts(&m_Sha1);
|
||||||
|
m_DoesAcceptInput = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
164
src/Crypto.h
Normal file
164
src/Crypto.h
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
|
||||||
|
// Crypto.h
|
||||||
|
|
||||||
|
// Declares classes that wrap the cryptographic code library
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "polarssl/rsa.h"
|
||||||
|
#include "polarssl/aes.h"
|
||||||
|
#include "polarssl/entropy.h"
|
||||||
|
#include "polarssl/ctr_drbg.h"
|
||||||
|
#include "polarssl/sha1.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Encapsulates an RSA private key used in PKI cryptography */
|
||||||
|
class cRSAPrivateKey
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Creates a new empty object, the key is not assigned */
|
||||||
|
cRSAPrivateKey(void);
|
||||||
|
|
||||||
|
/** Deep-copies the key from a_Other */
|
||||||
|
cRSAPrivateKey(const cRSAPrivateKey & a_Other);
|
||||||
|
|
||||||
|
~cRSAPrivateKey();
|
||||||
|
|
||||||
|
/** Generates a new key within this object, with the specified size in bits.
|
||||||
|
Returns true on success, false on failure. */
|
||||||
|
bool Generate(unsigned a_KeySizeBits = 1024);
|
||||||
|
|
||||||
|
/** Returns the public key part encoded in ASN1 DER encoding */
|
||||||
|
AString GetPubKeyDER(void);
|
||||||
|
|
||||||
|
/** Decrypts the data using RSAES-PKCS#1 algorithm.
|
||||||
|
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
||||||
|
Returns the number of bytes decrypted, or negative number for error. */
|
||||||
|
int Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
rsa_context m_Rsa;
|
||||||
|
entropy_context m_Entropy;
|
||||||
|
ctr_drbg_context m_Ctr_drbg;
|
||||||
|
|
||||||
|
/** Initializes the m_Entropy and m_Ctr_drbg contexts
|
||||||
|
Common part of this object's construction, called from all constructors. */
|
||||||
|
void InitRnd(void);
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Decrypts data using the AES / CFB (128) algorithm */
|
||||||
|
class cAESCFBDecryptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Byte test;
|
||||||
|
|
||||||
|
cAESCFBDecryptor(void);
|
||||||
|
~cAESCFBDecryptor();
|
||||||
|
|
||||||
|
/** Initializes the decryptor with the specified Key / IV */
|
||||||
|
void Init(const Byte a_Key[16], const Byte a_IV[16]);
|
||||||
|
|
||||||
|
/** Decrypts a_Length bytes of the encrypted data; produces a_Length output bytes */
|
||||||
|
void ProcessData(Byte * a_DecryptedOut, const Byte * a_EncryptedIn, size_t a_Length);
|
||||||
|
|
||||||
|
/** Returns true if the object has been initialized with the Key / IV */
|
||||||
|
bool IsValid(void) const { return m_IsValid; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
aes_context m_Aes;
|
||||||
|
|
||||||
|
/** The InitialVector, used by the CFB mode decryption */
|
||||||
|
Byte m_IV[16];
|
||||||
|
|
||||||
|
/** Current offset in the m_IV, used by the CFB mode decryption */
|
||||||
|
size_t m_IVOffset;
|
||||||
|
|
||||||
|
/** Indicates whether the object has been initialized with the Key / IV */
|
||||||
|
bool m_IsValid;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Encrypts data using the AES / CFB (128) algorithm */
|
||||||
|
class cAESCFBEncryptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Byte test;
|
||||||
|
|
||||||
|
cAESCFBEncryptor(void);
|
||||||
|
~cAESCFBEncryptor();
|
||||||
|
|
||||||
|
/** Initializes the decryptor with the specified Key / IV */
|
||||||
|
void Init(const Byte a_Key[16], const Byte a_IV[16]);
|
||||||
|
|
||||||
|
/** Encrypts a_Length bytes of the plain data; produces a_Length output bytes */
|
||||||
|
void ProcessData(Byte * a_EncryptedOut, const Byte * a_PlainIn, size_t a_Length);
|
||||||
|
|
||||||
|
/** Returns true if the object has been initialized with the Key / IV */
|
||||||
|
bool IsValid(void) const { return m_IsValid; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
aes_context m_Aes;
|
||||||
|
|
||||||
|
/** The InitialVector, used by the CFB mode encryption */
|
||||||
|
Byte m_IV[16];
|
||||||
|
|
||||||
|
/** Current offset in the m_IV, used by the CFB mode encryption */
|
||||||
|
size_t m_IVOffset;
|
||||||
|
|
||||||
|
/** Indicates whether the object has been initialized with the Key / IV */
|
||||||
|
bool m_IsValid;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Calculates a SHA1 checksum for data stream */
|
||||||
|
class cSHA1Checksum
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Byte Checksum[20]; // The type used for storing the checksum
|
||||||
|
|
||||||
|
cSHA1Checksum(void);
|
||||||
|
|
||||||
|
/** Adds the specified data to the checksum */
|
||||||
|
void Update(const Byte * a_Data, size_t a_Length);
|
||||||
|
|
||||||
|
/** Calculates and returns the final checksum */
|
||||||
|
void Finalize(Checksum & a_Output);
|
||||||
|
|
||||||
|
/** Returns true if the object is accepts more input data, false if Finalize()-d (need to Restart()) */
|
||||||
|
bool DoesAcceptInput(void) const { return m_DoesAcceptInput; }
|
||||||
|
|
||||||
|
/** Converts a raw 160-bit SHA1 digest into a Java Hex representation
|
||||||
|
According to http://wiki.vg/wiki/index.php?title=Protocol_Encryption&oldid=2802
|
||||||
|
*/
|
||||||
|
static void DigestToJava(const Checksum & a_Digest, AString & a_JavaOut);
|
||||||
|
|
||||||
|
/** Clears the current context and start a new checksum calculation */
|
||||||
|
void Restart(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** True if the object is accepts more input data, false if Finalize()-d (need to Restart()) */
|
||||||
|
bool m_DoesAcceptInput;
|
||||||
|
|
||||||
|
sha1_context m_Sha1;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef unsigned char Byte;
|
|
||||||
|
|
||||||
/// List of slot numbers, used for inventory-painting
|
/// List of slot numbers, used for inventory-painting
|
||||||
typedef std::vector<int> cSlotNums;
|
typedef std::vector<int> cSlotNums;
|
||||||
|
|
||||||
|
@ -91,6 +91,9 @@ typedef unsigned long long UInt64;
|
|||||||
typedef unsigned int UInt32;
|
typedef unsigned int UInt32;
|
||||||
typedef unsigned short UInt16;
|
typedef unsigned short UInt16;
|
||||||
|
|
||||||
|
typedef unsigned char Byte;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,13 +28,14 @@
|
|||||||
#pragma warning(disable:4702)
|
#pragma warning(disable:4702)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "cryptopp/randpool.h"
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define HANDLE_PACKET_READ(Proc, Type, Var) \
|
#define HANDLE_PACKET_READ(Proc, Type, Var) \
|
||||||
Type Var; \
|
Type Var; \
|
||||||
{ \
|
{ \
|
||||||
@ -49,17 +50,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef unsigned char Byte;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using namespace CryptoPP;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const int MAX_ENC_LEN = 512; // Maximum size of the encrypted message; should be 128, but who knows...
|
const int MAX_ENC_LEN = 512; // Maximum size of the encrypted message; should be 128, but who knows...
|
||||||
|
|
||||||
@ -93,81 +83,6 @@ enum
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Converts a raw 160-bit SHA1 digest into a Java Hex representation
|
|
||||||
// According to http://wiki.vg/wiki/index.php?title=Protocol_Encryption&oldid=2802
|
|
||||||
static void DigestToJava(byte a_Digest[20], AString & a_Out)
|
|
||||||
{
|
|
||||||
bool IsNegative = (a_Digest[0] >= 0x80);
|
|
||||||
if (IsNegative)
|
|
||||||
{
|
|
||||||
// Two's complement:
|
|
||||||
bool carry = true; // Add one to the whole number
|
|
||||||
for (int i = 19; i >= 0; i--)
|
|
||||||
{
|
|
||||||
a_Digest[i] = ~a_Digest[i];
|
|
||||||
if (carry)
|
|
||||||
{
|
|
||||||
carry = (a_Digest[i] == 0xff);
|
|
||||||
a_Digest[i]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
a_Out.clear();
|
|
||||||
a_Out.reserve(40);
|
|
||||||
for (int i = 0; i < 20; i++)
|
|
||||||
{
|
|
||||||
AppendPrintf(a_Out, "%02x", a_Digest[i]);
|
|
||||||
}
|
|
||||||
while ((a_Out.length() > 0) && (a_Out[0] == '0'))
|
|
||||||
{
|
|
||||||
a_Out.erase(0, 1);
|
|
||||||
}
|
|
||||||
if (IsNegative)
|
|
||||||
{
|
|
||||||
a_Out.insert(0, "-");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Self-test the hash formatting for known values:
|
|
||||||
// sha1(Notch) : 4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48
|
|
||||||
// sha1(jeb_) : -7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1
|
|
||||||
// sha1(simon) : 88e16a1019277b15d58faf0541e11910eb756f6
|
|
||||||
|
|
||||||
class Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Test(void)
|
|
||||||
{
|
|
||||||
AString DigestNotch, DigestJeb, DigestSimon;
|
|
||||||
byte Digest[20];
|
|
||||||
CryptoPP::SHA1 Checksum;
|
|
||||||
Checksum.Update((const byte *)"Notch", 5);
|
|
||||||
Checksum.Final(Digest);
|
|
||||||
DigestToJava(Digest, DigestNotch);
|
|
||||||
Checksum.Restart();
|
|
||||||
Checksum.Update((const byte *)"jeb_", 4);
|
|
||||||
Checksum.Final(Digest);
|
|
||||||
DigestToJava(Digest, DigestJeb);
|
|
||||||
Checksum.Restart();
|
|
||||||
Checksum.Update((const byte *)"simon", 5);
|
|
||||||
Checksum.Final(Digest);
|
|
||||||
DigestToJava(Digest, DigestSimon);
|
|
||||||
printf("Notch: \"%s\"", DigestNotch.c_str());
|
|
||||||
printf("jeb_: \"%s\"", DigestJeb.c_str());
|
|
||||||
printf("simon: \"%s\"", DigestSimon.c_str());
|
|
||||||
}
|
|
||||||
} test;
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cProtocol132:
|
// cProtocol132:
|
||||||
|
|
||||||
@ -197,11 +112,11 @@ void cProtocol132::DataReceived(const char * a_Data, int a_Size)
|
|||||||
{
|
{
|
||||||
if (m_IsEncrypted)
|
if (m_IsEncrypted)
|
||||||
{
|
{
|
||||||
byte Decrypted[512];
|
Byte Decrypted[512];
|
||||||
while (a_Size > 0)
|
while (a_Size > 0)
|
||||||
{
|
{
|
||||||
int NumBytes = (a_Size > (int)sizeof(Decrypted)) ? (int)sizeof(Decrypted) : a_Size;
|
int NumBytes = (a_Size > (int)sizeof(Decrypted)) ? (int)sizeof(Decrypted) : a_Size;
|
||||||
m_Decryptor.ProcessData(Decrypted, (byte *)a_Data, NumBytes);
|
m_Decryptor.ProcessData(Decrypted, (Byte *)a_Data, NumBytes);
|
||||||
super::DataReceived((const char *)Decrypted, NumBytes);
|
super::DataReceived((const char *)Decrypted, NumBytes);
|
||||||
a_Size -= NumBytes;
|
a_Size -= NumBytes;
|
||||||
a_Data += NumBytes;
|
a_Data += NumBytes;
|
||||||
@ -582,9 +497,7 @@ int cProtocol132::ParseHandshake(void)
|
|||||||
return PARSE_OK; // Player is not allowed into the server
|
return PARSE_OK; // Player is not allowed into the server
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a 0xFD Encryption Key Request http://wiki.vg/Protocol#0xFD
|
// Send a 0xfd Encryption Key Request http://wiki.vg/Protocol#0xFD
|
||||||
CryptoPP::StringSink sink(m_ServerPublicKey); // GCC won't allow inline instantiation in the following line, damned temporary refs
|
|
||||||
cRoot::Get()->GetServer()->GetPublicKey().Save(sink);
|
|
||||||
SendEncryptionKeyRequest();
|
SendEncryptionKeyRequest();
|
||||||
|
|
||||||
return PARSE_OK;
|
return PARSE_OK;
|
||||||
@ -596,7 +509,7 @@ int cProtocol132::ParseHandshake(void)
|
|||||||
|
|
||||||
int cProtocol132::ParseClientStatuses(void)
|
int cProtocol132::ParseClientStatuses(void)
|
||||||
{
|
{
|
||||||
HANDLE_PACKET_READ(ReadByte, byte, Status);
|
HANDLE_PACKET_READ(ReadByte, Byte, Status);
|
||||||
if ((Status & 1) == 0)
|
if ((Status & 1) == 0)
|
||||||
{
|
{
|
||||||
m_Client->HandleLogin(39, m_Username);
|
m_Client->HandleLogin(39, m_Username);
|
||||||
@ -714,11 +627,11 @@ void cProtocol132::Flush(void)
|
|||||||
int a_Size = m_DataToSend.size();
|
int a_Size = m_DataToSend.size();
|
||||||
if (m_IsEncrypted)
|
if (m_IsEncrypted)
|
||||||
{
|
{
|
||||||
byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks)
|
Byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks)
|
||||||
while (a_Size > 0)
|
while (a_Size > 0)
|
||||||
{
|
{
|
||||||
int NumBytes = (a_Size > (int)sizeof(Encrypted)) ? (int)sizeof(Encrypted) : a_Size;
|
int NumBytes = (a_Size > (int)sizeof(Encrypted)) ? (int)sizeof(Encrypted) : a_Size;
|
||||||
m_Encryptor.ProcessData(Encrypted, (byte *)a_Data, NumBytes);
|
m_Encryptor.ProcessData(Encrypted, (Byte *)a_Data, NumBytes);
|
||||||
super::SendData((const char *)Encrypted, NumBytes);
|
super::SendData((const char *)Encrypted, NumBytes);
|
||||||
a_Size -= NumBytes;
|
a_Size -= NumBytes;
|
||||||
a_Data += NumBytes;
|
a_Data += NumBytes;
|
||||||
@ -880,8 +793,8 @@ void cProtocol132::SendEncryptionKeyRequest(void)
|
|||||||
cCSLock Lock(m_CSPacket);
|
cCSLock Lock(m_CSPacket);
|
||||||
WriteByte(0xfd);
|
WriteByte(0xfd);
|
||||||
WriteString(cRoot::Get()->GetServer()->GetServerID());
|
WriteString(cRoot::Get()->GetServer()->GetServerID());
|
||||||
WriteShort((short)m_ServerPublicKey.size());
|
WriteShort((short)(cRoot::Get()->GetServer()->GetPublicKeyDER().size()));
|
||||||
SendData(m_ServerPublicKey.data(), m_ServerPublicKey.size());
|
SendData(cRoot::Get()->GetServer()->GetPublicKeyDER().data(), cRoot::Get()->GetServer()->GetPublicKeyDER().size());
|
||||||
WriteShort(4);
|
WriteShort(4);
|
||||||
WriteInt((int)(intptr_t)this); // Using 'this' as the cryptographic nonce, so that we don't have to generate one each time :)
|
WriteInt((int)(intptr_t)this); // Using 'this' as the cryptographic nonce, so that we don't have to generate one each time :)
|
||||||
Flush();
|
Flush();
|
||||||
@ -894,13 +807,11 @@ void cProtocol132::SendEncryptionKeyRequest(void)
|
|||||||
void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const AString & a_EncNonce)
|
void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const AString & a_EncNonce)
|
||||||
{
|
{
|
||||||
// Decrypt EncNonce using privkey
|
// Decrypt EncNonce using privkey
|
||||||
RSAES<PKCS1v15>::Decryptor rsaDecryptor(cRoot::Get()->GetServer()->GetPrivateKey());
|
cRSAPrivateKey & rsaDecryptor = cRoot::Get()->GetServer()->GetPrivateKey();
|
||||||
time_t CurTime = time(NULL);
|
|
||||||
CryptoPP::RandomPool rng;
|
|
||||||
rng.Put((const byte *)&CurTime, sizeof(CurTime));
|
|
||||||
Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)];
|
Int32 DecryptedNonce[MAX_ENC_LEN / sizeof(Int32)];
|
||||||
DecodingResult res = rsaDecryptor.Decrypt(rng, (const byte *)a_EncNonce.data(), a_EncNonce.size(), (byte *)DecryptedNonce);
|
int res = rsaDecryptor.Decrypt((const Byte *)a_EncNonce.data(), a_EncNonce.size(), (Byte *)DecryptedNonce, sizeof(DecryptedNonce));
|
||||||
if (!res.isValidCoding || (res.messageLength != 4))
|
if (res != 4)
|
||||||
{
|
{
|
||||||
LOGD("Bad nonce length");
|
LOGD("Bad nonce length");
|
||||||
m_Client->Kick("Hacked client");
|
m_Client->Kick("Hacked client");
|
||||||
@ -914,9 +825,9 @@ void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const A
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt the symmetric encryption key using privkey:
|
// Decrypt the symmetric encryption key using privkey:
|
||||||
byte DecryptedKey[MAX_ENC_LEN];
|
Byte DecryptedKey[MAX_ENC_LEN];
|
||||||
res = rsaDecryptor.Decrypt(rng, (const byte *)a_EncKey.data(), a_EncKey.size(), DecryptedKey);
|
res = rsaDecryptor.Decrypt((const Byte *)a_EncKey.data(), a_EncKey.size(), DecryptedKey, sizeof(DecryptedKey));
|
||||||
if (!res.isValidCoding || (res.messageLength != 16))
|
if (res != 16)
|
||||||
{
|
{
|
||||||
LOGD("Bad key length");
|
LOGD("Bad key length");
|
||||||
m_Client->Kick("Hacked client");
|
m_Client->Kick("Hacked client");
|
||||||
@ -932,6 +843,12 @@ void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const A
|
|||||||
Flush();
|
Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
AString DecryptedKeyHex;
|
||||||
|
CreateHexDump(DecryptedKeyHex, DecryptedKey, res, 16);
|
||||||
|
LOGD("Received encryption key, %d bytes:\n%s", res, DecryptedKeyHex.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
StartEncryption(DecryptedKey);
|
StartEncryption(DecryptedKey);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -940,21 +857,21 @@ void cProtocol132::HandleEncryptionKeyResponse(const AString & a_EncKey, const A
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol132::StartEncryption(const byte * a_Key)
|
void cProtocol132::StartEncryption(const Byte * a_Key)
|
||||||
{
|
{
|
||||||
m_Encryptor.SetKey(a_Key, 16, MakeParameters(Name::IV(), ConstByteArrayParameter(a_Key, 16))(Name::FeedbackSize(), 1));
|
m_Encryptor.Init(a_Key, a_Key);
|
||||||
m_Decryptor.SetKey(a_Key, 16, MakeParameters(Name::IV(), ConstByteArrayParameter(a_Key, 16))(Name::FeedbackSize(), 1));
|
m_Decryptor.Init(a_Key, a_Key);
|
||||||
m_IsEncrypted = true;
|
m_IsEncrypted = true;
|
||||||
|
|
||||||
// Prepare the m_AuthServerID:
|
// Prepare the m_AuthServerID:
|
||||||
CryptoPP::SHA1 Checksum;
|
cSHA1Checksum Checksum;
|
||||||
AString ServerID = cRoot::Get()->GetServer()->GetServerID();
|
AString ServerID = cRoot::Get()->GetServer()->GetServerID();
|
||||||
Checksum.Update((const byte *)ServerID.c_str(), ServerID.length());
|
Checksum.Update((const Byte *)ServerID.c_str(), ServerID.length());
|
||||||
Checksum.Update(a_Key, 16);
|
Checksum.Update(a_Key, 16);
|
||||||
Checksum.Update((const byte *)m_ServerPublicKey.c_str(), m_ServerPublicKey.length());
|
Checksum.Update((const Byte *)cRoot::Get()->GetServer()->GetPublicKeyDER().data(), cRoot::Get()->GetServer()->GetPublicKeyDER().size());
|
||||||
byte Digest[20];
|
Byte Digest[20];
|
||||||
Checksum.Final(Digest);
|
Checksum.Finalize(Digest);
|
||||||
DigestToJava(Digest, m_AuthServerID);
|
cSHA1Checksum::DigestToJava(Digest, m_AuthServerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,13 +20,12 @@
|
|||||||
#pragma warning(disable:4702)
|
#pragma warning(disable:4702)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "cryptopp/modes.h"
|
|
||||||
#include "cryptopp/aes.h"
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "../Crypto.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -79,16 +78,15 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_IsEncrypted;
|
bool m_IsEncrypted;
|
||||||
CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption m_Decryptor;
|
|
||||||
CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption m_Encryptor;
|
cAESCFBDecryptor m_Decryptor;
|
||||||
|
cAESCFBEncryptor m_Encryptor;
|
||||||
|
|
||||||
AString m_DataToSend;
|
AString m_DataToSend;
|
||||||
|
|
||||||
/// The ServerID used for session authentication; set in StartEncryption(), used in GetAuthServerID()
|
/// The ServerID used for session authentication; set in StartEncryption(), used in GetAuthServerID()
|
||||||
AString m_AuthServerID;
|
AString m_AuthServerID;
|
||||||
|
|
||||||
/// The server's public key, as used by SendEncryptionKeyRequest() and StartEncryption()
|
|
||||||
AString m_ServerPublicKey;
|
|
||||||
|
|
||||||
virtual void SendData(const char * a_Data, int a_Size) override;
|
virtual void SendData(const char * a_Data, int a_Size) override;
|
||||||
|
|
||||||
// DEBUG:
|
// DEBUG:
|
||||||
@ -108,7 +106,7 @@ protected:
|
|||||||
void HandleEncryptionKeyResponse(const AString & a_EncKey, const AString & a_EncNonce);
|
void HandleEncryptionKeyResponse(const AString & a_EncKey, const AString & a_EncNonce);
|
||||||
|
|
||||||
/// Starts the symmetric encryption with the specified key; also sets m_AuthServerID
|
/// Starts the symmetric encryption with the specified key; also sets m_AuthServerID
|
||||||
void StartEncryption(const byte * a_Key);
|
void StartEncryption(const Byte * a_Key);
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,8 +33,6 @@ Implements the 1.4.x protocol classes representing these protocols:
|
|||||||
#pragma warning(disable:4702)
|
#pragma warning(disable:4702)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "cryptopp/randpool.h"
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
@ -73,11 +73,11 @@ void cProtocol172::DataReceived(const char * a_Data, int a_Size)
|
|||||||
{
|
{
|
||||||
if (m_IsEncrypted)
|
if (m_IsEncrypted)
|
||||||
{
|
{
|
||||||
byte Decrypted[512];
|
Byte Decrypted[512];
|
||||||
while (a_Size > 0)
|
while (a_Size > 0)
|
||||||
{
|
{
|
||||||
int NumBytes = (a_Size > sizeof(Decrypted)) ? sizeof(Decrypted) : a_Size;
|
int NumBytes = (a_Size > sizeof(Decrypted)) ? sizeof(Decrypted) : a_Size;
|
||||||
m_Decryptor.ProcessData(Decrypted, (byte *)a_Data, NumBytes);
|
m_Decryptor.ProcessData(Decrypted, (Byte *)a_Data, NumBytes);
|
||||||
AddReceivedData((const char *)Decrypted, NumBytes);
|
AddReceivedData((const char *)Decrypted, NumBytes);
|
||||||
a_Size -= NumBytes;
|
a_Size -= NumBytes;
|
||||||
a_Data += NumBytes;
|
a_Data += NumBytes;
|
||||||
@ -1664,11 +1664,11 @@ void cProtocol172::SendData(const char * a_Data, int a_Size)
|
|||||||
{
|
{
|
||||||
if (m_IsEncrypted)
|
if (m_IsEncrypted)
|
||||||
{
|
{
|
||||||
byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks)
|
Byte Encrypted[8192]; // Larger buffer, we may be sending lots of data (chunks)
|
||||||
while (a_Size > 0)
|
while (a_Size > 0)
|
||||||
{
|
{
|
||||||
int NumBytes = (a_Size > sizeof(Encrypted)) ? sizeof(Encrypted) : a_Size;
|
int NumBytes = (a_Size > sizeof(Encrypted)) ? sizeof(Encrypted) : a_Size;
|
||||||
m_Encryptor.ProcessData(Encrypted, (byte *)a_Data, NumBytes);
|
m_Encryptor.ProcessData(Encrypted, (Byte *)a_Data, NumBytes);
|
||||||
m_Client->SendData((const char *)Encrypted, NumBytes);
|
m_Client->SendData((const char *)Encrypted, NumBytes);
|
||||||
a_Size -= NumBytes;
|
a_Size -= NumBytes;
|
||||||
a_Data += NumBytes;
|
a_Data += NumBytes;
|
||||||
|
@ -26,21 +26,20 @@ Declares the 1.7.x protocol classes:
|
|||||||
#pragma warning(disable:4702)
|
#pragma warning(disable:4702)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "cryptopp/modes.h"
|
|
||||||
#include "cryptopp/aes.h"
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "../Crypto.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cProtocol172 :
|
class cProtocol172 :
|
||||||
public cProtocol // TODO
|
public cProtocol
|
||||||
{
|
{
|
||||||
typedef cProtocol super; // TODO
|
typedef cProtocol super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -220,9 +219,9 @@ protected:
|
|||||||
cByteBuffer m_OutPacketLenBuffer;
|
cByteBuffer m_OutPacketLenBuffer;
|
||||||
|
|
||||||
bool m_IsEncrypted;
|
bool m_IsEncrypted;
|
||||||
CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption m_Decryptor;
|
|
||||||
CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption m_Encryptor;
|
|
||||||
|
|
||||||
|
cAESCFBDecryptor m_Decryptor;
|
||||||
|
cAESCFBEncryptor m_Encryptor;
|
||||||
|
|
||||||
/// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets
|
/// Adds the received (unencrypted) data to m_ReceivedData, parses complete packets
|
||||||
void AddReceivedData(const char * a_Data, int a_Size);
|
void AddReceivedData(const char * a_Data, int a_Size);
|
||||||
|
@ -965,7 +965,7 @@ void cProtocolRecognizer::SendLengthlessServerPing(void)
|
|||||||
m_Buffer.ResetRead();
|
m_Buffer.ResetRead();
|
||||||
if (m_Buffer.CanReadBytes(2))
|
if (m_Buffer.CanReadBytes(2))
|
||||||
{
|
{
|
||||||
byte val;
|
Byte val;
|
||||||
m_Buffer.ReadByte(val); // Packet type - Serverlist ping
|
m_Buffer.ReadByte(val); // Packet type - Serverlist ping
|
||||||
m_Buffer.ReadByte(val); // 0x01 magic value
|
m_Buffer.ReadByte(val); // 0x01 magic value
|
||||||
ASSERT(val == 0x01);
|
ASSERT(val == 0x01);
|
||||||
|
@ -284,17 +284,9 @@ int cServer::GetNumPlayers(void)
|
|||||||
|
|
||||||
void cServer::PrepareKeys(void)
|
void cServer::PrepareKeys(void)
|
||||||
{
|
{
|
||||||
// TODO: Save and load key for persistence across sessions
|
|
||||||
// But generating the key takes only a moment, do we even need that?
|
|
||||||
|
|
||||||
LOGD("Generating protocol encryption keypair...");
|
LOGD("Generating protocol encryption keypair...");
|
||||||
|
VERIFY(m_PrivateKey.Generate(1024));
|
||||||
time_t CurTime = time(NULL);
|
m_PublicKeyDER = m_PrivateKey.GetPubKeyDER();
|
||||||
CryptoPP::RandomPool rng;
|
|
||||||
rng.Put((const byte *)&CurTime, sizeof(CurTime));
|
|
||||||
m_PrivateKey.GenerateRandomWithKeySize(rng, 1024);
|
|
||||||
CryptoPP::RSA::PublicKey pk(m_PrivateKey);
|
|
||||||
m_PublicKey = pk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
14
src/Server.h
14
src/Server.h
@ -23,8 +23,7 @@
|
|||||||
#pragma warning(disable:4702)
|
#pragma warning(disable:4702)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "cryptopp/rsa.h"
|
#include "Crypto.h"
|
||||||
#include "cryptopp/randpool.h"
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
@ -110,8 +109,8 @@ public: // tolua_export
|
|||||||
/** Returns base64 encoded favicon data (obtained from favicon.png) */
|
/** Returns base64 encoded favicon data (obtained from favicon.png) */
|
||||||
const AString & GetFaviconData(void) const { return m_FaviconData; }
|
const AString & GetFaviconData(void) const { return m_FaviconData; }
|
||||||
|
|
||||||
CryptoPP::RSA::PrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
|
cRSAPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
|
||||||
CryptoPP::RSA::PublicKey & GetPublicKey (void) { return m_PublicKey; }
|
const AString & GetPublicKeyDER(void) const { return m_PublicKeyDER; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -180,8 +179,11 @@ private:
|
|||||||
|
|
||||||
bool m_bRestarting;
|
bool m_bRestarting;
|
||||||
|
|
||||||
CryptoPP::RSA::PrivateKey m_PrivateKey;
|
/** The private key used for the assymetric encryption start in the protocols */
|
||||||
CryptoPP::RSA::PublicKey m_PublicKey;
|
cRSAPrivateKey m_PrivateKey;
|
||||||
|
|
||||||
|
/** Public key for m_PrivateKey, ASN1-DER-encoded */
|
||||||
|
AString m_PublicKeyDER;
|
||||||
|
|
||||||
cRCONServer m_RCONServer;
|
cRCONServer m_RCONServer;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user