diff --git a/server/src/crypto/cipher.hpp b/server/src/crypto/cipher.hpp index a05674f..dc2ec9a 100644 --- a/server/src/crypto/cipher.hpp +++ b/server/src/crypto/cipher.hpp @@ -1,13 +1,19 @@ #ifndef SOSC_CRYPTO_CIPHER_H #define SOSC_CRYPTO_CIPHER_H +#include "../utils/bigint.hpp" + namespace sosc { namespace cgc { class Cipher { public: private: + const std::string sigma = "expand 32-byte k"; + const std::string tau = "expand 16-byte k"; + std::string key; + std::string state; }; }} diff --git a/server/src/crypto/keyex.cpp b/server/src/crypto/keyex.cpp index 8cc2d17..64bf911 100644 --- a/server/src/crypto/keyex.cpp +++ b/server/src/crypto/keyex.cpp @@ -1,2 +1,52 @@ #include "keyex.hpp" +sosc::cgc::KeyExchange::KeyExchange() { + if(KeyExchange::secret.IsZero()) + KeyExchange::secret = + BigUInt::GenerateRandomPrime(this->key_size_bytes); + + this->modulus = BigUInt::GenerateRandomPrime(this->key_size_bytes); +} + +sosc::Packet sosc::cgc::KeyExchange::GenerateRequest() const { + return Packet(1, { + this->generator.ToString(), + this->modulus.ToString(), + BigUInt::ModPow(this->generator, this->secret, this->modulus); + }); +} + +bool sosc::cgc::KeyExchange::ParseRequest + (const Packet& request, Packet* response) +{ + if(request.GetId() != 1 || request.RegionCount() != 3) + return false; + + BigUInt generator, modulus, public_key; + bool check = generator.Parse(request[0]); + check = check || modulus.Parse(request[1]); + check = check || public_key.Parse(request[2]); + + if(!check) + return false; + + this->private_key = BigUInt::ModPow(public_key, this->secret, modulus); + public_key = BigUInt::ModPow(generator, this->secret, modulus); + *response = Packet(1, { public_key.ToString() }); + + return true; +} + +bool sosc::cgc::KeyExchange::ParseResponse(const Packet& response) { + if(response.GetId() != 1 || response.RegionCount() != 1) + return false; + + BigUInt public_key; + if(!public_key.Parse(response[0])) + return false; + + this->private_key = + BigUInt::ModPow(public_key, this->secret, this->modulus); + + return true; +} diff --git a/server/src/crypto/keyex.hpp b/server/src/crypto/keyex.hpp index c76a8c7..b4708eb 100644 --- a/server/src/crypto/keyex.hpp +++ b/server/src/crypto/keyex.hpp @@ -1,15 +1,35 @@ #ifndef SOSC_CRYPTO_KEYEX_H #define SOSC_CRYPTO_KEYEX_H +#include "../utils/bigint.hpp" +#include "../sock/packet.hpp" + namespace sosc { namespace cgc { class KeyExchange { public: - const int key_size = 512; - const int key_size_bytes = key_size / 8; - const int generator = 2; -private: + KeyExchange(); + Packet GenerateRequest() const; + bool ParseRequest(const Packet& request, Packet* response); + bool ParseResponse(const Packet& response); + + inline bool Succeeded() { + return !this->private_key.IsZero(); + } + + inline const BigUInt& GetPrivateKey() { + return this->private_key; + } +private: + const int key_size = 256; + const int key_size_bytes = key_size / 8; + + const BigUInt generator = BigUInt(2u); + static BigUInt secret; + BigUInt modulus; + + BigUInt private_key; }; }} diff --git a/server/src/sock/packet.cpp b/server/src/sock/packet.cpp index 1fceb3c..e6b4ac6 100644 --- a/server/src/sock/packet.cpp +++ b/server/src/sock/packet.cpp @@ -1,5 +1,14 @@ #include "packet.hpp" +sosc::Packet::Packet() { + this->id = 0; +} + +sosc::Packet::Packet(uint8_t id, std::vector data) { + this->SetId(id); + this->regions = data; +} + bool sosc::Packet::AddRegion(std::string data) { if(this->regions.size() >= 256) return false; diff --git a/server/src/sock/packet.hpp b/server/src/sock/packet.hpp index 75d4ab5..87bc587 100644 --- a/server/src/sock/packet.hpp +++ b/server/src/sock/packet.hpp @@ -18,6 +18,9 @@ namespace sosc { class Packet { public: + Packet(); + Packet(uint8_t id, std::vector data); + bool AddRegion(std::string data); bool AddRegions(std::vector data); diff --git a/server/src/utils/bigint.cpp b/server/src/utils/bigint.cpp index 74d7419..cc7eac2 100644 --- a/server/src/utils/bigint.cpp +++ b/server/src/utils/bigint.cpp @@ -437,6 +437,11 @@ sosc::BigUInt sosc::BigUInt::operator << (const uint64_t& rhs) const { return shifted; } +std::string sosc::BigUInt::ToRawString(uint64_t byte_count) const { + std::string raw(byte_count == 0 ? this->UsedByteCount() : byte_count, 0); + +} + std::string sosc::BigUInt::ToString() const { std::stringstream stream; for(size_t i = this->WordCount() - 1;; --i) { diff --git a/server/src/utils/bigint.hpp b/server/src/utils/bigint.hpp index 8c01171..013766a 100644 --- a/server/src/utils/bigint.hpp +++ b/server/src/utils/bigint.hpp @@ -82,6 +82,7 @@ public: BigUInt operator >> (const uint64_t& rhs) const; BigUInt operator << (const uint64_t& rhs) const; + std::string ToRawString(uint64_t byte_count = 0) const; std::string ToString() const; inline operator std::string () const { return this->ToString();