XChaCha20-Poly1305 via libsodium
This commit is contained in:
@@ -2,8 +2,7 @@ file(GLOB_RECURSE FILE_SOURCES "*.h" "*.c" "*.cpp")
|
||||
|
||||
add_library(AudioLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(AudioLib
|
||||
cryptopp-static
|
||||
target_link_libraries(AudioLib
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
file(GLOB_RECURSE FILE_SOURCES "*.h" "*.c" "*.cpp")
|
||||
|
||||
# Use tea.cpp from EterBase instead of maintaining a local copy
|
||||
list(APPEND FILE_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../EterBase/tea.cpp")
|
||||
|
||||
add_executable(DumpProto ${FILE_SOURCES})
|
||||
set_target_properties(DumpProto PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
target_include_directories(DumpProto PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../EterBase
|
||||
)
|
||||
|
||||
target_link_libraries(DumpProto
|
||||
lzo2
|
||||
)
|
||||
sodium
|
||||
)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <cstring>
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <sodium.h>
|
||||
|
||||
#include "lzo.h"
|
||||
|
||||
@@ -1152,7 +1153,13 @@ int main(int argc, char ** argv)
|
||||
|
||||
printf("=== MAIN START ===\n");
|
||||
fflush(stdout);
|
||||
|
||||
|
||||
if (sodium_init() < 0)
|
||||
{
|
||||
fprintf(stderr, "sodium_init() failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (BuildMobTable())
|
||||
{
|
||||
printf("=== BuildMobTable returned TRUE ===\n");
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Filename: tea.c
|
||||
* Description: TEA 암호화 모듈
|
||||
*
|
||||
* Author: 김한주 (aka. 비엽, Cronan), 송영진 (aka. myevan, 빗자루)
|
||||
*/
|
||||
#include "tea.h"
|
||||
#include <memory.h>
|
||||
|
||||
/*
|
||||
* TEA Encryption Module Instruction
|
||||
* Edited by 김한주 aka. 비엽, Cronan
|
||||
*
|
||||
* void tea_code(const unsigned long sz, const unsigned long sy, const unsigned long *key, unsigned long *dest)
|
||||
* void tea_decode(const unsigned long sz, const unsigned long sy, const unsigned long *key, unsigned long *dest)
|
||||
* 8바이트를 암호/복호화 할때 사용된다. key 는 16 바이트여야 한다.
|
||||
* sz, sy 는 8바이트의 역순으로 대입한다.
|
||||
*
|
||||
* int tea_decrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size);
|
||||
* int tea_encrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size);
|
||||
* 한꺼번에 8 바이트 이상을 암호/복호화 할때 사용한다. 만약 size 가
|
||||
* 8의 배수가 아니면 8의 배수로 크기를 "늘려서" 암호화 한다.
|
||||
*
|
||||
* ex. tea_code(pdwSrc[1], pdwSrc[0], pdwKey, pdwDest);
|
||||
* tea_decrypt(pdwDest, pdwSrc, pdwKey, nSize);
|
||||
*/
|
||||
|
||||
#define TEA_ROUND 32 // 32 를 권장하며, 높을 수록 결과가 난해해 진다.
|
||||
#define DELTA 0x9E3779B9 // DELTA 값 바꾸지 말것.
|
||||
|
||||
void tea_code(const unsigned long sz, const unsigned long sy, const unsigned long *key, unsigned long *dest)
|
||||
{
|
||||
register unsigned long y = sy, z = sz, sum = 0;
|
||||
unsigned long n = TEA_ROUND;
|
||||
|
||||
while (n-- > 0)
|
||||
{
|
||||
y += ((z << 4 ^ z >> 5) + z) ^ (sum + key[sum & 3]);
|
||||
sum += DELTA;
|
||||
z += ((y << 4 ^ y >> 5) + y) ^ (sum + key[sum >> 11 & 3]);
|
||||
}
|
||||
|
||||
*(dest++) = y;
|
||||
*dest = z;
|
||||
}
|
||||
|
||||
void tea_decode(const unsigned long sz, const unsigned long sy, const unsigned long *key, unsigned long *dest)
|
||||
{
|
||||
#pragma warning(disable:4307)
|
||||
register unsigned long y = sy, z = sz, sum = DELTA * TEA_ROUND;
|
||||
#pragma warning(default:4307)
|
||||
|
||||
unsigned long n = TEA_ROUND;
|
||||
|
||||
while (n-- > 0)
|
||||
{
|
||||
z -= ((y << 4 ^ y >> 5) + y) ^ (sum + key[sum >> 11 & 3]);
|
||||
sum -= DELTA;
|
||||
y -= ((z << 4 ^ z >> 5) + z) ^ (sum + key[sum & 3]);
|
||||
}
|
||||
|
||||
*(dest++) = y;
|
||||
*dest = z;
|
||||
}
|
||||
|
||||
int tea_encrypt(unsigned long *dest, const unsigned long *src, const unsigned long * key, int size)
|
||||
{
|
||||
int i;
|
||||
int resize;
|
||||
|
||||
if (size % 8 != 0)
|
||||
{
|
||||
resize = size + 8 - (size % 8);
|
||||
memset((char *) src + size, 0, resize - size);
|
||||
}
|
||||
else
|
||||
resize = size;
|
||||
|
||||
for (i = 0; i < resize >> 3; i++, dest += 2, src += 2)
|
||||
tea_code(*(src + 1), *src, key, dest);
|
||||
|
||||
return (resize);
|
||||
}
|
||||
|
||||
int tea_decrypt(unsigned long *dest, const unsigned long *src, const unsigned long * key, int size)
|
||||
{
|
||||
int i;
|
||||
int resize;
|
||||
|
||||
if (size % 8 != 0)
|
||||
resize = size + 8 - (size % 8);
|
||||
else
|
||||
resize = size;
|
||||
|
||||
for (i = 0; i < resize >> 3; i++, dest += 2, src += 2)
|
||||
tea_decode(*(src + 1), *src, key, dest);
|
||||
|
||||
return (resize);
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* TEA is a 64-bit symmetric block cipher with a 128-bit key, developed
|
||||
by David J. Wheeler and Roger M. Needham, and described in their
|
||||
paper at <URL:http://www.cl.cam.ac.uk/ftp/users/djw3/tea.ps>.
|
||||
|
||||
This implementation is based on their code in
|
||||
<URL:http://www.cl.cam.ac.uk/ftp/users/djw3/xtea.ps> */
|
||||
|
||||
int tea_encrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size);
|
||||
int tea_decrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
add_library(EffectLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(EffectLib
|
||||
cryptopp-static
|
||||
target_link_libraries(EffectLib
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
add_library(EterBase STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(EterBase
|
||||
target_link_libraries(EterBase
|
||||
lzo2
|
||||
cryptopp-static
|
||||
sodium
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
294
src/EterBase/SecureCipher.cpp
Normal file
294
src/EterBase/SecureCipher.cpp
Normal file
@@ -0,0 +1,294 @@
|
||||
#include "StdAfx.h"
|
||||
#include "SecureCipher.h"
|
||||
|
||||
// Static initialization flag for libsodium
|
||||
static bool s_sodiumInitialized = false;
|
||||
|
||||
static bool EnsureSodiumInit()
|
||||
{
|
||||
if (!s_sodiumInitialized)
|
||||
{
|
||||
if (sodium_init() < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
s_sodiumInitialized = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SecureCipher::SecureCipher()
|
||||
{
|
||||
sodium_memzero(m_pk, sizeof(m_pk));
|
||||
sodium_memzero(m_sk, sizeof(m_sk));
|
||||
sodium_memzero(m_tx_key, sizeof(m_tx_key));
|
||||
sodium_memzero(m_rx_key, sizeof(m_rx_key));
|
||||
sodium_memzero(m_session_token, sizeof(m_session_token));
|
||||
}
|
||||
|
||||
SecureCipher::~SecureCipher()
|
||||
{
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
bool SecureCipher::Initialize()
|
||||
{
|
||||
if (!EnsureSodiumInit())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate X25519 keypair
|
||||
if (crypto_kx_keypair(m_pk, m_sk) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_tx_nonce = 0;
|
||||
m_rx_nonce = 0;
|
||||
m_initialized = true;
|
||||
m_activated = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SecureCipher::CleanUp()
|
||||
{
|
||||
// Securely erase all sensitive key material
|
||||
sodium_memzero(m_sk, sizeof(m_sk));
|
||||
sodium_memzero(m_tx_key, sizeof(m_tx_key));
|
||||
sodium_memzero(m_rx_key, sizeof(m_rx_key));
|
||||
sodium_memzero(m_session_token, sizeof(m_session_token));
|
||||
|
||||
m_initialized = false;
|
||||
m_activated = false;
|
||||
m_tx_nonce = 0;
|
||||
m_rx_nonce = 0;
|
||||
}
|
||||
|
||||
void SecureCipher::GetPublicKey(uint8_t* out_pk) const
|
||||
{
|
||||
memcpy(out_pk, m_pk, PK_SIZE);
|
||||
}
|
||||
|
||||
bool SecureCipher::ComputeClientKeys(const uint8_t* server_pk)
|
||||
{
|
||||
if (!m_initialized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Client: tx_key is for sending TO server, rx_key is for receiving FROM server
|
||||
if (crypto_kx_client_session_keys(m_rx_key, m_tx_key, m_pk, m_sk, server_pk) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SecureCipher::ComputeServerKeys(const uint8_t* client_pk)
|
||||
{
|
||||
if (!m_initialized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Server: tx_key is for sending TO client, rx_key is for receiving FROM client
|
||||
if (crypto_kx_server_session_keys(m_rx_key, m_tx_key, m_pk, m_sk, client_pk) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SecureCipher::GenerateChallenge(uint8_t* out_challenge)
|
||||
{
|
||||
randombytes_buf(out_challenge, CHALLENGE_SIZE);
|
||||
}
|
||||
|
||||
void SecureCipher::ComputeChallengeResponse(const uint8_t* challenge, uint8_t* out_response)
|
||||
{
|
||||
// HMAC the challenge using our rx_key as the authentication key
|
||||
// This proves we derived the correct shared secret
|
||||
crypto_auth(out_response, challenge, CHALLENGE_SIZE, m_rx_key);
|
||||
}
|
||||
|
||||
bool SecureCipher::VerifyChallengeResponse(const uint8_t* challenge, const uint8_t* response)
|
||||
{
|
||||
// Verify the HMAC - peer should have used their tx_key (our rx_key) to compute it
|
||||
return crypto_auth_verify(response, challenge, CHALLENGE_SIZE, m_rx_key) == 0;
|
||||
}
|
||||
|
||||
void SecureCipher::BuildNonce(uint8_t* nonce, uint64_t counter, bool is_tx)
|
||||
{
|
||||
// 24-byte nonce structure:
|
||||
// [0]: direction flag (0x01 for tx, 0x02 for rx)
|
||||
// [1-7]: reserved/zero
|
||||
// [8-15]: 64-bit counter (little-endian)
|
||||
// [16-23]: reserved/zero
|
||||
|
||||
sodium_memzero(nonce, NONCE_SIZE);
|
||||
nonce[0] = is_tx ? 0x01 : 0x02;
|
||||
|
||||
// Store counter in little-endian at offset 8
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
nonce[8 + i] = (uint8_t)(counter >> (i * 8));
|
||||
}
|
||||
}
|
||||
|
||||
size_t SecureCipher::Encrypt(const void* plaintext, size_t plaintext_len, void* ciphertext)
|
||||
{
|
||||
if (!m_activated)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t nonce[NONCE_SIZE];
|
||||
BuildNonce(nonce, m_tx_nonce, true);
|
||||
|
||||
unsigned long long ciphertext_len = 0;
|
||||
|
||||
if (crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
(uint8_t*)ciphertext, &ciphertext_len,
|
||||
(const uint8_t*)plaintext, plaintext_len,
|
||||
nullptr, 0, // No additional data
|
||||
nullptr, // No secret nonce
|
||||
nonce,
|
||||
m_tx_key) != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
++m_tx_nonce;
|
||||
return (size_t)ciphertext_len;
|
||||
}
|
||||
|
||||
size_t SecureCipher::Decrypt(const void* ciphertext, size_t ciphertext_len, void* plaintext)
|
||||
{
|
||||
if (!m_activated)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ciphertext_len < TAG_SIZE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t nonce[NONCE_SIZE];
|
||||
BuildNonce(nonce, m_rx_nonce, false);
|
||||
|
||||
unsigned long long plaintext_len = 0;
|
||||
|
||||
if (crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
(uint8_t*)plaintext, &plaintext_len,
|
||||
nullptr, // No secret nonce output
|
||||
(const uint8_t*)ciphertext, ciphertext_len,
|
||||
nullptr, 0, // No additional data
|
||||
nonce,
|
||||
m_rx_key) != 0)
|
||||
{
|
||||
// Decryption failed - either wrong key, tampered data, or replay attack
|
||||
return 0;
|
||||
}
|
||||
|
||||
++m_rx_nonce;
|
||||
return (size_t)plaintext_len;
|
||||
}
|
||||
|
||||
void SecureCipher::EncryptInPlace(void* buffer, size_t len)
|
||||
{
|
||||
if (!m_activated || len == 0)
|
||||
return;
|
||||
|
||||
uint8_t nonce[NONCE_SIZE];
|
||||
BuildNonce(nonce, m_tx_nonce, true);
|
||||
|
||||
crypto_stream_xchacha20_xor_ic(
|
||||
(uint8_t*)buffer,
|
||||
(const uint8_t*)buffer,
|
||||
(unsigned long long)len,
|
||||
nonce,
|
||||
0,
|
||||
m_tx_key);
|
||||
|
||||
++m_tx_nonce;
|
||||
}
|
||||
|
||||
void SecureCipher::DecryptInPlace(void* buffer, size_t len)
|
||||
{
|
||||
if (!m_activated || len == 0)
|
||||
return;
|
||||
|
||||
uint8_t nonce[NONCE_SIZE];
|
||||
BuildNonce(nonce, m_rx_nonce, false);
|
||||
|
||||
crypto_stream_xchacha20_xor_ic(
|
||||
(uint8_t*)buffer,
|
||||
(const uint8_t*)buffer,
|
||||
(unsigned long long)len,
|
||||
nonce,
|
||||
0,
|
||||
m_rx_key);
|
||||
|
||||
++m_rx_nonce;
|
||||
}
|
||||
|
||||
bool SecureCipher::EncryptToken(const uint8_t* plaintext, size_t len,
|
||||
uint8_t* ciphertext, uint8_t* nonce_out)
|
||||
{
|
||||
if (!m_initialized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate random nonce for this one-time encryption
|
||||
randombytes_buf(nonce_out, NONCE_SIZE);
|
||||
|
||||
unsigned long long ciphertext_len = 0;
|
||||
|
||||
if (crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||
ciphertext, &ciphertext_len,
|
||||
plaintext, len,
|
||||
nullptr, 0,
|
||||
nullptr,
|
||||
nonce_out,
|
||||
m_tx_key) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SecureCipher::DecryptToken(const uint8_t* ciphertext, size_t len,
|
||||
const uint8_t* nonce, uint8_t* plaintext)
|
||||
{
|
||||
if (!m_initialized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long long plaintext_len = 0;
|
||||
|
||||
if (crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
plaintext, &plaintext_len,
|
||||
nullptr,
|
||||
ciphertext, len,
|
||||
nullptr, 0,
|
||||
nonce,
|
||||
m_rx_key) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SecureCipher::SetSessionToken(const uint8_t* token)
|
||||
{
|
||||
memcpy(m_session_token, token, SESSION_TOKEN_SIZE);
|
||||
}
|
||||
102
src/EterBase/SecureCipher.h
Normal file
102
src/EterBase/SecureCipher.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
|
||||
#include <sodium.h>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
class SecureCipher {
|
||||
public:
|
||||
// libsodium constants
|
||||
static constexpr size_t PK_SIZE = crypto_kx_PUBLICKEYBYTES; // 32
|
||||
static constexpr size_t SK_SIZE = crypto_kx_SECRETKEYBYTES; // 32
|
||||
static constexpr size_t KEY_SIZE = crypto_kx_SESSIONKEYBYTES; // 32
|
||||
static constexpr size_t NONCE_SIZE = crypto_aead_xchacha20poly1305_ietf_NPUBBYTES; // 24
|
||||
static constexpr size_t TAG_SIZE = crypto_aead_xchacha20poly1305_ietf_ABYTES; // 16
|
||||
static constexpr size_t CHALLENGE_SIZE = 32;
|
||||
static constexpr size_t SESSION_TOKEN_SIZE = 32;
|
||||
static constexpr size_t HMAC_SIZE = crypto_auth_BYTES; // 32
|
||||
|
||||
SecureCipher();
|
||||
~SecureCipher();
|
||||
|
||||
// Initialization - generates keypair
|
||||
bool Initialize();
|
||||
void CleanUp();
|
||||
|
||||
// Key exchange
|
||||
void GetPublicKey(uint8_t* out_pk) const;
|
||||
|
||||
// Client computes session keys from server's public key
|
||||
bool ComputeClientKeys(const uint8_t* server_pk);
|
||||
|
||||
// Server computes session keys from client's public key
|
||||
bool ComputeServerKeys(const uint8_t* client_pk);
|
||||
|
||||
// Challenge-response for authentication
|
||||
void GenerateChallenge(uint8_t* out_challenge);
|
||||
void ComputeChallengeResponse(const uint8_t* challenge, uint8_t* out_response);
|
||||
bool VerifyChallengeResponse(const uint8_t* challenge, const uint8_t* response);
|
||||
|
||||
// AEAD encryption - output is len + TAG_SIZE bytes
|
||||
// Returns actual ciphertext length (plaintext_len + TAG_SIZE)
|
||||
size_t Encrypt(const void* plaintext, size_t plaintext_len, void* ciphertext);
|
||||
|
||||
// AEAD decryption - input must be ciphertext_len bytes (includes TAG_SIZE)
|
||||
// Returns actual plaintext length, or 0 on failure
|
||||
size_t Decrypt(const void* ciphertext, size_t ciphertext_len, void* plaintext);
|
||||
|
||||
// In-place stream encryption for network buffers (XChaCha20, no tag overhead)
|
||||
// Same length in/out. Nonce counter prevents replay.
|
||||
void EncryptInPlace(void* buffer, size_t len);
|
||||
void DecryptInPlace(void* buffer, size_t len);
|
||||
|
||||
// Encrypt a single token with explicit nonce (for KeyComplete packet)
|
||||
bool EncryptToken(const uint8_t* plaintext, size_t len,
|
||||
uint8_t* ciphertext, uint8_t* nonce_out);
|
||||
bool DecryptToken(const uint8_t* ciphertext, size_t len,
|
||||
const uint8_t* nonce, uint8_t* plaintext);
|
||||
|
||||
// State
|
||||
bool IsActivated() const { return m_activated; }
|
||||
void SetActivated(bool value) { m_activated = value; }
|
||||
bool IsInitialized() const { return m_initialized; }
|
||||
|
||||
// Session token management
|
||||
void SetSessionToken(const uint8_t* token);
|
||||
const uint8_t* GetSessionToken() const { return m_session_token; }
|
||||
|
||||
// Get current nonce counters (for debugging/logging)
|
||||
uint64_t GetTxNonce() const { return m_tx_nonce; }
|
||||
uint64_t GetRxNonce() const { return m_rx_nonce; }
|
||||
|
||||
// Access keys directly (for special decrypt operations like session token)
|
||||
const uint8_t* GetRxKey() const { return m_rx_key; }
|
||||
const uint8_t* GetTxKey() const { return m_tx_key; }
|
||||
|
||||
// Alias for convenience
|
||||
void ComputeResponse(const uint8_t* challenge, uint8_t* out_response) {
|
||||
ComputeChallengeResponse(challenge, out_response);
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_initialized = false;
|
||||
bool m_activated = false;
|
||||
|
||||
// X25519 keypair
|
||||
uint8_t m_pk[PK_SIZE];
|
||||
uint8_t m_sk[SK_SIZE];
|
||||
|
||||
// Session keys derived from key exchange
|
||||
uint8_t m_tx_key[KEY_SIZE]; // Key for encrypting outgoing packets
|
||||
uint8_t m_rx_key[KEY_SIZE]; // Key for decrypting incoming packets
|
||||
|
||||
// Nonce counters - prevent replay attacks
|
||||
uint64_t m_tx_nonce = 0;
|
||||
uint64_t m_rx_nonce = 0;
|
||||
|
||||
// Server-generated session token
|
||||
uint8_t m_session_token[SESSION_TOKEN_SIZE];
|
||||
|
||||
// Build 24-byte nonce from counter
|
||||
void BuildNonce(uint8_t* nonce, uint64_t counter, bool is_tx);
|
||||
};
|
||||
@@ -1,414 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "cipher.h"
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
//#pragma warning(push)
|
||||
//#pragma warning(disable: 4100 4127 4189 4231 4512 4706)
|
||||
|
||||
#include <modes.h>
|
||||
#include <nbtheory.h>
|
||||
#include <osrng.h>
|
||||
|
||||
// Diffie-Hellman key agreement
|
||||
#include <dh.h>
|
||||
#include <dh2.h>
|
||||
|
||||
// AES winner and candidates
|
||||
#include <aes.h>
|
||||
#include <cast.h>
|
||||
#include <rc6.h>
|
||||
#include <mars.h>
|
||||
#include <serpent.h>
|
||||
#include <twofish.h>
|
||||
// Other block ciphers
|
||||
#include <blowfish.h>
|
||||
#include <camellia.h>
|
||||
#include <des.h>
|
||||
#include <idea.h>
|
||||
#include <rc5.h>
|
||||
#include <seed.h>
|
||||
#include <shacal2.h>
|
||||
#include <skipjack.h>
|
||||
#include <tea.h>
|
||||
#include "Debug.h"
|
||||
|
||||
|
||||
using namespace CryptoPP;
|
||||
|
||||
// Block cipher algorithm selector abstract base class.
|
||||
struct BlockCipherAlgorithm {
|
||||
enum {
|
||||
kDefault, // to give more chances to default algorithm
|
||||
// AES winner and candidates
|
||||
// kAES, // Rijndael
|
||||
kRC6,
|
||||
kMARS,
|
||||
kTwofish,
|
||||
kSerpent,
|
||||
kCAST256,
|
||||
// Other block ciphers
|
||||
kIDEA,
|
||||
k3DES, // DES-EDE2
|
||||
kCamellia,
|
||||
kSEED,
|
||||
kRC5,
|
||||
kBlowfish,
|
||||
kTEA,
|
||||
//kSKIPJACK,
|
||||
kSHACAL2,
|
||||
// End sentinel
|
||||
kMaxAlgorithms
|
||||
};
|
||||
|
||||
BlockCipherAlgorithm() {}
|
||||
virtual ~BlockCipherAlgorithm() {}
|
||||
|
||||
static BlockCipherAlgorithm* Pick(int hint);
|
||||
|
||||
virtual int GetBlockSize() const = 0;
|
||||
virtual int GetDefaultKeyLength() const = 0;
|
||||
virtual int GetIVLength() const = 0;
|
||||
|
||||
virtual SymmetricCipher* CreateEncoder(const CryptoPP::byte* key, size_t keylen,
|
||||
const CryptoPP::byte* iv) const = 0;
|
||||
virtual SymmetricCipher* CreateDecoder(const CryptoPP::byte* key, size_t keylen,
|
||||
const CryptoPP::byte* iv) const = 0;
|
||||
};
|
||||
|
||||
// Block cipher (with CTR mode) algorithm selector template class.
|
||||
template<class T>
|
||||
struct BlockCipherDetail : public BlockCipherAlgorithm {
|
||||
BlockCipherDetail() {}
|
||||
virtual ~BlockCipherDetail() {}
|
||||
|
||||
virtual int GetBlockSize() const { return T::BLOCKSIZE; }
|
||||
virtual int GetDefaultKeyLength() const { return T::DEFAULT_KEYLENGTH; }
|
||||
virtual int GetIVLength() const { return T::IV_LENGTH; }
|
||||
|
||||
virtual SymmetricCipher* CreateEncoder(const CryptoPP::byte* key, size_t keylen,
|
||||
const CryptoPP::byte* iv) const
|
||||
{
|
||||
return new typename CTR_Mode<T>::Encryption(key, keylen, iv);
|
||||
}
|
||||
virtual SymmetricCipher* CreateDecoder(const CryptoPP::byte* key, size_t keylen,
|
||||
const CryptoPP::byte* iv) const
|
||||
{
|
||||
return new typename CTR_Mode<T>::Decryption(key, keylen, iv);
|
||||
}
|
||||
};
|
||||
|
||||
// Key agreement scheme abstract class.
|
||||
class KeyAgreement {
|
||||
public:
|
||||
KeyAgreement() {}
|
||||
virtual ~KeyAgreement() {}
|
||||
|
||||
virtual size_t Prepare(void* buffer, size_t* length) = 0;
|
||||
virtual bool Agree(size_t agreed_length, const void* buffer, size_t length) = 0;
|
||||
|
||||
const SecByteBlock& shared() const { return shared_; }
|
||||
|
||||
protected:
|
||||
SecByteBlock shared_;
|
||||
};
|
||||
|
||||
// Crypto++ Unified Diffie-Hellman key agreement scheme implementation.
|
||||
class DH2KeyAgreement : public KeyAgreement {
|
||||
public:
|
||||
DH2KeyAgreement();
|
||||
virtual ~DH2KeyAgreement();
|
||||
|
||||
virtual size_t Prepare(void* buffer, size_t* length);
|
||||
virtual bool Agree(size_t agreed_length, const void* buffer, size_t length);
|
||||
|
||||
private:
|
||||
DH dh_;
|
||||
DH2 dh2_;
|
||||
SecByteBlock spriv_key_;
|
||||
SecByteBlock epriv_key_;
|
||||
};
|
||||
|
||||
Cipher::Cipher()
|
||||
: activated_(false), encoder_(NULL), decoder_(NULL), key_agreement_(NULL) {
|
||||
}
|
||||
|
||||
Cipher::~Cipher() {
|
||||
if (activated_) {
|
||||
CleanUp();
|
||||
}
|
||||
}
|
||||
|
||||
void Cipher::CleanUp() {
|
||||
if (encoder_ != NULL) {
|
||||
delete encoder_;
|
||||
encoder_ = NULL;
|
||||
}
|
||||
if (decoder_ != NULL) {
|
||||
delete decoder_;
|
||||
decoder_ = NULL;
|
||||
}
|
||||
if (key_agreement_ != NULL) {
|
||||
delete key_agreement_;
|
||||
key_agreement_ = NULL;
|
||||
}
|
||||
activated_ = false;
|
||||
}
|
||||
|
||||
size_t Cipher::Prepare(void* buffer, size_t* length) {
|
||||
|
||||
assert(key_agreement_ == NULL);
|
||||
key_agreement_ = new DH2KeyAgreement();
|
||||
assert(key_agreement_ != NULL);
|
||||
size_t agreed_length = key_agreement_->Prepare(buffer, length);
|
||||
if (agreed_length == 0) {
|
||||
delete key_agreement_;
|
||||
key_agreement_ = NULL;
|
||||
}
|
||||
|
||||
return agreed_length;
|
||||
}
|
||||
|
||||
bool Cipher::Activate(bool polarity, size_t agreed_length,
|
||||
const void* buffer, size_t length) {
|
||||
|
||||
assert(activated_ == false);
|
||||
assert(key_agreement_ != NULL);
|
||||
bool result = false;
|
||||
if (key_agreement_->Agree(agreed_length, buffer, length)) {
|
||||
result = SetUp(polarity);
|
||||
}
|
||||
delete key_agreement_;
|
||||
key_agreement_ = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Cipher::SetUp(bool polarity) {
|
||||
assert(key_agreement_ != NULL);
|
||||
const SecByteBlock& shared = key_agreement_->shared();
|
||||
|
||||
// Pick a block cipher algorithm
|
||||
|
||||
if (shared.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int hint_0 = shared.BytePtr()[*(shared.BytePtr()) % shared.size()];
|
||||
int hint_1 = shared.BytePtr()[*(shared.BytePtr() + 1) % shared.size()];
|
||||
BlockCipherAlgorithm* detail_0 = BlockCipherAlgorithm::Pick(hint_0);
|
||||
BlockCipherAlgorithm* detail_1 = BlockCipherAlgorithm::Pick(hint_1);
|
||||
assert(detail_0 != NULL);
|
||||
assert(detail_1 != NULL);
|
||||
std::unique_ptr<BlockCipherAlgorithm> algorithm_0(detail_0);
|
||||
std::unique_ptr<BlockCipherAlgorithm> algorithm_1(detail_1);
|
||||
|
||||
const size_t key_length_0 = algorithm_0->GetDefaultKeyLength();
|
||||
const size_t iv_length_0 = algorithm_0->GetBlockSize();
|
||||
|
||||
if (shared.size() < key_length_0 || shared.size() < iv_length_0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t key_length_1 = algorithm_1->GetDefaultKeyLength();
|
||||
const size_t iv_length_1 = algorithm_1->GetBlockSize();
|
||||
|
||||
if (shared.size() < key_length_1 || shared.size() < iv_length_1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pick encryption keys and initial vectors
|
||||
|
||||
SecByteBlock key_0(key_length_0), iv_0(iv_length_0);
|
||||
SecByteBlock key_1(key_length_1), iv_1(iv_length_1);
|
||||
|
||||
size_t offset;
|
||||
|
||||
key_0.Assign(shared, key_length_0);
|
||||
offset = key_length_0;
|
||||
offset = std::min(key_length_0, shared.size() - key_length_1);
|
||||
key_1.Assign(shared.BytePtr() + offset, key_length_1);
|
||||
|
||||
offset = shared.size() - iv_length_0;
|
||||
iv_0.Assign(shared.BytePtr() + offset, iv_length_0);
|
||||
offset = (offset < iv_length_1 ? 0 : offset - iv_length_1);
|
||||
iv_1.Assign(shared.BytePtr() + offset, iv_length_1);
|
||||
|
||||
// Create encryption/decryption objects
|
||||
|
||||
if (polarity) {
|
||||
encoder_ = algorithm_1->CreateEncoder(key_1, key_1.size(), iv_1);
|
||||
decoder_ = algorithm_0->CreateDecoder(key_0, key_0.size(), iv_0);
|
||||
} else {
|
||||
encoder_ = algorithm_0->CreateEncoder(key_0, key_0.size(), iv_0);
|
||||
decoder_ = algorithm_1->CreateDecoder(key_1, key_1.size(), iv_1);
|
||||
}
|
||||
|
||||
assert(encoder_ != NULL);
|
||||
assert(decoder_ != NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BlockCipherAlgorithm* BlockCipherAlgorithm::Pick(int hint) {
|
||||
BlockCipherAlgorithm* detail;
|
||||
int selector = hint % kMaxAlgorithms;
|
||||
switch (selector) {
|
||||
//case kAES:
|
||||
// detail = new BlockCipherDetail<AES>();
|
||||
break;
|
||||
case kRC6:
|
||||
detail = new BlockCipherDetail<RC6>();
|
||||
break;
|
||||
case kMARS:
|
||||
detail = new BlockCipherDetail<MARS>();
|
||||
break;
|
||||
case kTwofish:
|
||||
detail = new BlockCipherDetail<Twofish>();
|
||||
break;
|
||||
case kSerpent:
|
||||
detail = new BlockCipherDetail<Serpent>();
|
||||
break;
|
||||
case kCAST256:
|
||||
detail = new BlockCipherDetail<CAST256>();
|
||||
break;
|
||||
case kIDEA:
|
||||
detail = new BlockCipherDetail<IDEA>();
|
||||
break;
|
||||
case k3DES:
|
||||
detail = new BlockCipherDetail<DES_EDE2>();
|
||||
break;
|
||||
case kCamellia:
|
||||
detail = new BlockCipherDetail<Camellia>();
|
||||
break;
|
||||
case kSEED:
|
||||
detail = new BlockCipherDetail<SEED>();
|
||||
break;
|
||||
case kRC5:
|
||||
detail = new BlockCipherDetail<RC5>();
|
||||
break;
|
||||
case kBlowfish:
|
||||
detail = new BlockCipherDetail<Blowfish>();
|
||||
break;
|
||||
case kTEA:
|
||||
detail = new BlockCipherDetail<TEA>();
|
||||
break;
|
||||
// case kSKIPJACK:
|
||||
// detail = new BlockCipherDetail<SKIPJACK>();
|
||||
// break;
|
||||
case kSHACAL2:
|
||||
detail = new BlockCipherDetail<SHACAL2>();
|
||||
break;
|
||||
case kDefault:
|
||||
default:
|
||||
detail = new BlockCipherDetail<Twofish>(); // default algorithm
|
||||
break;
|
||||
}
|
||||
|
||||
return detail;
|
||||
}
|
||||
|
||||
DH2KeyAgreement::DH2KeyAgreement() : dh_(), dh2_(dh_) {
|
||||
}
|
||||
|
||||
DH2KeyAgreement::~DH2KeyAgreement() {
|
||||
}
|
||||
|
||||
size_t DH2KeyAgreement::Prepare(void* buffer, size_t* length) {
|
||||
// RFC 5114, 1024-bit MODP Group with 160-bit Prime Order Subgroup
|
||||
// http://tools.ietf.org/html/rfc5114#section-2.1
|
||||
Integer p("0xB10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6"
|
||||
"9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0"
|
||||
"13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70"
|
||||
"98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0"
|
||||
"A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708"
|
||||
"DF1FB2BC2E4A4371");
|
||||
|
||||
Integer g("0xA4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F"
|
||||
"D6406CFF14266D31266FEA1E5C41564B777E690F5504F213"
|
||||
"160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1"
|
||||
"909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A"
|
||||
"D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24"
|
||||
"855E6EEB22B3B2E5");
|
||||
|
||||
Integer q("0xF518AA8781A8DF278ABA4E7D64B7CB9D49462353");
|
||||
|
||||
// Schnorr Group primes are of the form p = rq + 1, p and q prime. They
|
||||
// provide a subgroup order. In the case of 1024-bit MODP Group, the
|
||||
// security level is 80 bits (based on the 160-bit prime order subgroup).
|
||||
|
||||
// For a compare/contrast of using the maximum security level, see
|
||||
// dh-unified.zip. Also see http://www.cryptopp.com/wiki/Diffie-Hellman
|
||||
// and http://www.cryptopp.com/wiki/Security_level .
|
||||
|
||||
AutoSeededRandomPool rnd;
|
||||
|
||||
dh_.AccessGroupParameters().Initialize(p, q, g);
|
||||
|
||||
if(!dh_.GetGroupParameters().ValidateGroup(rnd, 3)) {
|
||||
// Failed to validate prime and generator
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
|
||||
p = dh_.GetGroupParameters().GetModulus();
|
||||
q = dh_.GetGroupParameters().GetSubgroupOrder();
|
||||
g = dh_.GetGroupParameters().GetGenerator();
|
||||
|
||||
// http://groups.google.com/group/sci.crypt/browse_thread/thread/7dc7eeb04a09f0ce
|
||||
Integer v = ModularExponentiation(g, q, p);
|
||||
|
||||
if(v != Integer::One()) {
|
||||
// Failed to verify order of the subgroup
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
spriv_key_.New(dh2_.StaticPrivateKeyLength());
|
||||
epriv_key_.New(dh2_.EphemeralPrivateKeyLength());
|
||||
SecByteBlock spub_key(dh2_.StaticPublicKeyLength());
|
||||
SecByteBlock epub_key(dh2_.EphemeralPublicKeyLength());
|
||||
|
||||
dh2_.GenerateStaticKeyPair(rnd, spriv_key_, spub_key);
|
||||
dh2_.GenerateEphemeralKeyPair(rnd, epriv_key_, epub_key);
|
||||
|
||||
// Prepare key agreement data
|
||||
const size_t spub_key_length = spub_key.size();
|
||||
const size_t epub_key_length = epub_key.size();
|
||||
const size_t data_length = spub_key_length + epub_key_length;
|
||||
|
||||
if (*length < data_length) {
|
||||
// Not enough data buffer length b-l-a-c-k
|
||||
return 0;
|
||||
}
|
||||
|
||||
*length = data_length;
|
||||
CryptoPP::byte* buf = (CryptoPP::byte*)buffer;
|
||||
memcpy(buf, spub_key.BytePtr(), spub_key_length);
|
||||
memcpy(buf + spub_key_length, epub_key.BytePtr(), epub_key_length);
|
||||
|
||||
return dh2_.AgreedValueLength();
|
||||
}
|
||||
|
||||
bool DH2KeyAgreement::Agree(size_t agreed_length, const void* buffer, size_t length) {
|
||||
if (agreed_length != dh2_.AgreedValueLength()) {
|
||||
// Shared secret size mismatch
|
||||
return false;
|
||||
}
|
||||
const size_t spub_key_length = dh2_.StaticPublicKeyLength();
|
||||
if (const size_t epub_key_length = dh2_.EphemeralPublicKeyLength(); length != (spub_key_length + epub_key_length)) {
|
||||
// Wrong data length
|
||||
return false;
|
||||
}
|
||||
shared_.New(dh2_.AgreedValueLength());
|
||||
if (const CryptoPP::byte* buf = (const CryptoPP::byte*)buffer; !dh2_.Agree(shared_, spriv_key_, epriv_key_, buf, buf + spub_key_length)) {
|
||||
// Failed to reach shared secret
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,61 +0,0 @@
|
||||
#ifndef __CIPHER_H__
|
||||
#define __CIPHER_H__
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4100 4127 4189 4231 4512 4706)
|
||||
#include <cryptlib.h>
|
||||
#pragma warning(pop)
|
||||
// Forward declaration
|
||||
class KeyAgreement;
|
||||
|
||||
// Communication channel encryption handler.
|
||||
class Cipher {
|
||||
public:
|
||||
explicit Cipher();
|
||||
~Cipher();
|
||||
|
||||
void CleanUp();
|
||||
|
||||
// Returns agreed value length in CryptoPP::bytes, or zero on failure.
|
||||
size_t Prepare(void* buffer, size_t* length);
|
||||
// Try to activate cipher algorithm with agreement data received from peer.
|
||||
bool Activate(bool polarity, size_t agreed_length,
|
||||
const void* buffer, size_t length);
|
||||
|
||||
// Encrypts the given block of data. (no padding required)
|
||||
void Encrypt(void* buffer, size_t length) {
|
||||
assert(activated_);
|
||||
if (!activated_) {
|
||||
return;
|
||||
}
|
||||
encoder_->ProcessData((CryptoPP::byte*)buffer, (const CryptoPP::byte*)buffer, length);
|
||||
}
|
||||
// Decrypts the given block of data. (no padding required)
|
||||
void Decrypt(void* buffer, size_t length) {
|
||||
assert(activated_);
|
||||
if (!activated_) {
|
||||
return;
|
||||
}
|
||||
decoder_->ProcessData((CryptoPP::byte*)buffer, (const CryptoPP::byte*)buffer, length);
|
||||
}
|
||||
|
||||
bool activated() const { return activated_; }
|
||||
|
||||
void set_activated(bool value) { activated_ = value; }
|
||||
|
||||
private:
|
||||
bool SetUp(bool polarity);
|
||||
|
||||
bool activated_;
|
||||
|
||||
CryptoPP::SymmetricCipher* encoder_;
|
||||
CryptoPP::SymmetricCipher* decoder_;
|
||||
|
||||
KeyAgreement* key_agreement_;
|
||||
};
|
||||
|
||||
#endif // _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
#endif // __CIPHER_H__
|
||||
@@ -1,101 +1,87 @@
|
||||
/*
|
||||
* Filename: tea.c
|
||||
* Description: TEA 암호화 모듈
|
||||
*
|
||||
* Author: 김한주 (aka. 비엽, Cronan), 송영진 (aka. myevan, 빗자루)
|
||||
*/
|
||||
#include "StdAfx.h"
|
||||
* Symmetric encryption module using libsodium (XChaCha20)
|
||||
* API-compatible replacement for legacy TEA encryption
|
||||
*
|
||||
* Key expansion: 16-byte input key is hashed to 32 bytes using BLAKE2b
|
||||
* Nonce: Derived deterministically from the key to ensure encrypt/decrypt consistency
|
||||
*/
|
||||
#include "tea.h"
|
||||
#include <memory.h>
|
||||
#include <sodium.h>
|
||||
#include <cstring>
|
||||
|
||||
/*
|
||||
* TEA Encryption Module Instruction
|
||||
* Edited by 김한주 aka. 비엽, Cronan
|
||||
*
|
||||
* void tea_code(const unsigned long sz, const unsigned long sy, const unsigned long *key, unsigned long *dest)
|
||||
* void tea_decode(const unsigned long sz, const unsigned long sy, const unsigned long *key, unsigned long *dest)
|
||||
* 8바이트를 암호/복호화 할때 사용된다. key 는 16 바이트여야 한다.
|
||||
* sz, sy 는 8바이트의 역순으로 대입한다.
|
||||
*
|
||||
* int tea_decrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size);
|
||||
* int tea_encrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size);
|
||||
* 한꺼번에 8 바이트 이상을 암호/복호화 할때 사용한다. 만약 size 가
|
||||
* 8의 배수가 아니면 8의 배수로 크기를 "늘려서" 암호화 한다.
|
||||
*
|
||||
* ex. tea_code(pdwSrc[1], pdwSrc[0], pdwKey, pdwDest);
|
||||
* tea_decrypt(pdwDest, pdwSrc, pdwKey, nSize);
|
||||
*/
|
||||
// Fixed context string for key derivation
|
||||
static const char* KEY_CONTEXT = "M2DevPackEncrypt";
|
||||
|
||||
#define TEA_ROUND 32 // 32 를 권장하며, 높을 수록 결과가 난해해 진다.
|
||||
#define DELTA 0x9E3779B9 // DELTA 값 바꾸지 말것.
|
||||
|
||||
void tea_code(const unsigned long sz, const unsigned long sy, const unsigned long *key, unsigned long *dest)
|
||||
// Derive a 32-byte key and 24-byte nonce from the 16-byte input key
|
||||
static void DeriveKeyAndNonce(const unsigned long* key, uint8_t* derived_key, uint8_t* nonce)
|
||||
{
|
||||
unsigned long y = sy, z = sz, sum = 0;
|
||||
unsigned long n = TEA_ROUND;
|
||||
|
||||
while (n-- > 0)
|
||||
{
|
||||
y += ((z << 4 ^ z >> 5) + z) ^ (sum + key[sum & 3]);
|
||||
sum += DELTA;
|
||||
z += ((y << 4 ^ y >> 5) + y) ^ (sum + key[sum >> 11 & 3]);
|
||||
}
|
||||
|
||||
*(dest++) = y;
|
||||
*dest = z;
|
||||
// Use BLAKE2b to derive a 32-byte key
|
||||
crypto_generichash(derived_key, crypto_stream_xchacha20_KEYBYTES,
|
||||
(const uint8_t*)key, TEA_KEY_LENGTH,
|
||||
(const uint8_t*)KEY_CONTEXT, strlen(KEY_CONTEXT));
|
||||
|
||||
// Derive nonce from key (using different context)
|
||||
uint8_t nonce_seed[crypto_stream_xchacha20_NONCEBYTES + 8];
|
||||
crypto_generichash(nonce_seed, sizeof(nonce_seed),
|
||||
(const uint8_t*)key, TEA_KEY_LENGTH,
|
||||
(const uint8_t*)"M2DevNonce", 10);
|
||||
memcpy(nonce, nonce_seed, crypto_stream_xchacha20_NONCEBYTES);
|
||||
}
|
||||
|
||||
void tea_decode(const unsigned long sz, const unsigned long sy, const unsigned long *key, unsigned long *dest)
|
||||
int tea_encrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size)
|
||||
{
|
||||
#pragma warning(disable:4307)
|
||||
unsigned long y = sy, z = sz, sum = DELTA * TEA_ROUND;
|
||||
#pragma warning(default:4307)
|
||||
int resize;
|
||||
|
||||
unsigned long n = TEA_ROUND;
|
||||
|
||||
while (n-- > 0)
|
||||
{
|
||||
z -= ((y << 4 ^ y >> 5) + y) ^ (sum + key[sum >> 11 & 3]);
|
||||
sum -= DELTA;
|
||||
y -= ((z << 4 ^ z >> 5) + z) ^ (sum + key[sum & 3]);
|
||||
}
|
||||
|
||||
*(dest++) = y;
|
||||
*dest = z;
|
||||
}
|
||||
|
||||
int tea_encrypt(unsigned long *dest, const unsigned long *src, const unsigned long * key, int size)
|
||||
{
|
||||
int i;
|
||||
int resize;
|
||||
|
||||
// Align to 8 bytes for compatibility with legacy format
|
||||
if (size % 8 != 0)
|
||||
{
|
||||
resize = size + 8 - (size % 8);
|
||||
memset((char *) src + size, 0, resize - size);
|
||||
// Zero-pad the source (caller must ensure buffer is large enough)
|
||||
memset((char*)src + size, 0, resize - size);
|
||||
}
|
||||
else
|
||||
{
|
||||
resize = size;
|
||||
|
||||
for (i = 0; i < resize >> 3; i++, dest += 2, src += 2)
|
||||
tea_code(*(src + 1), *src, key, dest);
|
||||
|
||||
return (resize);
|
||||
}
|
||||
|
||||
// Derive 32-byte key and nonce from 16-byte input
|
||||
uint8_t derived_key[crypto_stream_xchacha20_KEYBYTES];
|
||||
uint8_t nonce[crypto_stream_xchacha20_NONCEBYTES];
|
||||
DeriveKeyAndNonce(key, derived_key, nonce);
|
||||
|
||||
// XOR encrypt using XChaCha20 stream
|
||||
crypto_stream_xchacha20_xor((uint8_t*)dest, (const uint8_t*)src, resize, nonce, derived_key);
|
||||
|
||||
// Securely clear derived key
|
||||
sodium_memzero(derived_key, sizeof(derived_key));
|
||||
|
||||
return resize;
|
||||
}
|
||||
|
||||
int tea_decrypt(unsigned long *dest, const unsigned long *src, const unsigned long * key, int size)
|
||||
int tea_decrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size)
|
||||
{
|
||||
int i;
|
||||
int resize;
|
||||
|
||||
if (size % 8 != 0)
|
||||
resize = size + 8 - (size % 8);
|
||||
else
|
||||
resize = size;
|
||||
|
||||
for (i = 0; i < resize >> 3; i++, dest += 2, src += 2)
|
||||
tea_decode(*(src + 1), *src, key, dest);
|
||||
|
||||
return (resize);
|
||||
}
|
||||
int resize;
|
||||
|
||||
// Align to 8 bytes for compatibility with legacy format
|
||||
if (size % 8 != 0)
|
||||
{
|
||||
resize = size + 8 - (size % 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
resize = size;
|
||||
}
|
||||
|
||||
// Derive 32-byte key and nonce from 16-byte input
|
||||
uint8_t derived_key[crypto_stream_xchacha20_KEYBYTES];
|
||||
uint8_t nonce[crypto_stream_xchacha20_NONCEBYTES];
|
||||
DeriveKeyAndNonce(key, derived_key, nonce);
|
||||
|
||||
// XOR decrypt using XChaCha20 stream (same as encrypt for stream cipher)
|
||||
crypto_stream_xchacha20_xor((uint8_t*)dest, (const uint8_t*)src, resize, nonce, derived_key);
|
||||
|
||||
// Securely clear derived key
|
||||
sodium_memzero(derived_key, sizeof(derived_key));
|
||||
|
||||
return resize;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* TEA is a 64-bit symmetric block cipher with a 128-bit key, developed
|
||||
by David J. Wheeler and Roger M. Needham, and described in their
|
||||
paper at <URL:http://www.cl.cam.ac.uk/ftp/users/djw3/tea.ps>.
|
||||
// Symmetric encryption API using libsodium (XChaCha20)
|
||||
// Key is 16 bytes (128-bit), internally expanded to 32 bytes
|
||||
|
||||
This implementation is based on their code in
|
||||
<URL:http://www.cl.cam.ac.uk/ftp/users/djw3/xtea.ps> */
|
||||
#define TEA_KEY_LENGTH 16
|
||||
|
||||
#define TEA_KEY_LENGTH 16
|
||||
|
||||
int tea_encrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size);
|
||||
int tea_decrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size);
|
||||
int tea_encrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size);
|
||||
int tea_decrypt(unsigned long *dest, const unsigned long *src, const unsigned long *key, int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
add_library(EterGrnLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(EterGrnLib
|
||||
cryptopp-static
|
||||
target_link_libraries(EterGrnLib
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
add_library(EterImageLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(EterImageLib
|
||||
cryptopp-static
|
||||
target_link_libraries(EterImageLib
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
add_library(EterLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(EterLib
|
||||
cryptopp-static
|
||||
target_link_libraries(EterLib
|
||||
sodium
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
@@ -1,58 +1,28 @@
|
||||
#include "StdAfx.h"
|
||||
#include "NetStream.h"
|
||||
//#include "eterCrypt.h"
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
#include "EterBase/tea.h"
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define _PACKETDUMP
|
||||
#endif
|
||||
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
void CNetworkStream::SetSecurityMode(bool isSecurityMode, const char* c_szTeaKey)
|
||||
{
|
||||
m_isSecurityMode = isSecurityMode;
|
||||
memcpy(m_szEncryptKey, c_szTeaKey, TEA_KEY_LENGTH);
|
||||
memcpy(m_szDecryptKey, c_szTeaKey, TEA_KEY_LENGTH);
|
||||
}
|
||||
|
||||
void CNetworkStream::SetSecurityMode(bool isSecurityMode, const char* c_szTeaEncryptKey, const char* c_szTeaDecryptKey)
|
||||
{
|
||||
m_isSecurityMode = isSecurityMode;
|
||||
memcpy(m_szEncryptKey, c_szTeaEncryptKey, TEA_KEY_LENGTH);
|
||||
memcpy(m_szDecryptKey, c_szTeaDecryptKey, TEA_KEY_LENGTH);
|
||||
}
|
||||
#endif // _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
bool CNetworkStream::IsSecurityMode()
|
||||
{
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
return m_cipher.activated();
|
||||
#else
|
||||
return m_isSecurityMode;
|
||||
#endif
|
||||
return m_secureCipher.IsActivated();
|
||||
}
|
||||
|
||||
void CNetworkStream::SetRecvBufferSize(int recvBufSize)
|
||||
{
|
||||
if (m_recvBuf)
|
||||
{
|
||||
if (m_recvBufSize>recvBufSize)
|
||||
if (m_recvBufSize > recvBufSize)
|
||||
return;
|
||||
|
||||
delete [] m_recvBuf;
|
||||
|
||||
if (m_recvTEABuf)
|
||||
delete [] m_recvTEABuf;
|
||||
}
|
||||
m_recvBufSize = recvBufSize;
|
||||
m_recvBuf = new char[m_recvBufSize];
|
||||
m_recvTEABufSize = ((m_recvBufSize>>3)+1)<<3;
|
||||
m_recvTEABuf = new char[m_recvTEABufSize];
|
||||
m_recvBuf = new char[m_recvBufSize];
|
||||
}
|
||||
|
||||
void CNetworkStream::SetSendBufferSize(int sendBufSize)
|
||||
@@ -63,142 +33,50 @@ void CNetworkStream::SetSendBufferSize(int sendBufSize)
|
||||
return;
|
||||
|
||||
delete [] m_sendBuf;
|
||||
|
||||
if (m_sendTEABuf)
|
||||
delete [] m_sendTEABuf;
|
||||
}
|
||||
|
||||
m_sendBufSize = sendBufSize;
|
||||
m_sendBuf = new char[m_sendBufSize];
|
||||
m_sendTEABufSize = ((m_sendBufSize>>3)+1)<<3;
|
||||
m_sendTEABuf = new char[m_sendTEABufSize];
|
||||
}
|
||||
|
||||
bool CNetworkStream::__RecvInternalBuffer()
|
||||
{
|
||||
if (m_recvBufOutputPos>0)
|
||||
if (m_recvBufOutputPos > 0)
|
||||
{
|
||||
int recvBufDataSize = m_recvBufInputPos - m_recvBufOutputPos;
|
||||
if (recvBufDataSize>0)
|
||||
if (recvBufDataSize > 0)
|
||||
{
|
||||
memmove(m_recvBuf, m_recvBuf + m_recvBufOutputPos, recvBufDataSize);
|
||||
}
|
||||
|
||||
|
||||
m_recvBufInputPos -= m_recvBufOutputPos;
|
||||
m_recvBufOutputPos = 0;
|
||||
}
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
int restSize = m_recvBufSize - m_recvBufInputPos;
|
||||
if (restSize>0)
|
||||
{
|
||||
int recvSize = recv(m_sock, m_recvBuf + m_recvBufInputPos, m_recvBufSize - m_recvBufInputPos, 0);
|
||||
//Tracenf("RECV %d %d(%d, %d)", recvSize, restSize, m_recvTEABufSize - m_recvTEABufInputPos, m_recvBufSize - m_recvBufInputPos);
|
||||
if (restSize > 0)
|
||||
{
|
||||
int recvSize = recv(m_sock, m_recvBuf + m_recvBufInputPos, restSize, 0);
|
||||
|
||||
if (recvSize < 0)
|
||||
{
|
||||
int error = WSAGetLastError();
|
||||
|
||||
if (error != WSAEWOULDBLOCK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (recvSize == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsSecurityMode()) {
|
||||
m_cipher.Decrypt(m_recvBuf + m_recvBufInputPos, recvSize);
|
||||
}
|
||||
|
||||
m_recvBufInputPos += recvSize;
|
||||
}
|
||||
#else
|
||||
if (IsSecurityMode())
|
||||
{
|
||||
int restSize = std::min(m_recvTEABufSize - m_recvTEABufInputPos, m_recvBufSize - m_recvBufInputPos);
|
||||
|
||||
if (restSize > 0)
|
||||
else
|
||||
{
|
||||
int recvSize = recv(m_sock, m_recvTEABuf + m_recvTEABufInputPos, restSize, 0);
|
||||
//Tracenf("RECV %d %d(%d, %d)", recvSize, restSize, m_recvTEABufSize - m_recvTEABufInputPos, m_recvBufSize - m_recvBufInputPos);
|
||||
|
||||
if (recvSize < 0)
|
||||
if (m_secureCipher.IsActivated())
|
||||
{
|
||||
int error = WSAGetLastError();
|
||||
|
||||
if (error != WSAEWOULDBLOCK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_secureCipher.DecryptInPlace(m_recvBuf + m_recvBufInputPos, recvSize);
|
||||
}
|
||||
else if (recvSize == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_recvTEABufInputPos += recvSize;
|
||||
|
||||
int decodeSize = m_recvTEABufInputPos;
|
||||
|
||||
if (decodeSize >= 8)
|
||||
{
|
||||
decodeSize >>= 3;
|
||||
decodeSize <<= 3;
|
||||
|
||||
/*int decodeDstSize = tea_decrypt((DWORD *) (m_recvBuf + m_recvBufInputPos),
|
||||
(DWORD *) m_recvTEABuf,
|
||||
(const DWORD *) m_szDecryptKey,
|
||||
decodeSize);
|
||||
*/
|
||||
int decodeDstSize = tea_decrypt((DWORD *) (m_recvBuf + m_recvBufInputPos),
|
||||
(DWORD *) m_recvTEABuf,
|
||||
(const DWORD *) m_szDecryptKey,
|
||||
decodeSize);
|
||||
|
||||
m_recvBufInputPos += decodeDstSize;
|
||||
|
||||
if (m_recvTEABufInputPos>decodeSize)
|
||||
memmove(m_recvTEABuf, m_recvTEABuf+decodeSize, m_recvTEABufInputPos-decodeSize);
|
||||
|
||||
m_recvTEABufInputPos -= decodeSize;
|
||||
|
||||
|
||||
//Tracenf("!!!!!! decrypt decodeSrcSize %d -> decodeDstSize %d (recvOutputPos %d, recvInputPos %d, teaInputPos %d)",
|
||||
// decodeSize, decodeDstSize, m_recvBufOutputPos, m_recvBufInputPos, m_recvTEABufInputPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int restSize = m_recvBufSize - m_recvBufInputPos;
|
||||
if (restSize>0)
|
||||
{
|
||||
int recvSize = recv(m_sock, m_recvBuf + m_recvBufInputPos, m_recvBufSize - m_recvBufInputPos, 0);
|
||||
//Tracenf("RECV %d %d(%d, %d)", recvSize, restSize, m_recvTEABufSize - m_recvTEABufInputPos, m_recvBufSize - m_recvBufInputPos);
|
||||
|
||||
if (recvSize < 0)
|
||||
{
|
||||
int error = WSAGetLastError();
|
||||
|
||||
if (error != WSAEWOULDBLOCK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (recvSize == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_recvBufInputPos += recvSize;
|
||||
}
|
||||
}
|
||||
#endif // _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
//Tracef("recvSize: %d input pos %d output pos %d\n", recvSize, m_recvBufInputPos, m_recvBufOutputPos);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -206,82 +84,34 @@ bool CNetworkStream::__RecvInternalBuffer()
|
||||
|
||||
bool CNetworkStream::__SendInternalBuffer()
|
||||
{
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
int dataSize=__GetSendBufferSize();
|
||||
if (dataSize<=0)
|
||||
int dataSize = __GetSendBufferSize();
|
||||
if (dataSize <= 0)
|
||||
return true;
|
||||
|
||||
if (IsSecurityMode()) {
|
||||
m_cipher.Encrypt(m_sendBuf + m_sendBufOutputPos, dataSize);
|
||||
}
|
||||
|
||||
int sendSize = send(m_sock, m_sendBuf+m_sendBufOutputPos, dataSize, 0);
|
||||
int sendSize = send(m_sock, m_sendBuf + m_sendBufOutputPos, dataSize, 0);
|
||||
if (sendSize < 0)
|
||||
return false;
|
||||
|
||||
m_sendBufOutputPos+=sendSize;
|
||||
|
||||
m_sendBufOutputPos += sendSize;
|
||||
__PopSendBuffer();
|
||||
#else
|
||||
if (IsSecurityMode())
|
||||
{
|
||||
int encodeSize=__GetSendBufferSize();
|
||||
if (encodeSize<=0)
|
||||
return true;
|
||||
|
||||
m_sendTEABufInputPos += tea_encrypt((DWORD *) (m_sendTEABuf + m_sendTEABufInputPos),
|
||||
(DWORD *) (m_sendBuf + m_sendBufOutputPos),
|
||||
(const DWORD *) m_szEncryptKey,
|
||||
encodeSize);
|
||||
m_sendBufOutputPos += encodeSize;
|
||||
|
||||
if (m_sendTEABufInputPos>0)
|
||||
{
|
||||
int sendSize = send(m_sock, m_sendTEABuf, m_sendTEABufInputPos, 0);
|
||||
if (sendSize < 0)
|
||||
return false;
|
||||
|
||||
if (m_sendTEABufInputPos>sendSize)
|
||||
memmove(m_sendTEABuf, m_sendTEABuf+sendSize, m_sendTEABufInputPos-sendSize);
|
||||
|
||||
m_sendTEABufInputPos-=sendSize;
|
||||
}
|
||||
|
||||
__PopSendBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
int dataSize=__GetSendBufferSize();
|
||||
if (dataSize<=0)
|
||||
return true;
|
||||
|
||||
int sendSize = send(m_sock, m_sendBuf+m_sendBufOutputPos, dataSize, 0);
|
||||
if (sendSize < 0)
|
||||
return false;
|
||||
|
||||
m_sendBufOutputPos+=sendSize;
|
||||
|
||||
__PopSendBuffer();
|
||||
}
|
||||
#endif // _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNetworkStream::__PopSendBuffer()
|
||||
{
|
||||
if (m_sendBufOutputPos<=0)
|
||||
if (m_sendBufOutputPos <= 0)
|
||||
return;
|
||||
|
||||
|
||||
int sendBufDataSize = m_sendBufInputPos - m_sendBufOutputPos;
|
||||
|
||||
if (sendBufDataSize>0)
|
||||
if (sendBufDataSize > 0)
|
||||
{
|
||||
memmove(m_sendBuf, m_sendBuf+m_sendBufOutputPos, sendBufDataSize);
|
||||
memmove(m_sendBuf, m_sendBuf + m_sendBufOutputPos, sendBufDataSize);
|
||||
}
|
||||
|
||||
m_sendBufInputPos = sendBufDataSize;
|
||||
m_sendBufOutputPos = 0;
|
||||
m_sendBufOutputPos = 0;
|
||||
}
|
||||
|
||||
#pragma warning(push)
|
||||
@@ -304,7 +134,7 @@ void CNetworkStream::Process()
|
||||
|
||||
delay.tv_sec = 0;
|
||||
delay.tv_usec = 0;
|
||||
|
||||
|
||||
if (select(0, &fdsRecv, &fdsSend, NULL, &delay) == SOCKET_ERROR)
|
||||
return;
|
||||
|
||||
@@ -362,8 +192,6 @@ void CNetworkStream::Disconnect()
|
||||
if (m_sock == INVALID_SOCKET)
|
||||
return;
|
||||
|
||||
//OnDisconnect();
|
||||
|
||||
Clear();
|
||||
}
|
||||
|
||||
@@ -372,30 +200,18 @@ void CNetworkStream::Clear()
|
||||
if (m_sock == INVALID_SOCKET)
|
||||
return;
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
m_cipher.CleanUp();
|
||||
#endif
|
||||
m_secureCipher.CleanUp();
|
||||
|
||||
closesocket(m_sock);
|
||||
m_sock = INVALID_SOCKET;
|
||||
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
memset(m_szEncryptKey, 0, sizeof(m_szEncryptKey));
|
||||
memset(m_szDecryptKey, 0, sizeof(m_szDecryptKey));
|
||||
|
||||
m_isSecurityMode = false;
|
||||
#endif
|
||||
|
||||
m_isOnline = false;
|
||||
m_connectLimitTime = 0;
|
||||
|
||||
m_recvTEABufInputPos = 0;
|
||||
m_sendTEABufInputPos = 0;
|
||||
|
||||
m_recvBufInputPos = 0;
|
||||
m_recvBufInputPos = 0;
|
||||
m_recvBufOutputPos = 0;
|
||||
|
||||
m_sendBufInputPos = 0;
|
||||
|
||||
m_sendBufInputPos = 0;
|
||||
m_sendBufOutputPos = 0;
|
||||
|
||||
m_SequenceGenerator.seed(SEQUENCE_SEED);
|
||||
@@ -406,10 +222,10 @@ bool CNetworkStream::Connect(const CNetworkAddress& c_rkNetAddr, int limitSec)
|
||||
Clear();
|
||||
|
||||
m_addr = c_rkNetAddr;
|
||||
|
||||
|
||||
m_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (m_sock == INVALID_SOCKET)
|
||||
if (m_sock == INVALID_SOCKET)
|
||||
{
|
||||
Clear();
|
||||
OnConnectFailure();
|
||||
@@ -440,7 +256,7 @@ bool CNetworkStream::Connect(const CNetworkAddress& c_rkNetAddr, int limitSec)
|
||||
}
|
||||
|
||||
m_connectLimitTime = time(NULL) + limitSec;
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CNetworkStream::Connect(DWORD dwAddr, int port, int limitSec)
|
||||
@@ -469,7 +285,7 @@ bool CNetworkStream::Connect(const char* c_szAddr, int port, int /*limitSec*/)
|
||||
|
||||
void CNetworkStream::ClearRecvBuffer()
|
||||
{
|
||||
m_recvBufOutputPos = m_recvBufInputPos = 0;
|
||||
m_recvBufOutputPos = m_recvBufInputPos = 0;
|
||||
}
|
||||
|
||||
int CNetworkStream::GetRecvBufferSize()
|
||||
@@ -508,7 +324,6 @@ const char * GetSendHeaderName(BYTE header)
|
||||
sprintf(buf,"%d",i);
|
||||
stringList[i] = buf;
|
||||
}
|
||||
stringList[1] = "HEADER_CG_LOGIN";
|
||||
stringList[2] = "HEADER_CG_ATTACK";
|
||||
stringList[3] = "HEADER_CG_CHAT";
|
||||
stringList[4] = "HEADER_CG_PLAYER_CREATE";
|
||||
@@ -575,9 +390,7 @@ const char * GetSendHeaderName(BYTE header)
|
||||
stringList[112] = "HEADER_CG_GUILD_SYMBOL_UPLOAD";
|
||||
stringList[113] = "HEADER_CG_GUILD_SYMBOL_CRC";
|
||||
stringList[114] = "HEADER_CG_SCRIPT_SELECT_ITEM";
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
stringList[0xfb] = "HEADER_CG_KEY_AGREEMENT";
|
||||
#endif
|
||||
stringList[0xf9] = "HEADER_CG_KEY_RESPONSE";
|
||||
stringList[0xfc] = "HEADER_CG_TIME_SYNC";
|
||||
stringList[0xfd] = "HEADER_CG_CLIENT_VERSION";
|
||||
stringList[0xfe] = "HEADER_CG_PONG";
|
||||
@@ -642,9 +455,9 @@ const char * GetRecvHeaderName(BYTE header)
|
||||
stringList[46] = "HEADER_GC_QUEST_CONFIRM";
|
||||
|
||||
stringList[61] = "HEADER_GC_MOUNT";
|
||||
stringList[62] = "HEADER_GC_OWNERSHIP";
|
||||
stringList[62] = "HEADER_GC_OWNERSHIP";
|
||||
stringList[63] = "HEADER_GC_TARGET";
|
||||
stringList[65] = "HEADER_GC_WARP";
|
||||
stringList[65] = "HEADER_GC_WARP";
|
||||
stringList[69] = "HEADER_GC_ADD_FLY_TARGETING";
|
||||
|
||||
stringList[70] = "HEADER_GC_CREATE_FLY";
|
||||
@@ -682,7 +495,7 @@ const char * GetRecvHeaderName(BYTE header)
|
||||
stringList[106] = "HEADER_GC_TIME";
|
||||
stringList[107] = "HEADER_GC_CHANGE_NAME";
|
||||
stringList[110] = "HEADER_GC_DUNGEON";
|
||||
stringList[111] = "HEADER_GC_WALK_MODE";
|
||||
stringList[111] = "HEADER_GC_WALK_MODE";
|
||||
stringList[112] = "HEADER_GC_CHANGE_SKILL_GROUP";
|
||||
stringList[113] = "HEADER_GC_MAIN_CHARACTER_NEW";
|
||||
stringList[114] = "HEADER_GC_USE_POTION";
|
||||
@@ -709,10 +522,8 @@ const char * GetRecvHeaderName(BYTE header)
|
||||
stringList[135] = "HEADER_GC_DAMAGE_INFO";
|
||||
stringList[136] = "HEADER_GC_CHAR_ADDITIONAL_INFO";
|
||||
stringList[150] = "HEADER_GC_AUTH_SUCCESS";
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
stringList[0xfa] = "HEADER_GC_KEY_AGREEMENT_COMPLETED";
|
||||
stringList[0xfb] = "HEADER_GC_KEY_AGREEMENT";
|
||||
#endif
|
||||
stringList[0xf7] = "HEADER_GC_KEY_COMPLETE";
|
||||
stringList[0xf8] = "HEADER_GC_KEY_CHALLENGE";
|
||||
stringList[0xfc] = "HEADER_GC_HANDSHAKE_OK";
|
||||
stringList[0xfd] = "HEADER_GC_PHASE";
|
||||
stringList[0xfe] = "HEADER_GC_BINDUDP";
|
||||
@@ -751,9 +562,9 @@ static std::string dump_hex(const uint8_t* ptr, const std::size_t length)
|
||||
|
||||
bool CNetworkStream::Recv(int size, char * pDestBuf)
|
||||
{
|
||||
if (!Peek(size, pDestBuf))
|
||||
if (!Peek(size, pDestBuf))
|
||||
return false;
|
||||
|
||||
|
||||
#ifdef _PACKETDUMP
|
||||
if (*pDestBuf != 0)
|
||||
{
|
||||
@@ -771,7 +582,7 @@ bool CNetworkStream::Recv(int size, char * pDestBuf)
|
||||
|
||||
int CNetworkStream::__GetSendBufferSize()
|
||||
{
|
||||
return m_sendBufInputPos-m_sendBufOutputPos;
|
||||
return m_sendBufInputPos - m_sendBufOutputPos;
|
||||
}
|
||||
|
||||
|
||||
@@ -782,6 +593,12 @@ bool CNetworkStream::Send(int size, const char * pSrcBuf)
|
||||
return false;
|
||||
|
||||
memcpy(m_sendBuf + m_sendBufInputPos, pSrcBuf, size);
|
||||
|
||||
if (m_secureCipher.IsActivated())
|
||||
{
|
||||
m_secureCipher.EncryptInPlace(m_sendBuf + m_sendBufInputPos, size);
|
||||
}
|
||||
|
||||
m_sendBufInputPos += size;
|
||||
|
||||
#ifdef _PACKETDUMP
|
||||
@@ -796,23 +613,6 @@ bool CNetworkStream::Send(int size, const char * pSrcBuf)
|
||||
#endif
|
||||
|
||||
return true;
|
||||
/*
|
||||
if (size > 0)
|
||||
{
|
||||
if (IsSecurityMode())
|
||||
{
|
||||
m_sendBufInputPos += TEA_Encrypt((DWORD *) (m_sendBuf + m_sendBufInputPos),
|
||||
(DWORD *) (m_sendBuf + m_sendBufInputPos),
|
||||
(const DWORD *) gs_szTeaKey,
|
||||
size);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return __SendInternalBuffer();
|
||||
*/
|
||||
}
|
||||
|
||||
bool CNetworkStream::Peek(int len, void* pDestBuf)
|
||||
@@ -885,39 +685,20 @@ void CNetworkStream::OnConnectFailure()
|
||||
Tracen("Failed to connect.");
|
||||
}
|
||||
|
||||
//void CNetworkStream::OnCheckinSuccess()
|
||||
//{
|
||||
//}
|
||||
|
||||
//void CNetworkStream::OnCheckinFailure()
|
||||
//{
|
||||
//}
|
||||
|
||||
CNetworkStream::CNetworkStream()
|
||||
{
|
||||
m_sock = INVALID_SOCKET;
|
||||
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
m_isSecurityMode = false;
|
||||
#endif
|
||||
m_isOnline = false;
|
||||
m_connectLimitTime = 0;
|
||||
|
||||
m_recvTEABuf = NULL;
|
||||
m_recvTEABufSize = 0;
|
||||
m_recvTEABufInputPos = 0;
|
||||
|
||||
m_recvBuf = NULL;
|
||||
m_recvBufSize = 0;
|
||||
m_recvBuf = NULL;
|
||||
m_recvBufSize = 0;
|
||||
m_recvBufOutputPos = 0;
|
||||
m_recvBufInputPos = 0;
|
||||
m_recvBufInputPos = 0;
|
||||
|
||||
m_sendTEABuf = NULL;
|
||||
m_sendTEABuf = 0;
|
||||
m_sendTEABufInputPos = 0;
|
||||
|
||||
m_sendBuf = NULL;
|
||||
m_sendBufSize = 0;
|
||||
m_sendBuf = NULL;
|
||||
m_sendBufSize = 0;
|
||||
m_sendBufOutputPos = 0;
|
||||
m_sendBufInputPos = 0;
|
||||
|
||||
@@ -929,57 +710,15 @@ CNetworkStream::~CNetworkStream()
|
||||
{
|
||||
Clear();
|
||||
|
||||
if (m_sendTEABuf)
|
||||
{
|
||||
delete [] m_sendTEABuf;
|
||||
m_sendTEABuf=NULL;
|
||||
}
|
||||
|
||||
if (m_recvTEABuf)
|
||||
{
|
||||
delete [] m_recvTEABuf;
|
||||
m_recvTEABuf=NULL;
|
||||
}
|
||||
|
||||
if (m_recvBuf)
|
||||
{
|
||||
delete [] m_recvBuf;
|
||||
m_recvBuf=NULL;
|
||||
m_recvBuf = NULL;
|
||||
}
|
||||
|
||||
if (m_sendBuf)
|
||||
{
|
||||
delete [] m_sendBuf;
|
||||
m_sendBuf=NULL;
|
||||
m_sendBuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
size_t CNetworkStream::Prepare(void* buffer, size_t* length)
|
||||
{
|
||||
return m_cipher.Prepare(buffer, length);
|
||||
}
|
||||
|
||||
bool CNetworkStream::Activate(size_t agreed_length, const void* buffer, size_t length)
|
||||
{
|
||||
return m_cipher.Activate(true, agreed_length, buffer, length);
|
||||
}
|
||||
|
||||
void CNetworkStream::ActivateCipher()
|
||||
{
|
||||
return m_cipher.set_activated(true);
|
||||
}
|
||||
|
||||
// If cipher is active and there's unread data in buffer, decrypt it in-place
|
||||
void CNetworkStream::DecryptAlreadyReceivedData()
|
||||
{
|
||||
if (!IsSecurityMode())
|
||||
return;
|
||||
|
||||
const int unreadSize = m_recvBufInputPos - m_recvBufOutputPos;
|
||||
if (unreadSize <= 0)
|
||||
return;
|
||||
|
||||
m_cipher.Decrypt(m_recvBuf + m_recvBufOutputPos, unreadSize);
|
||||
}
|
||||
#endif // _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
#include "EterBase/cipher.h"
|
||||
#endif
|
||||
#include "EterBase/tea.h"
|
||||
#include "EterBase/SecureCipher.h"
|
||||
#include "NetAddress.h"
|
||||
|
||||
#include <pcg_random.hpp>
|
||||
@@ -14,15 +11,11 @@ class CNetworkStream
|
||||
{
|
||||
public:
|
||||
CNetworkStream();
|
||||
virtual ~CNetworkStream();
|
||||
virtual ~CNetworkStream();
|
||||
|
||||
void SetRecvBufferSize(int recvBufSize);
|
||||
void SetSendBufferSize(int sendBufSize);
|
||||
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
void SetSecurityMode(bool isSecurityMode, const char* c_szTeaKey);
|
||||
void SetSecurityMode(bool isSecurityMode, const char* c_szTeaEncryptKey, const char* c_szTeaDecryptKey);
|
||||
#endif
|
||||
bool IsSecurityMode();
|
||||
|
||||
int GetRecvBufferSize();
|
||||
@@ -55,11 +48,11 @@ class CNetworkStream
|
||||
bool SendSequence();
|
||||
uint8_t GetNextSequence();
|
||||
|
||||
protected:
|
||||
virtual void OnConnectSuccess();
|
||||
protected:
|
||||
virtual void OnConnectSuccess();
|
||||
virtual void OnConnectFailure();
|
||||
virtual void OnRemoteDisconnect();
|
||||
virtual void OnDisconnect();
|
||||
virtual void OnDisconnect();
|
||||
virtual bool OnProcess();
|
||||
|
||||
bool __SendInternalBuffer();
|
||||
@@ -69,20 +62,14 @@ class CNetworkStream
|
||||
|
||||
int __GetSendBufferSize();
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
size_t Prepare(void* buffer, size_t* length);
|
||||
bool Activate(size_t agreed_length, const void* buffer, size_t length);
|
||||
void ActivateCipher();
|
||||
void DecryptAlreadyReceivedData();
|
||||
#endif
|
||||
// Secure cipher methods (libsodium)
|
||||
SecureCipher& GetSecureCipher() { return m_secureCipher; }
|
||||
bool IsSecureCipherActivated() const { return m_secureCipher.IsActivated(); }
|
||||
void ActivateSecureCipher() { m_secureCipher.SetActivated(true); }
|
||||
|
||||
private:
|
||||
time_t m_connectLimitTime;
|
||||
|
||||
char* m_recvTEABuf;
|
||||
int m_recvTEABufInputPos;
|
||||
int m_recvTEABufSize;
|
||||
|
||||
char* m_recvBuf;
|
||||
int m_recvBufSize;
|
||||
int m_recvBufInputPos;
|
||||
@@ -93,20 +80,10 @@ class CNetworkStream
|
||||
int m_sendBufInputPos;
|
||||
int m_sendBufOutputPos;
|
||||
|
||||
char* m_sendTEABuf;
|
||||
int m_sendTEABufSize;
|
||||
int m_sendTEABufInputPos;
|
||||
|
||||
bool m_isOnline;
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
Cipher m_cipher;
|
||||
#else
|
||||
// Obsolete encryption stuff here
|
||||
bool m_isSecurityMode;
|
||||
char m_szEncryptKey[TEA_KEY_LENGTH]; // Client 에서 보낼 패킷을 Encrypt 할때 사용하는 Key
|
||||
char m_szDecryptKey[TEA_KEY_LENGTH]; // Server 에서 전송된 패킷을 Decrypt 할때 사용하는 Key
|
||||
#endif
|
||||
// Secure cipher (libsodium/XChaCha20-Poly1305)
|
||||
SecureCipher m_secureCipher;
|
||||
|
||||
SOCKET m_sock;
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
add_library(EterLocale STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(EterLocale
|
||||
cryptopp-static
|
||||
target_link_libraries(EterLocale
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
add_library(EterPythonLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(EterPythonLib
|
||||
cryptopp-static
|
||||
target_link_libraries(EterPythonLib
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
add_library(GameLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(GameLib
|
||||
target_link_libraries(GameLib
|
||||
lzo2
|
||||
cryptopp-static
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
add_library(PRTerrainLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(PRTerrainLib
|
||||
cryptopp-static
|
||||
target_link_libraries(PRTerrainLib
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
add_library(PackLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(PackLib
|
||||
target_link_libraries(PackLib
|
||||
libzstd_static
|
||||
cryptopp-static
|
||||
sodium
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
@@ -13,11 +13,16 @@ static ZSTD_DCtx* GetThreadLocalZSTDContext()
|
||||
return g_zstdDCtx;
|
||||
}
|
||||
|
||||
void CPack::DecryptData(uint8_t* data, size_t len, const uint8_t* nonce)
|
||||
{
|
||||
crypto_stream_xchacha20_xor(data, data, len, nonce, PACK_KEY.data());
|
||||
}
|
||||
|
||||
bool CPack::Load(const std::string& path)
|
||||
{
|
||||
std::error_code ec;
|
||||
m_file.map(path, ec);
|
||||
|
||||
|
||||
if (ec) {
|
||||
return false;
|
||||
}
|
||||
@@ -28,7 +33,6 @@ bool CPack::Load(const std::string& path)
|
||||
}
|
||||
|
||||
memcpy(&m_header, m_file.data(), sizeof(TPackFileHeader));
|
||||
m_decryption.SetKeyWithIV(PACK_KEY.data(), PACK_KEY.size(), m_header.iv, CryptoPP::Camellia::BLOCKSIZE);
|
||||
|
||||
if (file_size < sizeof(TPackFileHeader) + m_header.entry_num * sizeof(TPackFileEntry)) {
|
||||
return false;
|
||||
@@ -39,7 +43,7 @@ bool CPack::Load(const std::string& path)
|
||||
for (size_t i = 0; i < m_header.entry_num; i++) {
|
||||
TPackFileEntry& entry = m_index[i];
|
||||
memcpy(&entry, m_file.data() + sizeof(TPackFileHeader) + i * sizeof(TPackFileEntry), sizeof(TPackFileEntry));
|
||||
m_decryption.ProcessData((CryptoPP::byte*)&entry, (CryptoPP::byte*)&entry, sizeof(TPackFileEntry));
|
||||
DecryptData((uint8_t*)&entry, sizeof(TPackFileEntry), m_header.nonce);
|
||||
|
||||
if (file_size < m_header.data_begin + entry.offset + entry.compressed_size) {
|
||||
return false;
|
||||
@@ -79,8 +83,7 @@ bool CPack::GetFileWithPool(const TPackFileEntry& entry, TPackFile& result, CBuf
|
||||
|
||||
memcpy(compressed_data.data(), m_file.data() + offset, entry.compressed_size);
|
||||
|
||||
m_decryption.Resynchronize(entry.iv, sizeof(entry.iv));
|
||||
m_decryption.ProcessData(compressed_data.data(), compressed_data.data(), entry.compressed_size);
|
||||
DecryptData(compressed_data.data(), entry.compressed_size, entry.nonce);
|
||||
|
||||
size_t decompressed_size = ZSTD_decompressDCtx(dctx, result.data(), result.size(), compressed_data.data(), compressed_data.size());
|
||||
|
||||
@@ -97,4 +100,4 @@ bool CPack::GetFileWithPool(const TPackFileEntry& entry, TPackFile& result, CBuf
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,14 @@ public:
|
||||
|
||||
bool Load(const std::string& path);
|
||||
const std::vector<TPackFileEntry>& GetIndex() const { return m_index; }
|
||||
|
||||
|
||||
bool GetFile(const TPackFileEntry& entry, TPackFile& result);
|
||||
bool GetFileWithPool(const TPackFileEntry& entry, TPackFile& result, CBufferPool* pPool);
|
||||
|
||||
private:
|
||||
void DecryptData(uint8_t* data, size_t len, const uint8_t* nonce);
|
||||
|
||||
TPackFileHeader m_header;
|
||||
std::vector<TPackFileEntry> m_index;
|
||||
mio::mmap_source m_file;
|
||||
|
||||
CryptoPP::CTR_Mode<CryptoPP::Camellia>::Decryption m_decryption;
|
||||
};
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <gcm.h>
|
||||
#include <modes.h>
|
||||
#include <osrng.h>
|
||||
#include <secblock.h>
|
||||
#include <camellia.h>
|
||||
#include <sodium.h>
|
||||
|
||||
constexpr std::array<uint8_t, 32> PACK_KEY = {
|
||||
constexpr size_t PACK_KEY_SIZE = crypto_stream_xchacha20_KEYBYTES; // 32 bytes
|
||||
constexpr size_t PACK_NONCE_SIZE = crypto_stream_xchacha20_NONCEBYTES; // 24 bytes
|
||||
|
||||
constexpr std::array<uint8_t, PACK_KEY_SIZE> PACK_KEY = {
|
||||
0x00,0x11,0x22,0x33, 0x44,0x55,0x66,0x77,
|
||||
0x88,0x99,0xAA,0xBB, 0xCC,0xDD,0xEE,0xFF,
|
||||
0x01,0x23,0x45,0x67, 0x89,0xAB,0xCD,0xEF,
|
||||
@@ -24,7 +23,7 @@ struct TPackFileHeader
|
||||
{
|
||||
uint64_t entry_num;
|
||||
uint64_t data_begin;
|
||||
uint8_t iv[CryptoPP::Camellia::BLOCKSIZE];
|
||||
uint8_t nonce[PACK_NONCE_SIZE];
|
||||
};
|
||||
struct TPackFileEntry
|
||||
{
|
||||
@@ -33,11 +32,11 @@ struct TPackFileEntry
|
||||
uint64_t file_size;
|
||||
uint64_t compressed_size;
|
||||
uint8_t encryption;
|
||||
uint8_t iv[CryptoPP::Camellia::BLOCKSIZE];
|
||||
uint8_t nonce[PACK_NONCE_SIZE];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
class CPack;
|
||||
using TPackFile = std::vector<uint8_t>;
|
||||
using TPackFileMapEntry = std::pair<std::shared_ptr<CPack>, TPackFileEntry>;
|
||||
using TPackFileMap = std::unordered_map<std::string, TPackFileMapEntry>;
|
||||
using TPackFileMap = std::unordered_map<std::string, TPackFileMapEntry>;
|
||||
|
||||
@@ -5,7 +5,7 @@ set_target_properties(PackMaker PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
target_link_libraries(PackMaker
|
||||
target_link_libraries(PackMaker
|
||||
libzstd_static
|
||||
cryptopp-static
|
||||
sodium
|
||||
)
|
||||
|
||||
@@ -5,13 +5,24 @@
|
||||
|
||||
#include <zstd.h>
|
||||
#include <argparse.hpp>
|
||||
#include <sodium.h>
|
||||
|
||||
#include "PackLib/config.h"
|
||||
|
||||
static void EncryptData(uint8_t* data, size_t len, const uint8_t* nonce)
|
||||
{
|
||||
crypto_stream_xchacha20_xor(data, data, len, nonce, PACK_KEY.data());
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
std::setlocale(LC_ALL, "en_US.UTF-8");
|
||||
|
||||
if (sodium_init() < 0) {
|
||||
std::cerr << "Failed to initialize libsodium" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
argparse::ArgumentParser program("PackMaker");
|
||||
|
||||
program.add_argument("--input")
|
||||
@@ -54,7 +65,7 @@ int main(int argc, char* argv[])
|
||||
continue;
|
||||
|
||||
std::filesystem::path relative_path = std::filesystem::relative(entry.path(), input);
|
||||
|
||||
|
||||
TPackFileEntry& file_entry = entries[relative_path];
|
||||
memset(&file_entry, 0, sizeof(file_entry));
|
||||
file_entry.file_size = entry.file_size();
|
||||
@@ -77,15 +88,11 @@ int main(int argc, char* argv[])
|
||||
header.entry_num = entries.size();
|
||||
header.data_begin = sizeof(TPackFileHeader) + sizeof(TPackFileEntry) * entries.size();
|
||||
|
||||
CryptoPP::AutoSeededRandomPool rnd;
|
||||
rnd.GenerateBlock(header.iv, sizeof(header.iv));
|
||||
randombytes_buf(header.nonce, sizeof(header.nonce));
|
||||
|
||||
ofs.write((const char*) &header, sizeof(header));
|
||||
ofs.seekp(header.data_begin, std::ios::beg);
|
||||
|
||||
CryptoPP::CTR_Mode<CryptoPP::Camellia>::Encryption encryption;
|
||||
encryption.SetKeyWithIV(PACK_KEY.data(), PACK_KEY.size(), header.iv, CryptoPP::Camellia::BLOCKSIZE);
|
||||
|
||||
uint64_t offset = 0;
|
||||
for (auto& [path, entry] : entries) {
|
||||
std::ifstream ifs(input / path, std::ios::binary);
|
||||
@@ -118,9 +125,8 @@ int main(int argc, char* argv[])
|
||||
if (path.has_extension() && path.extension() == ".py") {
|
||||
entry.encryption = 1;
|
||||
|
||||
rnd.GenerateBlock(entry.iv, sizeof(entry.iv));
|
||||
encryption.Resynchronize(entry.iv, sizeof(entry.iv));
|
||||
encryption.ProcessData((uint8_t*)compressed_buffer.data(), (uint8_t*)compressed_buffer.data(), entry.compressed_size);
|
||||
randombytes_buf(entry.nonce, sizeof(entry.nonce));
|
||||
EncryptData((uint8_t*)compressed_buffer.data(), entry.compressed_size, entry.nonce);
|
||||
}
|
||||
|
||||
ofs.write(compressed_buffer.data(), entry.compressed_size);
|
||||
@@ -128,11 +134,10 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
ofs.seekp(sizeof(TPackFileHeader), std::ios::beg);
|
||||
encryption.Resynchronize(header.iv, sizeof(header.iv));
|
||||
|
||||
|
||||
for (auto& [path, entry] : entries) {
|
||||
TPackFileEntry tmp = entry;
|
||||
encryption.ProcessData((uint8_t*)&tmp, (uint8_t*)&tmp, sizeof(TPackFileEntry));
|
||||
EncryptData((uint8_t*)&tmp, sizeof(TPackFileEntry), header.nonce);
|
||||
ofs.write((const char*)&tmp, sizeof(TPackFileEntry));
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
add_library(ScriptLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(ScriptLib
|
||||
cryptopp-static
|
||||
target_link_libraries(ScriptLib
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
@@ -36,25 +36,40 @@ void Traceback()
|
||||
str.append(g_stTraceBuffer[i]);
|
||||
str.append("\n");
|
||||
}
|
||||
|
||||
|
||||
PyObject * exc;
|
||||
PyObject * v;
|
||||
PyObject * tb;
|
||||
const char * errStr;
|
||||
|
||||
PyErr_Fetch(&exc, &v, &tb);
|
||||
PyErr_NormalizeException(&exc, &v, &tb);
|
||||
|
||||
if (PyString_Check(v))
|
||||
if (exc)
|
||||
{
|
||||
errStr = PyString_AS_STRING(v);
|
||||
str.append("Error: ");
|
||||
str.append(errStr);
|
||||
|
||||
Tracef("%s\n", errStr);
|
||||
PyObject* excName = PyObject_GetAttrString(exc, "__name__");
|
||||
if (excName && PyString_Check(excName))
|
||||
{
|
||||
str.append(PyString_AS_STRING(excName));
|
||||
str.append(": ");
|
||||
}
|
||||
Py_XDECREF(excName);
|
||||
}
|
||||
Py_DECREF(exc);
|
||||
Py_DECREF(v);
|
||||
Py_DECREF(tb);
|
||||
|
||||
if (v)
|
||||
{
|
||||
PyObject* vStr = PyObject_Str(v);
|
||||
if (vStr && PyString_Check(vStr))
|
||||
{
|
||||
const char* errStr = PyString_AS_STRING(vStr);
|
||||
str.append(errStr);
|
||||
Tracef("%s\n", errStr);
|
||||
}
|
||||
Py_XDECREF(vStr);
|
||||
}
|
||||
|
||||
Py_XDECREF(exc);
|
||||
Py_XDECREF(v);
|
||||
Py_XDECREF(tb);
|
||||
LogBoxf("Traceback:\n\n%s\n", str.c_str());
|
||||
}
|
||||
|
||||
@@ -237,11 +252,41 @@ bool CPythonLauncher::RunFile(const char* c_szFileName)
|
||||
{
|
||||
TPackFile file;
|
||||
CPackManager::Instance().GetFile(c_szFileName, file);
|
||||
|
||||
|
||||
if (file.empty())
|
||||
return false;
|
||||
|
||||
return RunMemoryTextFile(c_szFileName, file.size(), file.data());
|
||||
|
||||
// Convert \r\n to \n and null-terminate
|
||||
std::string source;
|
||||
source.reserve(file.size());
|
||||
for (size_t i = 0; i < file.size(); ++i)
|
||||
{
|
||||
if (file[i] != '\r')
|
||||
source += (char)file[i];
|
||||
}
|
||||
|
||||
// Compile directly with the filename for proper error reporting
|
||||
PyObject* code = Py_CompileString(source.c_str(), c_szFileName, Py_file_input);
|
||||
if (!code)
|
||||
{
|
||||
Traceback();
|
||||
return false;
|
||||
}
|
||||
|
||||
PyObject* result = PyEval_EvalCode((PyCodeObject*)code, m_poDic, m_poDic);
|
||||
Py_DECREF(code);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
Traceback();
|
||||
return false;
|
||||
}
|
||||
|
||||
Py_DECREF(result);
|
||||
if (Py_FlushLine())
|
||||
PyErr_Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPythonLauncher::RunLine(const char* c_szSrc)
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
add_library(SpeedTreeLib STATIC ${FILE_SOURCES})
|
||||
|
||||
target_link_libraries(SpeedTreeLib
|
||||
cryptopp-static
|
||||
target_link_libraries(SpeedTreeLib
|
||||
mio
|
||||
)
|
||||
|
||||
|
||||
@@ -2,13 +2,6 @@
|
||||
#include "AccountConnector.h"
|
||||
#include "Packet.h"
|
||||
#include "PythonNetworkStream.h"
|
||||
#include "EterBase/tea.h"
|
||||
#include "PackLib/PackManager.h"
|
||||
|
||||
// CHINA_CRYPT_KEY
|
||||
extern DWORD g_adwEncryptKey[4];
|
||||
extern DWORD g_adwDecryptKey[4];
|
||||
// END_OF_CHINA_CRYPT_KEY
|
||||
|
||||
void CAccountConnector::SetHandler(PyObject* poHandler)
|
||||
{
|
||||
@@ -29,14 +22,9 @@ void CAccountConnector::ClearLoginInfo( void )
|
||||
|
||||
bool CAccountConnector::Connect(const char * c_szAddr, int iPort, const char * c_szAccountAddr, int iAccountPort)
|
||||
{
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
__BuildClientKey();
|
||||
#endif
|
||||
|
||||
m_strAddr = c_szAddr;
|
||||
m_iPort = iPort;
|
||||
__OfflineState_Set();
|
||||
__BuildClientKey_20050304Myevan();
|
||||
|
||||
return CNetworkStream::Connect(c_szAccountAddr, iAccountPort);
|
||||
}
|
||||
@@ -84,21 +72,12 @@ bool CAccountConnector::__HandshakeState_Process()
|
||||
if (!__AnalyzePacket(HEADER_GC_PING, sizeof(TPacketGCPing), &CAccountConnector::__AuthState_RecvPing))
|
||||
return false;
|
||||
|
||||
// TODO : 차후 서버와 동일하게 가변길이 data serialize & deserialize 작업해야 한다.
|
||||
if (!__AnalyzeVarSizePacket(HEADER_GC_HYBRIDCRYPT_KEYS, &CAccountConnector::__AuthState_RecvHybridCryptKeys))
|
||||
if (!__AnalyzePacket(HEADER_GC_KEY_CHALLENGE, sizeof(TPacketGCKeyChallenge), &CAccountConnector::__AuthState_RecvKeyChallenge))
|
||||
return false;
|
||||
|
||||
if (!__AnalyzeVarSizePacket(HEADER_GC_HYBRIDCRYPT_SDB, &CAccountConnector::__AuthState_RecvHybridCryptSDB))
|
||||
if (!__AnalyzePacket(HEADER_GC_KEY_COMPLETE, sizeof(TPacketGCKeyComplete), &CAccountConnector::__AuthState_RecvKeyComplete))
|
||||
return false;
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
if (!__AnalyzePacket(HEADER_GC_KEY_AGREEMENT, sizeof(TPacketKeyAgreement), &CAccountConnector::__AuthState_RecvKeyAgreement))
|
||||
return false;
|
||||
|
||||
if (!__AnalyzePacket(HEADER_GC_KEY_AGREEMENT_COMPLETED, sizeof(TPacketKeyAgreementCompleted), &CAccountConnector::__AuthState_RecvKeyAgreementCompleted))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -122,22 +101,10 @@ bool CAccountConnector::__AuthState_Process()
|
||||
if (!__AnalyzePacket(HEADER_GC_HANDSHAKE, sizeof(TPacketGCHandshake), &CAccountConnector::__AuthState_RecvHandshake))
|
||||
return false;
|
||||
|
||||
if (!__AnalyzePacket(HEADER_GC_PANAMA_PACK, sizeof(TPacketGCPanamaPack), &CAccountConnector::__AuthState_RecvPanamaPack))
|
||||
if (!__AnalyzePacket(HEADER_GC_KEY_CHALLENGE, sizeof(TPacketGCKeyChallenge), &CAccountConnector::__AuthState_RecvKeyChallenge))
|
||||
return false;
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
if (!__AnalyzePacket(HEADER_GC_KEY_AGREEMENT, sizeof(TPacketKeyAgreement), &CAccountConnector::__AuthState_RecvKeyAgreement))
|
||||
return false;
|
||||
|
||||
if (!__AnalyzePacket(HEADER_GC_KEY_AGREEMENT_COMPLETED, sizeof(TPacketKeyAgreementCompleted), &CAccountConnector::__AuthState_RecvKeyAgreementCompleted))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
// TODO : 차후 서버와 동일하게 가변길이 data serialize & deserialize 작업해야 한다.
|
||||
if (!__AnalyzeVarSizePacket(HEADER_GC_HYBRIDCRYPT_KEYS, &CAccountConnector::__AuthState_RecvHybridCryptKeys))
|
||||
return false;
|
||||
|
||||
if (!__AnalyzeVarSizePacket(HEADER_GC_HYBRIDCRYPT_SDB, &CAccountConnector::__AuthState_RecvHybridCryptSDB))
|
||||
if (!__AnalyzePacket(HEADER_GC_KEY_COMPLETE, sizeof(TPacketGCKeyComplete), &CAccountConnector::__AuthState_RecvKeyComplete))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -162,11 +129,6 @@ bool CAccountConnector::__AuthState_RecvPhase()
|
||||
}
|
||||
else if (kPacketPhase.phase == PHASE_AUTH)
|
||||
{
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
const char* key = GetSecurityKey();
|
||||
SetSecurityMode(true, key);
|
||||
#endif
|
||||
|
||||
TPacketCGLogin3 LoginPacket;
|
||||
LoginPacket.header = HEADER_CG_LOGIN3;
|
||||
|
||||
@@ -175,16 +137,12 @@ bool CAccountConnector::__AuthState_RecvPhase()
|
||||
LoginPacket.name[ID_MAX_NUM] = '\0';
|
||||
LoginPacket.pwd[PASS_MAX_NUM] = '\0';
|
||||
|
||||
// 비밀번호를 메모리에 계속 갖고 있는 문제가 있어서, 사용 즉시 날리는 것으로 변경
|
||||
ClearLoginInfo();
|
||||
CPythonNetworkStream& rkNetStream=CPythonNetworkStream::Instance();
|
||||
rkNetStream.ClearLoginInfo();
|
||||
|
||||
m_strPassword = "";
|
||||
|
||||
for (DWORD i = 0; i < 4; ++i)
|
||||
LoginPacket.adwClientKey[i] = g_adwEncryptKey[i];
|
||||
|
||||
if (!Send(sizeof(LoginPacket), &LoginPacket))
|
||||
{
|
||||
Tracen(" CAccountConnector::__AuthState_RecvPhase - SendLogin3 Error");
|
||||
@@ -208,71 +166,93 @@ bool CAccountConnector::__AuthState_RecvHandshake()
|
||||
if (!Recv(sizeof(kPacketHandshake), &kPacketHandshake))
|
||||
return false;
|
||||
|
||||
// HandShake
|
||||
Tracenf("HANDSHAKE RECV %u %d", kPacketHandshake.dwTime, kPacketHandshake.lDelta);
|
||||
|
||||
ELTimer_SetServerMSec(kPacketHandshake.dwTime+ kPacketHandshake.lDelta);
|
||||
|
||||
kPacketHandshake.dwTime = kPacketHandshake.dwTime + kPacketHandshake.lDelta + kPacketHandshake.lDelta;
|
||||
kPacketHandshake.lDelta = 0;
|
||||
|
||||
Tracenf("HANDSHAKE SEND %u", kPacketHandshake.dwTime);
|
||||
|
||||
if (!Send(sizeof(kPacketHandshake), &kPacketHandshake))
|
||||
{
|
||||
Tracenf("HANDSHAKE RECV %u %d", kPacketHandshake.dwTime, kPacketHandshake.lDelta);
|
||||
|
||||
ELTimer_SetServerMSec(kPacketHandshake.dwTime+ kPacketHandshake.lDelta);
|
||||
|
||||
//DWORD dwBaseServerTime = kPacketHandshake.dwTime+ kPacketHandshake.lDelta;
|
||||
//DWORD dwBaseClientTime = ELTimer_GetMSec();
|
||||
|
||||
kPacketHandshake.dwTime = kPacketHandshake.dwTime + kPacketHandshake.lDelta + kPacketHandshake.lDelta;
|
||||
kPacketHandshake.lDelta = 0;
|
||||
|
||||
Tracenf("HANDSHAKE SEND %u", kPacketHandshake.dwTime);
|
||||
|
||||
if (!Send(sizeof(kPacketHandshake), &kPacketHandshake))
|
||||
{
|
||||
Tracen(" CAccountConnector::__AuthState_RecvHandshake - SendHandshake Error");
|
||||
return false;
|
||||
}
|
||||
Tracen(" CAccountConnector::__AuthState_RecvHandshake - SendHandshake Error");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAccountConnector::__AuthState_RecvPanamaPack()
|
||||
bool CAccountConnector::__AuthState_RecvKeyChallenge()
|
||||
{
|
||||
TPacketGCPanamaPack kPacket;
|
||||
|
||||
if (!Recv(sizeof(TPacketGCPanamaPack), &kPacket))
|
||||
TPacketGCKeyChallenge packet;
|
||||
if (!Recv(sizeof(packet), &packet))
|
||||
return false;
|
||||
|
||||
Tracen("KEY_CHALLENGE RECV - Starting secure key exchange");
|
||||
|
||||
SecureCipher& cipher = GetSecureCipher();
|
||||
if (!cipher.Initialize())
|
||||
{
|
||||
Tracen("SecureCipher initialization failed");
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cipher.ComputeClientKeys(packet.server_pk))
|
||||
{
|
||||
Tracen("Failed to compute client session keys");
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
TPacketCGKeyResponse response;
|
||||
response.bHeader = HEADER_CG_KEY_RESPONSE;
|
||||
cipher.GetPublicKey(response.client_pk);
|
||||
cipher.ComputeResponse(packet.challenge, response.challenge_response);
|
||||
|
||||
if (!Send(sizeof(response), &response))
|
||||
{
|
||||
Tracen("Failed to send key response");
|
||||
return false;
|
||||
}
|
||||
|
||||
Tracen("KEY_RESPONSE SEND - Awaiting key completion");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAccountConnector::__AuthState_RecvHybridCryptKeys(int iTotalSize)
|
||||
bool CAccountConnector::__AuthState_RecvKeyComplete()
|
||||
{
|
||||
int iFixedHeaderSize = TPacketGCHybridCryptKeys::GetFixedHeaderSize();
|
||||
|
||||
TPacketGCHybridCryptKeys kPacket(iTotalSize-iFixedHeaderSize);
|
||||
|
||||
if (!Recv(iFixedHeaderSize, &kPacket))
|
||||
TPacketGCKeyComplete packet;
|
||||
if (!Recv(sizeof(packet), &packet))
|
||||
return false;
|
||||
|
||||
if (!Recv(kPacket.iKeyStreamLen, kPacket.m_pStream))
|
||||
return false;
|
||||
Tracen("KEY_COMPLETE RECV - Decrypting session token");
|
||||
|
||||
SecureCipher& cipher = GetSecureCipher();
|
||||
|
||||
uint8_t session_token[SecureCipher::SESSION_TOKEN_SIZE];
|
||||
if (crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||
session_token, nullptr,
|
||||
nullptr,
|
||||
packet.encrypted_token, sizeof(packet.encrypted_token),
|
||||
nullptr, 0,
|
||||
packet.nonce,
|
||||
cipher.GetRxKey()) != 0)
|
||||
{
|
||||
Tracen("Failed to decrypt session token - authentication failed");
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
cipher.SetSessionToken(session_token);
|
||||
cipher.SetActivated(true);
|
||||
|
||||
Tracen("Secure channel established - encryption activated");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAccountConnector::__AuthState_RecvHybridCryptSDB(int iTotalSize)
|
||||
{
|
||||
int iFixedHeaderSize = TPacketGCHybridSDB::GetFixedHeaderSize();
|
||||
|
||||
TPacketGCHybridSDB kPacket(iTotalSize-iFixedHeaderSize);
|
||||
|
||||
if (!Recv(iFixedHeaderSize, &kPacket))
|
||||
return false;
|
||||
|
||||
if (!Recv(kPacket.iSDBStreamLen, kPacket.m_pStream))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CAccountConnector::__AuthState_RecvPing()
|
||||
{
|
||||
TPacketGCPing kPacketPing;
|
||||
@@ -309,8 +289,6 @@ bool CAccountConnector::__AuthState_RecvAuthSuccess()
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD dwPanamaKey = kAuthSuccessPacket.dwLoginKey ^ g_adwEncryptKey[0] ^ g_adwEncryptKey[1] ^ g_adwEncryptKey[2] ^ g_adwEncryptKey[3];
|
||||
|
||||
CPythonNetworkStream & rkNet = CPythonNetworkStream::Instance();
|
||||
rkNet.SetLoginKey(kAuthSuccessPacket.dwLoginKey);
|
||||
rkNet.Connect(m_strAddr.c_str(), m_iPort);
|
||||
@@ -331,72 +309,9 @@ bool CAccountConnector::__AuthState_RecvAuthFailure()
|
||||
if (m_poHandler)
|
||||
PyCallClassMemberFunc(m_poHandler, "OnLoginFailure", Py_BuildValue("(s)", packet_failure.szStatus));
|
||||
|
||||
// __OfflineState_Set();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
bool CAccountConnector::__AuthState_RecvKeyAgreement()
|
||||
{
|
||||
TPacketKeyAgreement packet;
|
||||
if (!Recv(sizeof(packet), &packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Tracenf("KEY_AGREEMENT RECV %u", packet.wDataLength);
|
||||
|
||||
TPacketKeyAgreement packetToSend;
|
||||
size_t dataLength = TPacketKeyAgreement::MAX_DATA_LEN;
|
||||
size_t agreedLength = Prepare(packetToSend.data, &dataLength);
|
||||
if (agreedLength == 0)
|
||||
{
|
||||
// 초기화 실패
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
assert(dataLength <= TPacketKeyAgreement::MAX_DATA_LEN);
|
||||
|
||||
if (Activate(packet.wAgreedLength, packet.data, packet.wDataLength))
|
||||
{
|
||||
// Key agreement 성공, 응답 전송
|
||||
packetToSend.bHeader = HEADER_CG_KEY_AGREEMENT;
|
||||
packetToSend.wAgreedLength = (WORD)agreedLength;
|
||||
packetToSend.wDataLength = (WORD)dataLength;
|
||||
|
||||
if (!Send(sizeof(packetToSend), &packetToSend))
|
||||
{
|
||||
Tracen(" CAccountConnector::__AuthState_RecvKeyAgreement - SendKeyAgreement Error");
|
||||
return false;
|
||||
}
|
||||
Tracenf("KEY_AGREEMENT SEND %u", packetToSend.wDataLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 키 협상 실패
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAccountConnector::__AuthState_RecvKeyAgreementCompleted()
|
||||
{
|
||||
TPacketKeyAgreementCompleted packet;
|
||||
if (!Recv(sizeof(packet), &packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Tracenf("KEY_AGREEMENT_COMPLETED RECV");
|
||||
|
||||
ActivateCipher();
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
bool CAccountConnector::__AnalyzePacket(UINT uHeader, UINT uPacketSize, bool (CAccountConnector::*pfnDispatchPacket)())
|
||||
{
|
||||
BYTE bHeader;
|
||||
@@ -412,27 +327,6 @@ bool CAccountConnector::__AnalyzePacket(UINT uHeader, UINT uPacketSize, bool (CA
|
||||
return (this->*pfnDispatchPacket)();
|
||||
}
|
||||
|
||||
bool CAccountConnector::__AnalyzeVarSizePacket(UINT uHeader, bool (CAccountConnector::*pfnDispatchPacket)(int))
|
||||
{
|
||||
BYTE bHeader;
|
||||
if (!Peek(sizeof(bHeader), &bHeader))
|
||||
return true;
|
||||
|
||||
if (bHeader!=uHeader)
|
||||
return true;
|
||||
|
||||
TDynamicSizePacketHeader dynamicHeader;
|
||||
|
||||
if (!Peek(sizeof(dynamicHeader), &dynamicHeader))
|
||||
return true;
|
||||
|
||||
if (!Peek(dynamicHeader.size))
|
||||
return true;
|
||||
|
||||
return (this->*pfnDispatchPacket)(dynamicHeader.size);
|
||||
}
|
||||
|
||||
|
||||
void CAccountConnector::__OfflineState_Set()
|
||||
{
|
||||
__Inialize();
|
||||
@@ -463,7 +357,6 @@ void CAccountConnector::OnConnectSuccess()
|
||||
|
||||
void CAccountConnector::OnRemoteDisconnect()
|
||||
{
|
||||
// Matrix Card Number 를 보내 놓았는데 close 되면 프로그램을 종료 한다.
|
||||
if (m_isWaitKey)
|
||||
{
|
||||
if (m_poHandler)
|
||||
@@ -481,17 +374,6 @@ void CAccountConnector::OnDisconnect()
|
||||
__OfflineState_Set();
|
||||
}
|
||||
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
void CAccountConnector::__BuildClientKey()
|
||||
{
|
||||
for (DWORD i = 0; i < 4; ++i)
|
||||
g_adwEncryptKey[i] = random();
|
||||
|
||||
const BYTE * c_pszKey = (const BYTE *) "JyTxtHljHJlVJHorRM301vf@4fvj10-v";
|
||||
tea_encrypt((DWORD *) g_adwDecryptKey, (const DWORD *) g_adwEncryptKey, (const DWORD *) c_pszKey, 16);
|
||||
}
|
||||
#endif
|
||||
|
||||
void CAccountConnector::__Inialize()
|
||||
{
|
||||
m_eState=STATE_OFFLINE;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma
|
||||
#pragma once
|
||||
|
||||
#include "EterLib/NetStream.h"
|
||||
#include "EterLib/FuncObject.h"
|
||||
@@ -49,22 +49,10 @@ class CAccountConnector : public CNetworkStream, public CSingleton<CAccountConne
|
||||
bool __AuthState_SendPong();
|
||||
bool __AuthState_RecvAuthSuccess();
|
||||
bool __AuthState_RecvAuthFailure();
|
||||
bool __AuthState_RecvPanamaPack();
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
bool __AuthState_RecvKeyAgreement();
|
||||
bool __AuthState_RecvKeyAgreementCompleted();
|
||||
#endif
|
||||
bool __AuthState_RecvHybridCryptKeys(int VarSize);
|
||||
bool __AuthState_RecvHybridCryptSDB(int VarSize);
|
||||
bool __AuthState_RecvKeyChallenge();
|
||||
bool __AuthState_RecvKeyComplete();
|
||||
|
||||
bool __AnalyzePacket(UINT uHeader, UINT uPacketSize, bool (CAccountConnector::*pfnDispatchPacket)());
|
||||
// TODO: 지금 현재는 임시다. header뒤에 size 4byte가 무조건 온다는 가정임.
|
||||
// 제대로 하려면 Packet System Refactoring해야 한다.
|
||||
bool __AnalyzeVarSizePacket(UINT uHeader, bool (CAccountConnector::*pfnDispatchPacket)(int));
|
||||
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
void __BuildClientKey();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
UINT m_eState;
|
||||
@@ -77,7 +65,4 @@ class CAccountConnector : public CNetworkStream, public CSingleton<CAccountConne
|
||||
|
||||
PyObject * m_poHandler;
|
||||
|
||||
// CHINA_CRYPT_KEY
|
||||
void __BuildClientKey_20050304Myevan();
|
||||
// END_OF_CHINA_CRYPT_KEY
|
||||
};
|
||||
|
||||
@@ -24,8 +24,7 @@ target_link_libraries(UserInterface
|
||||
SpeedTreeLib
|
||||
SphereLib
|
||||
PackLib
|
||||
|
||||
cryptopp-static
|
||||
|
||||
lzo2
|
||||
libzstd_static
|
||||
mio
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "PythonCharacterManager.h"
|
||||
#include "PythonTextTail.h"
|
||||
#include "Packet.h"
|
||||
#include "PackLib/PackManager.h"
|
||||
|
||||
// MARK_BUG_FIX
|
||||
struct SMarkIndex
|
||||
@@ -193,15 +192,12 @@ UINT CGuildMarkDownloader::__GetPacketSize(UINT header)
|
||||
return sizeof(TPacketGCMarkBlock);
|
||||
case HEADER_GC_GUILD_SYMBOL_DATA:
|
||||
return sizeof(TPacketGCGuildSymbolData);
|
||||
case HEADER_GC_MARK_DIFF_DATA: // 사용하지 않음
|
||||
case HEADER_GC_MARK_DIFF_DATA:
|
||||
return sizeof(BYTE);
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
case HEADER_GC_KEY_AGREEMENT:
|
||||
return sizeof(TPacketKeyAgreement);
|
||||
case HEADER_GC_KEY_AGREEMENT_COMPLETED:
|
||||
return sizeof(TPacketKeyAgreementCompleted);
|
||||
|
||||
#endif
|
||||
case HEADER_GC_KEY_CHALLENGE:
|
||||
return sizeof(TPacketGCKeyChallenge);
|
||||
case HEADER_GC_KEY_COMPLETE:
|
||||
return sizeof(TPacketGCKeyComplete);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -222,16 +218,14 @@ bool CGuildMarkDownloader::__DispatchPacket(UINT header)
|
||||
return __LoginState_RecvMarkBlock();
|
||||
case HEADER_GC_GUILD_SYMBOL_DATA:
|
||||
return __LoginState_RecvSymbolData();
|
||||
case HEADER_GC_MARK_DIFF_DATA: // 사용하지 않음
|
||||
case HEADER_GC_MARK_DIFF_DATA:
|
||||
return true;
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
case HEADER_GC_KEY_AGREEMENT:
|
||||
return __LoginState_RecvKeyAgreement();
|
||||
case HEADER_GC_KEY_AGREEMENT_COMPLETED:
|
||||
return __LoginState_RecvKeyAgreementCompleted();
|
||||
#endif
|
||||
case HEADER_GC_KEY_CHALLENGE:
|
||||
return __LoginState_RecvKeyChallenge();
|
||||
case HEADER_GC_KEY_COMPLETE:
|
||||
return __LoginState_RecvKeyComplete();
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
// END_OF_MARK_BUG_FIX
|
||||
|
||||
@@ -279,11 +273,6 @@ bool CGuildMarkDownloader::__LoginState_RecvPhase()
|
||||
|
||||
if (kPacketPhase.phase == PHASE_LOGIN)
|
||||
{
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
const char* key = GetSecurityKey();
|
||||
SetSecurityMode(true, key);
|
||||
#endif
|
||||
|
||||
switch (m_dwTodo)
|
||||
{
|
||||
case TODO_RECV_NONE:
|
||||
@@ -428,66 +417,63 @@ bool CGuildMarkDownloader::__LoginState_RecvMarkBlock()
|
||||
}
|
||||
// END_OF_MARK_BUG_FIX
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
bool CGuildMarkDownloader::__LoginState_RecvKeyAgreement()
|
||||
bool CGuildMarkDownloader::__LoginState_RecvKeyChallenge()
|
||||
{
|
||||
TPacketKeyAgreement packet;
|
||||
TPacketGCKeyChallenge packet;
|
||||
if (!Recv(sizeof(packet), &packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Tracenf("KEY_AGREEMENT RECV %u", packet.wDataLength);
|
||||
Tracen("KEY_CHALLENGE RECV");
|
||||
|
||||
TPacketKeyAgreement packetToSend;
|
||||
size_t dataLength = TPacketKeyAgreement::MAX_DATA_LEN;
|
||||
size_t agreedLength = Prepare(packetToSend.data, &dataLength);
|
||||
if (agreedLength == 0)
|
||||
SecureCipher& cipher = GetSecureCipher();
|
||||
if (!cipher.Initialize())
|
||||
{
|
||||
// 초기화 실패
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
assert(dataLength <= TPacketKeyAgreement::MAX_DATA_LEN);
|
||||
|
||||
if (Activate(packet.wAgreedLength, packet.data, packet.wDataLength))
|
||||
if (!cipher.ComputeClientKeys(packet.server_pk))
|
||||
{
|
||||
// Key agreement 성공, 응답 전송
|
||||
packetToSend.bHeader = HEADER_CG_KEY_AGREEMENT;
|
||||
packetToSend.wAgreedLength = (WORD)agreedLength;
|
||||
packetToSend.wDataLength = (WORD)dataLength;
|
||||
|
||||
if (!Send(sizeof(packetToSend), &packetToSend))
|
||||
{
|
||||
Tracen(" CAccountConnector::__AuthState_RecvKeyAgreement - SendKeyAgreement Error");
|
||||
return false;
|
||||
}
|
||||
Tracenf("KEY_AGREEMENT SEND %u", packetToSend.wDataLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 키 협상 실패
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
TPacketCGKeyResponse response;
|
||||
response.bHeader = HEADER_CG_KEY_RESPONSE;
|
||||
cipher.GetPublicKey(response.client_pk);
|
||||
cipher.ComputeResponse(packet.challenge, response.challenge_response);
|
||||
|
||||
if (!Send(sizeof(response), &response))
|
||||
return false;
|
||||
|
||||
Tracen("KEY_RESPONSE SENT");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGuildMarkDownloader::__LoginState_RecvKeyAgreementCompleted()
|
||||
bool CGuildMarkDownloader::__LoginState_RecvKeyComplete()
|
||||
{
|
||||
TPacketKeyAgreementCompleted packet;
|
||||
TPacketGCKeyComplete packet;
|
||||
if (!Recv(sizeof(packet), &packet))
|
||||
return false;
|
||||
|
||||
Tracen("KEY_COMPLETE RECV");
|
||||
|
||||
SecureCipher& cipher = GetSecureCipher();
|
||||
|
||||
uint8_t session_token[SecureCipher::SESSION_TOKEN_SIZE];
|
||||
if (!cipher.DecryptToken(packet.encrypted_token, sizeof(packet.encrypted_token),
|
||||
packet.nonce, session_token))
|
||||
{
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
Tracenf("KEY_AGREEMENT_COMPLETED RECV");
|
||||
|
||||
ActivateCipher();
|
||||
cipher.SetSessionToken(session_token);
|
||||
cipher.SetActivated(true);
|
||||
|
||||
Tracen("SECURE CIPHER ACTIVATED");
|
||||
return true;
|
||||
}
|
||||
#endif // _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
bool CGuildMarkDownloader::__SendSymbolCRCList()
|
||||
{
|
||||
|
||||
@@ -54,10 +54,8 @@ class CGuildMarkDownloader : public CNetworkStream, public CSingleton<CGuildMark
|
||||
bool __LoginState_RecvMarkIndex();
|
||||
bool __LoginState_RecvMarkBlock();
|
||||
bool __LoginState_RecvSymbolData();
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
bool __LoginState_RecvKeyAgreement();
|
||||
bool __LoginState_RecvKeyAgreementCompleted();
|
||||
#endif
|
||||
bool __LoginState_RecvKeyChallenge();
|
||||
bool __LoginState_RecvKeyComplete();
|
||||
bool __SendMarkIDXList();
|
||||
bool __SendMarkCRCList();
|
||||
bool __SendSymbolCRCList();
|
||||
|
||||
@@ -272,13 +272,11 @@ bool CGuildMarkUploader::__LoginState_Process()
|
||||
if (!__AnalyzePacket(HEADER_GC_PING, sizeof(TPacketGCPing), &CGuildMarkUploader::__LoginState_RecvPing))
|
||||
return false;
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
if (!__AnalyzePacket(HEADER_GC_KEY_AGREEMENT, sizeof(TPacketKeyAgreement), &CGuildMarkUploader::__LoginState_RecvKeyAgreement))
|
||||
if (!__AnalyzePacket(HEADER_GC_KEY_CHALLENGE, sizeof(TPacketGCKeyChallenge), &CGuildMarkUploader::__LoginState_RecvKeyChallenge))
|
||||
return false;
|
||||
|
||||
if (!__AnalyzePacket(HEADER_GC_KEY_AGREEMENT_COMPLETED, sizeof(TPacketKeyAgreementCompleted), &CGuildMarkUploader::__LoginState_RecvKeyAgreementCompleted))
|
||||
if (!__AnalyzePacket(HEADER_GC_KEY_COMPLETE, sizeof(TPacketGCKeyComplete), &CGuildMarkUploader::__LoginState_RecvKeyComplete))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -330,11 +328,6 @@ bool CGuildMarkUploader::__LoginState_RecvPhase()
|
||||
|
||||
if (kPacketPhase.phase==PHASE_LOGIN)
|
||||
{
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
const char* key = GetSecurityKey();
|
||||
SetSecurityMode(true, key);
|
||||
#endif
|
||||
|
||||
if (SEND_TYPE_MARK == m_dwSendType)
|
||||
{
|
||||
if (!__SendMarkPacket())
|
||||
@@ -384,66 +377,63 @@ bool CGuildMarkUploader::__LoginState_RecvPing()
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
bool CGuildMarkUploader::__LoginState_RecvKeyAgreement()
|
||||
bool CGuildMarkUploader::__LoginState_RecvKeyChallenge()
|
||||
{
|
||||
TPacketKeyAgreement packet;
|
||||
TPacketGCKeyChallenge packet;
|
||||
if (!Recv(sizeof(packet), &packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Tracenf("KEY_AGREEMENT RECV %u", packet.wDataLength);
|
||||
Tracen("KEY_CHALLENGE RECV");
|
||||
|
||||
TPacketKeyAgreement packetToSend;
|
||||
size_t dataLength = TPacketKeyAgreement::MAX_DATA_LEN;
|
||||
size_t agreedLength = Prepare(packetToSend.data, &dataLength);
|
||||
if (agreedLength == 0)
|
||||
SecureCipher& cipher = GetSecureCipher();
|
||||
if (!cipher.Initialize())
|
||||
{
|
||||
// 초기화 실패
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
assert(dataLength <= TPacketKeyAgreement::MAX_DATA_LEN);
|
||||
|
||||
if (Activate(packet.wAgreedLength, packet.data, packet.wDataLength))
|
||||
if (!cipher.ComputeClientKeys(packet.server_pk))
|
||||
{
|
||||
// Key agreement 성공, 응답 전송
|
||||
packetToSend.bHeader = HEADER_CG_KEY_AGREEMENT;
|
||||
packetToSend.wAgreedLength = (WORD)agreedLength;
|
||||
packetToSend.wDataLength = (WORD)dataLength;
|
||||
|
||||
if (!Send(sizeof(packetToSend), &packetToSend))
|
||||
{
|
||||
Tracen(" CAccountConnector::__AuthState_RecvKeyAgreement - SendKeyAgreement Error");
|
||||
return false;
|
||||
}
|
||||
Tracenf("KEY_AGREEMENT SEND %u", packetToSend.wDataLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 키 협상 실패
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
TPacketCGKeyResponse response;
|
||||
response.bHeader = HEADER_CG_KEY_RESPONSE;
|
||||
cipher.GetPublicKey(response.client_pk);
|
||||
cipher.ComputeResponse(packet.challenge, response.challenge_response);
|
||||
|
||||
if (!Send(sizeof(response), &response))
|
||||
return false;
|
||||
|
||||
Tracen("KEY_RESPONSE SENT");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGuildMarkUploader::__LoginState_RecvKeyAgreementCompleted()
|
||||
bool CGuildMarkUploader::__LoginState_RecvKeyComplete()
|
||||
{
|
||||
TPacketKeyAgreementCompleted packet;
|
||||
TPacketGCKeyComplete packet;
|
||||
if (!Recv(sizeof(packet), &packet))
|
||||
return false;
|
||||
|
||||
Tracen("KEY_COMPLETE RECV");
|
||||
|
||||
SecureCipher& cipher = GetSecureCipher();
|
||||
|
||||
uint8_t session_token[SecureCipher::SESSION_TOKEN_SIZE];
|
||||
if (!cipher.DecryptToken(packet.encrypted_token, sizeof(packet.encrypted_token),
|
||||
packet.nonce, session_token))
|
||||
{
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
Tracenf("KEY_AGREEMENT_COMPLETED RECV");
|
||||
|
||||
ActivateCipher();
|
||||
cipher.SetSessionToken(session_token);
|
||||
cipher.SetActivated(true);
|
||||
|
||||
Tracen("SECURE CIPHER ACTIVATED");
|
||||
return true;
|
||||
}
|
||||
#endif // _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
bool CGuildMarkUploader::__AnalyzePacket(UINT uHeader, UINT uPacketSize, bool (CGuildMarkUploader::*pfnDispatchPacket)())
|
||||
{
|
||||
|
||||
@@ -88,10 +88,8 @@ class CGuildMarkUploader : public CNetworkStream, public CSingleton<CGuildMarkUp
|
||||
bool __LoginState_RecvPhase();
|
||||
bool __LoginState_RecvHandshake();
|
||||
bool __LoginState_RecvPing();
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
bool __LoginState_RecvKeyAgreement();
|
||||
bool __LoginState_RecvKeyAgreementCompleted();
|
||||
#endif
|
||||
bool __LoginState_RecvKeyChallenge();
|
||||
bool __LoginState_RecvKeyComplete();
|
||||
|
||||
bool __AnalyzePacket(UINT uHeader, UINT uPacketSize, bool (CGuildMarkUploader::*pfnDispatchPacket)());
|
||||
|
||||
|
||||
@@ -6,12 +6,6 @@
|
||||
|
||||
#include <windowsx.h>
|
||||
|
||||
#ifndef LSS_SECURITY_KEY
|
||||
#define LSS_SECURITY_KEY "testtesttesttest"
|
||||
#endif
|
||||
|
||||
std::string __SECURITY_KEY_STRING__ = LSS_SECURITY_KEY;
|
||||
|
||||
char MULTI_LOCALE_PATH_COMMON[256] = "locale/common";
|
||||
char MULTI_LOCALE_PATH[256] = "locale/en";
|
||||
char MULTI_LOCALE_NAME[256] = "en";
|
||||
@@ -100,11 +94,6 @@ int GetSkillPower(unsigned level)
|
||||
return SKILL_POWERS[level];
|
||||
}
|
||||
|
||||
const char* GetSecurityKey()
|
||||
{
|
||||
return __SECURITY_KEY_STRING__.c_str();
|
||||
}
|
||||
|
||||
const char* GetLocaleName()
|
||||
{
|
||||
return MULTI_LOCALE_NAME;
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
const char* GetLocaleName();
|
||||
const char* GetLocalePath();
|
||||
const char* GetLocalePathCommon();
|
||||
const char* GetSecurityKey();
|
||||
|
||||
bool IsRTL();
|
||||
int StringCompareCI( LPCSTR szStringLeft, LPCSTR szStringRight, size_t sizeLength );
|
||||
void LoadConfig(const char* fileName);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#define _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
#define ENABLE_COSTUME_SYSTEM
|
||||
#define ENABLE_ENERGY_SYSTEM
|
||||
#define ENABLE_DRAGON_SOUL_SYSTEM
|
||||
|
||||
@@ -11,7 +11,6 @@ enum
|
||||
/////////////////////////////////////////////////
|
||||
// To Server
|
||||
// HEADER_BLANK is the not use(for future use)
|
||||
HEADER_CG_LOGIN = 1,
|
||||
HEADER_CG_ATTACK = 2,
|
||||
HEADER_CG_CHAT = 3,
|
||||
HEADER_CG_PLAYER_CREATE = 4, // 새로운 플래이어를 생성
|
||||
@@ -131,7 +130,8 @@ enum
|
||||
HEADER_CG_DRAGON_SOUL_REFINE = 205,
|
||||
HEADER_CG_STATE_CHECKER = 206,
|
||||
|
||||
HEADER_CG_KEY_AGREEMENT = 0xfb, // _IMPROVED_PACKET_ENCRYPTION_
|
||||
HEADER_CG_KEY_RESPONSE = 0xf9, // Secure key exchange response
|
||||
HEADER_CG_LOGIN_SECURE = 0xf6, // Secure login packet
|
||||
HEADER_CG_TIME_SYNC = 0xfc,
|
||||
HEADER_CG_CLIENT_VERSION = 0xfd,
|
||||
HEADER_CG_CLIENT_VERSION2 = 0xf1,
|
||||
@@ -288,21 +288,15 @@ enum
|
||||
// END_OF_SUPPORT_BGM
|
||||
|
||||
HEADER_GC_AUTH_SUCCESS = 150,
|
||||
HEADER_GC_PANAMA_PACK = 151,
|
||||
|
||||
//HYBRID CRYPT
|
||||
HEADER_GC_HYBRIDCRYPT_KEYS = 152,
|
||||
HEADER_GC_HYBRIDCRYPT_SDB = 153, // SDB means Supplmentary Data Blocks
|
||||
//HYBRID CRYPT
|
||||
|
||||
HEADER_GC_SPECIFIC_EFFECT = 208,
|
||||
HEADER_GC_DRAGON_SOUL_REFINE = 209,
|
||||
HEADER_GC_DRAGON_SOUL_REFINE = 209,
|
||||
HEADER_GC_RESPOND_CHANNELSTATUS = 210,
|
||||
|
||||
HEADER_GC_ITEM_GET = 211,
|
||||
|
||||
HEADER_GC_KEY_AGREEMENT_COMPLETED = 0xfa, // _IMPROVED_PACKET_ENCRYPTION_
|
||||
HEADER_GC_KEY_AGREEMENT = 0xfb, // _IMPROVED_PACKET_ENCRYPTION_
|
||||
HEADER_GC_KEY_CHALLENGE = 0xf8, // Secure key exchange challenge
|
||||
HEADER_GC_KEY_COMPLETE = 0xf7, // Secure key exchange complete
|
||||
HEADER_GC_HANDSHAKE_OK = 0xfc, // 252
|
||||
HEADER_GC_PHASE = 0xfd, // 253
|
||||
HEADER_GC_BINDUDP = 0xfe, // 254
|
||||
@@ -479,20 +473,12 @@ typedef struct command_checkin
|
||||
char pwd[PASS_MAX_NUM+1];
|
||||
} TPacketCGCheckin;
|
||||
|
||||
typedef struct command_login
|
||||
{
|
||||
uint8_t header;
|
||||
char name[ID_MAX_NUM + 1];
|
||||
char pwd[PASS_MAX_NUM + 1];
|
||||
} TPacketCGLogin;
|
||||
|
||||
// start - 권한 서버 접속을 위한 패킷들
|
||||
typedef struct command_login2
|
||||
{
|
||||
uint8_t header;
|
||||
char name[ID_MAX_NUM + 1];
|
||||
uint32_t login_key;
|
||||
uint32_t adwClientKey[4];
|
||||
} TPacketCGLogin2;
|
||||
|
||||
typedef struct command_login3
|
||||
@@ -500,7 +486,6 @@ typedef struct command_login3
|
||||
uint8_t header;
|
||||
char name[ID_MAX_NUM + 1];
|
||||
char pwd[PASS_MAX_NUM + 1];
|
||||
uint32_t adwClientKey[4];
|
||||
} TPacketCGLogin3;
|
||||
|
||||
typedef struct command_direct_enter
|
||||
@@ -2468,70 +2453,6 @@ typedef struct SPacketGCResetOnTime
|
||||
uint8_t header;
|
||||
} TPacketGCResetOnTime;
|
||||
|
||||
typedef struct SPacketGCPanamaPack
|
||||
{
|
||||
uint8_t bHeader;
|
||||
char szPackName[256];
|
||||
uint8_t abIV[32];
|
||||
} TPacketGCPanamaPack;
|
||||
|
||||
typedef struct SPacketGCHybridCryptKeys
|
||||
{
|
||||
private:
|
||||
SPacketGCHybridCryptKeys() : m_pStream(NULL) {}
|
||||
|
||||
public:
|
||||
SPacketGCHybridCryptKeys(int32_t iStreamSize) : iKeyStreamLen(iStreamSize)
|
||||
{
|
||||
m_pStream = new uint8_t[iStreamSize];
|
||||
}
|
||||
~SPacketGCHybridCryptKeys()
|
||||
{
|
||||
if( m_pStream )
|
||||
{
|
||||
delete[] m_pStream;
|
||||
m_pStream = NULL;
|
||||
}
|
||||
}
|
||||
static int32_t GetFixedHeaderSize()
|
||||
{
|
||||
return sizeof(uint8_t)+sizeof(uint16_t)+sizeof(int32_t);
|
||||
}
|
||||
|
||||
uint8_t bHeader;
|
||||
uint16_t wDynamicPacketSize;
|
||||
int32_t iKeyStreamLen;
|
||||
uint8_t* m_pStream;
|
||||
|
||||
} TPacketGCHybridCryptKeys;
|
||||
|
||||
|
||||
typedef struct SPacketGCHybridSDB
|
||||
{
|
||||
private:
|
||||
SPacketGCHybridSDB() : m_pStream(NULL) {}
|
||||
|
||||
public:
|
||||
SPacketGCHybridSDB(int32_t iStreamSize) : iSDBStreamLen(iStreamSize)
|
||||
{
|
||||
m_pStream = new uint8_t[iStreamSize];
|
||||
}
|
||||
~SPacketGCHybridSDB()
|
||||
{
|
||||
delete[] m_pStream;
|
||||
m_pStream = NULL;
|
||||
}
|
||||
static int32_t GetFixedHeaderSize()
|
||||
{
|
||||
return sizeof(uint8_t)+sizeof(uint16_t)+sizeof(int32_t);
|
||||
}
|
||||
|
||||
uint8_t bHeader;
|
||||
uint16_t wDynamicPacketSize;
|
||||
int32_t iSDBStreamLen;
|
||||
uint8_t* m_pStream;
|
||||
|
||||
} TPacketGCHybridSDB;
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Client To Client
|
||||
|
||||
@@ -2556,22 +2477,43 @@ typedef struct packet_autoban_quiz
|
||||
} TPacketGCAutoBanQuiz;
|
||||
// END_OF_AUTOBAN
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
struct TPacketKeyAgreement
|
||||
// Secure authentication packets (libsodium/XChaCha20-Poly1305)
|
||||
#pragma pack(push, 1)
|
||||
|
||||
// Server -> Client: Key exchange challenge
|
||||
struct TPacketGCKeyChallenge
|
||||
{
|
||||
static const int32_t MAX_DATA_LEN = 256;
|
||||
uint8_t bHeader;
|
||||
uint16_t wAgreedLength;
|
||||
uint16_t wDataLength;
|
||||
uint8_t data[MAX_DATA_LEN];
|
||||
uint8_t bHeader; // HEADER_GC_KEY_CHALLENGE (0xf8)
|
||||
uint8_t server_pk[32]; // Server's X25519 public key
|
||||
uint8_t challenge[32]; // Random challenge bytes
|
||||
};
|
||||
|
||||
struct TPacketKeyAgreementCompleted
|
||||
// Client -> Server: Key exchange response
|
||||
struct TPacketCGKeyResponse
|
||||
{
|
||||
uint8_t bHeader;
|
||||
uint8_t data[3]; // dummy (not used)
|
||||
uint8_t bHeader; // HEADER_CG_KEY_RESPONSE (0xf9)
|
||||
uint8_t client_pk[32]; // Client's X25519 public key
|
||||
uint8_t challenge_response[32]; // HMAC(challenge, rx_key)
|
||||
};
|
||||
#endif // _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
// Server -> Client: Key exchange complete
|
||||
struct TPacketGCKeyComplete
|
||||
{
|
||||
uint8_t bHeader; // HEADER_GC_KEY_COMPLETE (0xf7)
|
||||
uint8_t encrypted_token[32 + 16]; // Session token + Poly1305 tag
|
||||
uint8_t nonce[24]; // XChaCha20 nonce
|
||||
};
|
||||
|
||||
// Client -> Server: Secure login
|
||||
struct TPacketCGLoginSecure
|
||||
{
|
||||
uint8_t bHeader; // HEADER_CG_LOGIN_SECURE (0xf6)
|
||||
char name[ID_MAX_NUM + 1];
|
||||
char pwd[PASS_MAX_NUM + 1];
|
||||
uint8_t session_token[32]; // Session token from KeyComplete
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct SPacketGCSpecificEffect
|
||||
{
|
||||
|
||||
@@ -108,10 +108,9 @@ class CMainPacketHeaderMap : public CNetworkPacketHeaderMap
|
||||
Set(HEADER_GC_BINDUDP, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCBindUDP), STATIC_SIZE_PACKET));
|
||||
Set(HEADER_GC_OWNERSHIP, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCOwnership), STATIC_SIZE_PACKET));
|
||||
Set(HEADER_GC_CREATE_FLY, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCCreateFly), STATIC_SIZE_PACKET));
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
Set(HEADER_GC_KEY_AGREEMENT, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketKeyAgreement), STATIC_SIZE_PACKET));
|
||||
Set(HEADER_GC_KEY_AGREEMENT_COMPLETED, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketKeyAgreementCompleted), STATIC_SIZE_PACKET));
|
||||
#endif
|
||||
// Secure key exchange (libsodium)
|
||||
Set(HEADER_GC_KEY_CHALLENGE, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCKeyChallenge), STATIC_SIZE_PACKET));
|
||||
Set(HEADER_GC_KEY_COMPLETE, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCKeyComplete), STATIC_SIZE_PACKET));
|
||||
Set(HEADER_GC_ADD_FLY_TARGETING, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCFlyTargeting), STATIC_SIZE_PACKET));
|
||||
Set(HEADER_GC_FLY_TARGETING, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCFlyTargeting), STATIC_SIZE_PACKET));
|
||||
|
||||
@@ -174,8 +173,6 @@ class CMainPacketHeaderMap : public CNetworkPacketHeaderMap
|
||||
Set(HEADER_GC_DIG_MOTION, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCDigMotion), STATIC_SIZE_PACKET));
|
||||
Set(HEADER_GC_DAMAGE_INFO, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCDamageInfo), STATIC_SIZE_PACKET));
|
||||
|
||||
Set(HEADER_GC_HYBRIDCRYPT_KEYS, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCHybridCryptKeys), DYNAMIC_SIZE_PACKET));
|
||||
Set(HEADER_GC_HYBRIDCRYPT_SDB, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCHybridSDB), DYNAMIC_SIZE_PACKET));
|
||||
Set(HEADER_GC_SPECIFIC_EFFECT, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCSpecificEffect), STATIC_SIZE_PACKET));
|
||||
Set(HEADER_GC_DRAGON_SOUL_REFINE, CNetworkPacketHeaderMap::TPacketType(sizeof(TPacketGCDragonSoulRefine), STATIC_SIZE_PACKET));
|
||||
|
||||
|
||||
@@ -270,13 +270,10 @@ class CPythonNetworkStream : public CNetworkStream, public CSingleton<CPythonNet
|
||||
bool RecvHandshakePacket();
|
||||
bool RecvHandshakeOKPacket();
|
||||
|
||||
bool RecvHybridCryptKeyPacket();
|
||||
bool RecvHybridCryptSDBPacket();
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
bool RecvKeyAgreementPacket();
|
||||
bool RecvKeyAgreementCompletedPacket();
|
||||
// Secure key exchange (libsodium/XChaCha20-Poly1305)
|
||||
bool RecvKeyChallenge();
|
||||
bool RecvKeyComplete();
|
||||
|
||||
#endif
|
||||
// ETC
|
||||
DWORD GetMainActorVID();
|
||||
DWORD GetMainActorRace();
|
||||
@@ -299,9 +296,7 @@ class CPythonNetworkStream : public CNetworkStream, public CSingleton<CPythonNet
|
||||
void ClosePhase();
|
||||
|
||||
// Login Phase
|
||||
bool SendLoginPacket(const char * c_szName, const char * c_szPassword);
|
||||
bool SendLoginPacketNew(const char * c_szName, const char * c_szPassword);
|
||||
bool SendDirectEnterPacket(const char * c_szName, const char * c_szPassword, UINT uChrSlot);
|
||||
|
||||
bool SendEnterGame();
|
||||
|
||||
|
||||
@@ -407,7 +407,7 @@ PyObject* netSendLoginPacket(PyObject* poSelf, PyObject* poArgs)
|
||||
return Py_BuildException();
|
||||
|
||||
CPythonNetworkStream& rkNetStream=CPythonNetworkStream::Instance();
|
||||
rkNetStream.SendLoginPacket(szName, szPwd);
|
||||
rkNetStream.SendLoginPacketNew(szName, szPwd);
|
||||
return Py_BuildNone();
|
||||
}
|
||||
|
||||
|
||||
@@ -598,30 +598,17 @@ void CPythonNetworkStream::GamePhase()
|
||||
RecvHandshakeOKPacket();
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_HYBRIDCRYPT_KEYS:
|
||||
RecvHybridCryptKeyPacket();
|
||||
|
||||
case HEADER_GC_KEY_CHALLENGE:
|
||||
RecvKeyChallenge();
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_HYBRIDCRYPT_SDB:
|
||||
RecvHybridCryptSDBPacket();
|
||||
case HEADER_GC_KEY_COMPLETE:
|
||||
RecvKeyComplete();
|
||||
return;
|
||||
break;
|
||||
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
case HEADER_GC_KEY_AGREEMENT:
|
||||
RecvKeyAgreementPacket();
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_KEY_AGREEMENT_COMPLETED:
|
||||
RecvKeyAgreementCompletedPacket();
|
||||
return;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case HEADER_GC_SPECIFIC_EFFECT:
|
||||
ret = RecvSpecificEffect();
|
||||
break;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "PythonNetworkStream.h"
|
||||
#include "PythonApplication.h"
|
||||
#include "Packet.h"
|
||||
#include "PackLib/PackManager.h"
|
||||
|
||||
// HandShake ---------------------------------------------------------------------------
|
||||
void CPythonNetworkStream::HandShakePhase()
|
||||
@@ -22,7 +21,7 @@ void CPythonNetworkStream::HandShakePhase()
|
||||
case HEADER_GC_BINDUDP:
|
||||
{
|
||||
TPacketGCBindUDP BindUDP;
|
||||
|
||||
|
||||
if (!Recv(sizeof(TPacketGCBindUDP), &BindUDP))
|
||||
return;
|
||||
|
||||
@@ -39,9 +38,6 @@ void CPythonNetworkStream::HandShakePhase()
|
||||
|
||||
ELTimer_SetServerMSec(m_HandshakeData.dwTime+ m_HandshakeData.lDelta);
|
||||
|
||||
//m_dwBaseServerTime = m_HandshakeData.dwTime+ m_HandshakeData.lDelta;
|
||||
//m_dwBaseClientTime = ELTimer_GetMSec();
|
||||
|
||||
m_HandshakeData.dwTime = m_HandshakeData.dwTime + m_HandshakeData.lDelta + m_HandshakeData.lDelta;
|
||||
m_HandshakeData.lDelta = 0;
|
||||
|
||||
@@ -57,32 +53,21 @@ void CPythonNetworkStream::HandShakePhase()
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case HEADER_GC_PING:
|
||||
RecvPingPacket();
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_HYBRIDCRYPT_KEYS:
|
||||
RecvHybridCryptKeyPacket();
|
||||
case HEADER_GC_KEY_CHALLENGE:
|
||||
RecvKeyChallenge();
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_HYBRIDCRYPT_SDB:
|
||||
RecvHybridCryptSDBPacket();
|
||||
case HEADER_GC_KEY_COMPLETE:
|
||||
RecvKeyComplete();
|
||||
return;
|
||||
break;
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
case HEADER_GC_KEY_AGREEMENT:
|
||||
RecvKeyAgreementPacket();
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_KEY_AGREEMENT_COMPLETED:
|
||||
RecvKeyAgreementCompletedPacket();
|
||||
return;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
RecvErrorPacket(header);
|
||||
@@ -107,7 +92,6 @@ void CPythonNetworkStream::SetHandShakePhase()
|
||||
|
||||
if (__DirectEnterMode_IsSet())
|
||||
{
|
||||
// None
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -125,7 +109,7 @@ bool CPythonNetworkStream::RecvHandshakePacket()
|
||||
|
||||
m_kServerTimeSync.m_dwChangeServerTime = kHandshakeData.dwTime + kHandshakeData.lDelta;
|
||||
m_kServerTimeSync.m_dwChangeClientTime = ELTimer_GetMSec();
|
||||
|
||||
|
||||
kHandshakeData.dwTime = kHandshakeData.dwTime + kHandshakeData.lDelta + kHandshakeData.lDelta;
|
||||
kHandshakeData.lDelta = 0;
|
||||
|
||||
@@ -157,103 +141,71 @@ bool CPythonNetworkStream::RecvHandshakeOKPacket()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPythonNetworkStream::RecvHybridCryptKeyPacket()
|
||||
// Secure key exchange handlers (libsodium/XChaCha20-Poly1305)
|
||||
bool CPythonNetworkStream::RecvKeyChallenge()
|
||||
{
|
||||
int iFixedHeaderSize = TPacketGCHybridCryptKeys::GetFixedHeaderSize();
|
||||
|
||||
TDynamicSizePacketHeader header;
|
||||
if( !Peek( sizeof(header), &header) )
|
||||
return false;
|
||||
|
||||
TPacketGCHybridCryptKeys kPacket(header.size-iFixedHeaderSize);
|
||||
|
||||
if (!Recv(iFixedHeaderSize, &kPacket))
|
||||
return false;
|
||||
|
||||
if (!Recv(kPacket.iKeyStreamLen, kPacket.m_pStream))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPythonNetworkStream::RecvHybridCryptSDBPacket()
|
||||
{
|
||||
int iFixedHeaderSize = TPacketGCHybridSDB::GetFixedHeaderSize();
|
||||
|
||||
TDynamicSizePacketHeader header;
|
||||
if( !Peek( sizeof(header), &header) )
|
||||
return false;
|
||||
|
||||
TPacketGCHybridSDB kPacket(header.size-iFixedHeaderSize);
|
||||
|
||||
if (!Recv(iFixedHeaderSize, &kPacket))
|
||||
return false;
|
||||
|
||||
if (!Recv(kPacket.iSDBStreamLen, kPacket.m_pStream))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
bool CPythonNetworkStream::RecvKeyAgreementPacket()
|
||||
{
|
||||
TPacketKeyAgreement packet;
|
||||
TPacketGCKeyChallenge packet;
|
||||
if (!Recv(sizeof(packet), &packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Tracenf("KEY_AGREEMENT RECV %u", packet.wDataLength);
|
||||
Tracen("SECURE KEY_CHALLENGE RECV");
|
||||
|
||||
TPacketKeyAgreement packetToSend;
|
||||
size_t dataLength = TPacketKeyAgreement::MAX_DATA_LEN;
|
||||
size_t agreedLength = Prepare(packetToSend.data, &dataLength);
|
||||
if (agreedLength == 0)
|
||||
SecureCipher& cipher = GetSecureCipher();
|
||||
if (!cipher.Initialize())
|
||||
{
|
||||
// 초기화 실패
|
||||
TraceError("Failed to initialize SecureCipher");
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
assert(dataLength <= TPacketKeyAgreement::MAX_DATA_LEN);
|
||||
|
||||
if (Activate(packet.wAgreedLength, packet.data, packet.wDataLength))
|
||||
if (!cipher.ComputeClientKeys(packet.server_pk))
|
||||
{
|
||||
// Key agreement 성공, 응답 전송
|
||||
packetToSend.bHeader = HEADER_CG_KEY_AGREEMENT;
|
||||
packetToSend.wAgreedLength = (WORD)agreedLength;
|
||||
packetToSend.wDataLength = (WORD)dataLength;
|
||||
|
||||
if (!Send(sizeof(packetToSend), &packetToSend))
|
||||
{
|
||||
assert(!"Failed Sending KeyAgreement");
|
||||
return false;
|
||||
}
|
||||
Tracenf("KEY_AGREEMENT SEND %u", packetToSend.wDataLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 키 협상 실패
|
||||
TraceError("Failed to compute client session keys");
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
TPacketCGKeyResponse response;
|
||||
response.bHeader = HEADER_CG_KEY_RESPONSE;
|
||||
cipher.GetPublicKey(response.client_pk);
|
||||
cipher.ComputeChallengeResponse(packet.challenge, response.challenge_response);
|
||||
|
||||
if (!Send(sizeof(response), &response))
|
||||
{
|
||||
TraceError("Failed to send KeyResponse");
|
||||
return false;
|
||||
}
|
||||
|
||||
Tracen("SECURE KEY_RESPONSE SENT");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPythonNetworkStream::RecvKeyAgreementCompletedPacket()
|
||||
bool CPythonNetworkStream::RecvKeyComplete()
|
||||
{
|
||||
TPacketKeyAgreementCompleted packet;
|
||||
TPacketGCKeyComplete packet;
|
||||
if (!Recv(sizeof(packet), &packet))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Tracenf("KEY_AGREEMENT_COMPLETED RECV");
|
||||
Tracen("SECURE KEY_COMPLETE RECV");
|
||||
|
||||
ActivateCipher();
|
||||
DecryptAlreadyReceivedData();
|
||||
SecureCipher& cipher = GetSecureCipher();
|
||||
|
||||
uint8_t decrypted_token[SecureCipher::SESSION_TOKEN_SIZE];
|
||||
if (!cipher.DecryptToken(packet.encrypted_token, sizeof(packet.encrypted_token),
|
||||
packet.nonce, decrypted_token))
|
||||
{
|
||||
TraceError("Failed to decrypt session token");
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
cipher.SetSessionToken(decrypted_token);
|
||||
cipher.SetActivated(true);
|
||||
|
||||
Tracen("SECURE CIPHER ACTIVATED");
|
||||
return true;
|
||||
}
|
||||
#endif // _IMPROVED_PACKET_ENCRYPTION_
|
||||
|
||||
@@ -142,17 +142,16 @@ void CPythonNetworkStream::LoadingPhase()
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_HYBRIDCRYPT_KEYS:
|
||||
RecvHybridCryptKeyPacket();
|
||||
case HEADER_GC_KEY_CHALLENGE:
|
||||
RecvKeyChallenge();
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_HYBRIDCRYPT_SDB:
|
||||
RecvHybridCryptSDBPacket();
|
||||
case HEADER_GC_KEY_COMPLETE:
|
||||
RecvKeyComplete();
|
||||
return;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
GamePhase();
|
||||
return;
|
||||
|
||||
@@ -47,13 +47,13 @@ void CPythonNetworkStream::LoginPhase()
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_HYBRIDCRYPT_KEYS:
|
||||
RecvHybridCryptKeyPacket();
|
||||
case HEADER_GC_KEY_CHALLENGE:
|
||||
RecvKeyChallenge();
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_HYBRIDCRYPT_SDB:
|
||||
RecvHybridCryptSDBPacket();
|
||||
case HEADER_GC_KEY_COMPLETE:
|
||||
RecvKeyComplete();
|
||||
return;
|
||||
break;
|
||||
|
||||
@@ -68,11 +68,6 @@ void CPythonNetworkStream::LoginPhase()
|
||||
|
||||
void CPythonNetworkStream::SetLoginPhase()
|
||||
{
|
||||
const char* key = GetSecurityKey();
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
SetSecurityMode(true, key);
|
||||
#endif
|
||||
|
||||
if ("Login" != m_strPhase)
|
||||
m_phaseLeaveFunc.Run();
|
||||
|
||||
@@ -87,26 +82,25 @@ void CPythonNetworkStream::SetLoginPhase()
|
||||
|
||||
m_dwChangingPhaseTime = ELTimer_GetMSec();
|
||||
|
||||
if (0 == m_dwLoginKey)
|
||||
{
|
||||
TraceError("SetLoginPhase: no login key - cannot login without auth server");
|
||||
ClearLoginInfo();
|
||||
return;
|
||||
}
|
||||
|
||||
if (__DirectEnterMode_IsSet())
|
||||
{
|
||||
if (0 != m_dwLoginKey)
|
||||
SendLoginPacketNew(m_stID.c_str(), m_stPassword.c_str());
|
||||
else
|
||||
SendLoginPacket(m_stID.c_str(), m_stPassword.c_str());
|
||||
SendLoginPacketNew(m_stID.c_str(), m_stPassword.c_str());
|
||||
|
||||
// 비밀번호를 메모리에 계속 갖고 있는 문제가 있어서, 사용 즉시 날리는 것으로 변경
|
||||
ClearLoginInfo();
|
||||
CAccountConnector & rkAccountConnector = CAccountConnector::Instance();
|
||||
rkAccountConnector.ClearLoginInfo();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != m_dwLoginKey)
|
||||
SendLoginPacketNew(m_stID.c_str(), m_stPassword.c_str());
|
||||
else
|
||||
SendLoginPacket(m_stID.c_str(), m_stPassword.c_str());
|
||||
SendLoginPacketNew(m_stID.c_str(), m_stPassword.c_str());
|
||||
|
||||
// 비밀번호를 메모리에 계속 갖고 있는 문제가 있어서, 사용 즉시 날리는 것으로 변경
|
||||
ClearLoginInfo();
|
||||
CAccountConnector & rkAccountConnector = CAccountConnector::Instance();
|
||||
rkAccountConnector.ClearLoginInfo();
|
||||
@@ -208,43 +202,6 @@ bool CPythonNetworkStream::__RecvLoginFailurePacket()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPythonNetworkStream::SendDirectEnterPacket(const char* c_szID, const char* c_szPassword, UINT uChrSlot)
|
||||
{
|
||||
TPacketCGDirectEnter kPacketDirectEnter;
|
||||
kPacketDirectEnter.bHeader=HEADER_CG_DIRECT_ENTER;
|
||||
kPacketDirectEnter.index=uChrSlot;
|
||||
strncpy(kPacketDirectEnter.login, c_szID, ID_MAX_NUM);
|
||||
strncpy(kPacketDirectEnter.passwd, c_szPassword, PASS_MAX_NUM);
|
||||
|
||||
if (!Send(sizeof(kPacketDirectEnter), &kPacketDirectEnter))
|
||||
{
|
||||
Tracen("SendDirectEnter");
|
||||
return false;
|
||||
}
|
||||
|
||||
return SendSequence();
|
||||
}
|
||||
|
||||
bool CPythonNetworkStream::SendLoginPacket(const char* c_szName, const char* c_szPassword)
|
||||
{
|
||||
TPacketCGLogin LoginPacket;
|
||||
LoginPacket.header = HEADER_CG_LOGIN;
|
||||
|
||||
strncpy(LoginPacket.name, c_szName, sizeof(LoginPacket.name)-1);
|
||||
strncpy(LoginPacket.pwd, c_szPassword, sizeof(LoginPacket.pwd)-1);
|
||||
|
||||
LoginPacket.name[ID_MAX_NUM]='\0';
|
||||
LoginPacket.pwd[PASS_MAX_NUM]='\0';
|
||||
|
||||
if (!Send(sizeof(LoginPacket), &LoginPacket))
|
||||
{
|
||||
Tracen("SendLogin Error");
|
||||
return false;
|
||||
}
|
||||
|
||||
return SendSequence();
|
||||
}
|
||||
|
||||
bool CPythonNetworkStream::SendLoginPacketNew(const char * c_szName, const char * c_szPassword)
|
||||
{
|
||||
TPacketCGLogin2 LoginPacket;
|
||||
@@ -254,11 +211,6 @@ bool CPythonNetworkStream::SendLoginPacketNew(const char * c_szName, const char
|
||||
strncpy(LoginPacket.name, c_szName, sizeof(LoginPacket.name)-1);
|
||||
LoginPacket.name[ID_MAX_NUM]='\0';
|
||||
|
||||
extern DWORD g_adwEncryptKey[4];
|
||||
extern DWORD g_adwDecryptKey[4];
|
||||
for (DWORD i = 0; i < 4; ++i)
|
||||
LoginPacket.adwClientKey[i] = g_adwEncryptKey[i];
|
||||
|
||||
if (!Send(sizeof(LoginPacket), &LoginPacket))
|
||||
{
|
||||
Tracen("SendLogin Error");
|
||||
@@ -273,9 +225,6 @@ bool CPythonNetworkStream::SendLoginPacketNew(const char * c_szName, const char
|
||||
|
||||
__SendInternalBuffer();
|
||||
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
SetSecurityMode(true, (const char *) g_adwEncryptKey, (const char *) g_adwDecryptKey);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
#include "PythonNetworkStream.h"
|
||||
#include "Packet.h"
|
||||
|
||||
extern DWORD g_adwEncryptKey[4];
|
||||
extern DWORD g_adwDecryptKey[4];
|
||||
|
||||
// Select Character ---------------------------------------------------------------------------
|
||||
void CPythonNetworkStream::SetSelectPhase()
|
||||
{
|
||||
@@ -15,11 +12,7 @@ void CPythonNetworkStream::SetSelectPhase()
|
||||
Tracen("## Network - Select Phase ##");
|
||||
Tracen("");
|
||||
|
||||
m_strPhase = "Select";
|
||||
|
||||
#ifndef _IMPROVED_PACKET_ENCRYPTION_
|
||||
SetSecurityMode(true, (const char *) g_adwEncryptKey, (const char *) g_adwDecryptKey);
|
||||
#endif
|
||||
m_strPhase = "Select";
|
||||
|
||||
m_dwChangingPhaseTime = ELTimer_GetMSec();
|
||||
m_phaseProcessFunc.Set(this, &CPythonNetworkStream::SelectPhase);
|
||||
@@ -103,29 +96,16 @@ void CPythonNetworkStream::SelectPhase()
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_HYBRIDCRYPT_KEYS:
|
||||
RecvHybridCryptKeyPacket();
|
||||
case HEADER_GC_KEY_CHALLENGE:
|
||||
RecvKeyChallenge();
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_HYBRIDCRYPT_SDB:
|
||||
RecvHybridCryptSDBPacket();
|
||||
case HEADER_GC_KEY_COMPLETE:
|
||||
RecvKeyComplete();
|
||||
return;
|
||||
break;
|
||||
|
||||
|
||||
#ifdef _IMPROVED_PACKET_ENCRYPTION_
|
||||
case HEADER_GC_KEY_AGREEMENT:
|
||||
RecvKeyAgreementPacket();
|
||||
return;
|
||||
break;
|
||||
|
||||
case HEADER_GC_KEY_AGREEMENT_COMPLETED:
|
||||
RecvKeyAgreementCompletedPacket();
|
||||
return;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case HEADER_GC_PLAYER_POINT_CHANGE:
|
||||
TPacketGCPointChange PointChange;
|
||||
Recv(sizeof(TPacketGCPointChange), &PointChange);
|
||||
|
||||
@@ -1,42 +1,5 @@
|
||||
#include "StdAfx.h"
|
||||
#include "PackLib/PackManager.h"
|
||||
#include "EterBase/tea.h"
|
||||
|
||||
// CHINA_CRYPT_KEY
|
||||
DWORD g_adwEncryptKey[4];
|
||||
DWORD g_adwDecryptKey[4];
|
||||
|
||||
#include "AccountConnector.h"
|
||||
|
||||
inline const BYTE* GetKey_20050304Myevan()
|
||||
{
|
||||
volatile static DWORD s_adwKey[1938];
|
||||
|
||||
volatile DWORD seed=1491971513;
|
||||
for (UINT i=0; i<BYTE(seed); i++)
|
||||
{
|
||||
seed^=2148941891;
|
||||
seed+=3592385981;
|
||||
s_adwKey[i]=seed;
|
||||
}
|
||||
|
||||
return (const BYTE*)s_adwKey;
|
||||
}
|
||||
|
||||
//#include <eterCrypt.h>
|
||||
|
||||
void CAccountConnector::__BuildClientKey_20050304Myevan()
|
||||
{
|
||||
const BYTE * c_pszKey = GetKey_20050304Myevan();
|
||||
memcpy(g_adwEncryptKey, c_pszKey+157, 16);
|
||||
|
||||
for (DWORD i = 0; i < 4; ++i)
|
||||
g_adwEncryptKey[i] = random();
|
||||
|
||||
tea_encrypt((DWORD *) g_adwDecryptKey, (const DWORD *) g_adwEncryptKey, (const DWORD *) (c_pszKey+37), 16);
|
||||
// TEA_Encrypt((DWORD *) g_adwDecryptKey, (const DWORD *) g_adwEncryptKey, (const DWORD *) (c_pszKey+37), 16);
|
||||
}
|
||||
// END_OF_CHINA_CRYPT_KEY
|
||||
|
||||
PyObject * packExist(PyObject * poSelf, PyObject * poArgs)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <utf8.h>
|
||||
#include <sodium.h>
|
||||
|
||||
extern "C" {
|
||||
extern int _fltused;
|
||||
@@ -290,6 +291,12 @@ static bool Main(HINSTANCE hInstance, LPSTR lpCmdLine)
|
||||
OpenLogFile(false); // false == uses syserr.txt only
|
||||
#endif
|
||||
|
||||
if (sodium_init() < 0)
|
||||
{
|
||||
LogBox("sodium_init() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
static CLZO lzo;
|
||||
CPackManager packMgr;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user