diff --git a/server/src/crypto/cipher.cpp b/server/src/crypto/cipher.cpp index c1bb66a..3d85299 100644 --- a/server/src/crypto/cipher.cpp +++ b/server/src/crypto/cipher.cpp @@ -1 +1,45 @@ #include "cipher.hpp" + +template +static void _swap(T& a, T& b) { + T tmp = a; + a = b; + b = tmp; +} + +sosc::cgc::Cipher::Cipher(const KeyExchange& key) { + std::string key_raw + = key.GetPrivateKey().ToRawString(key.key_size_bytes); + + this->state = std::string(256, 0); + for(int i = 0; i < this->state_size; ++i) + this->state[i] = i; + + int i = 0, j = 0; + for(i = 0; i < this->state_size; ++i) + j = (j + this->state[i] + key_raw[i % key_raw.length()]) % 256; + + GenerateStream(1024); +} + +void sosc::cgc::Cipher::Parse(std::string* data) { + std::string stream = this->GenerateStream(data->length()); + for(std::string::size_type i = 0; i < data->length(); ++i) + (*data)[i] ^= stream[i]; +} + +std::string sosc::cgc::Cipher::GenerateStream(uint64_t length) { + std::string stream(length, 0); + int i = 0, j = 0; + + for(uint64_t x = 0; x < length; ++x) { + i = (i + 1) % 256; + j = (j + this->state[i]) % 256; + _swap(this->state[i], this->state[j]); + + stream[x] = + this->state[(this->state[i] + this->state[j]) % 256]; + } + + return stream; +} diff --git a/server/src/crypto/cipher.hpp b/server/src/crypto/cipher.hpp index dc2ec9a..99d1a81 100644 --- a/server/src/crypto/cipher.hpp +++ b/server/src/crypto/cipher.hpp @@ -2,17 +2,19 @@ #define SOSC_CRYPTO_CIPHER_H #include "../utils/bigint.hpp" +#include "keyex.hpp" namespace sosc { namespace cgc { class Cipher { public: + Cipher(const KeyExchange& key); + void Parse(std::string* data); private: - const std::string sigma = "expand 32-byte k"; - const std::string tau = "expand 16-byte k"; + std::string GenerateStream(uint64_t length); - std::string key; + const int state_size = 256; std::string state; }; }} diff --git a/server/src/crypto/keyex.hpp b/server/src/crypto/keyex.hpp index b4708eb..bbed485 100644 --- a/server/src/crypto/keyex.hpp +++ b/server/src/crypto/keyex.hpp @@ -14,17 +14,17 @@ public: bool ParseRequest(const Packet& request, Packet* response); bool ParseResponse(const Packet& response); - inline bool Succeeded() { + inline bool Succeeded() const { return !this->private_key.IsZero(); } - inline const BigUInt& GetPrivateKey() { + inline const BigUInt& GetPrivateKey() const { return this->private_key; } -private: - const int key_size = 256; - const int key_size_bytes = key_size / 8; + const int key_size = 512; + const int key_size_bytes = key_size / 8; +private: const BigUInt generator = BigUInt(2u); static BigUInt secret; BigUInt modulus; diff --git a/server/src/utils/bigint.cpp b/server/src/utils/bigint.cpp index cc7eac2..0983f3d 100644 --- a/server/src/utils/bigint.cpp +++ b/server/src/utils/bigint.cpp @@ -438,8 +438,14 @@ sosc::BigUInt sosc::BigUInt::operator << (const uint64_t& rhs) const { } std::string sosc::BigUInt::ToRawString(uint64_t byte_count) const { - std::string raw(byte_count == 0 ? this->UsedByteCount() : byte_count, 0); + uint64_t used_bytes = this->UsedByteCount(); + byte_count = byte_count == 0 ? used_bytes : byte_count; + std::string raw(byte_count, 0); + for(uint64_t i = 0; i < std::min(byte_count, used_bytes); ++i) + raw[i] = (this->value[i / 4] >> (8 * (i % 4))) & 0xFF; + + return raw; } std::string sosc::BigUInt::ToString() const {