diff --git a/GCryptLib/exec/main.cpp b/GCryptLib/exec/main.cpp index 5f9d3dc..62ecf6f 100644 --- a/GCryptLib/exec/main.cpp +++ b/GCryptLib/exec/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace Leonetienne::GCrypt; @@ -14,11 +15,11 @@ void ExampleString() { std::cout << input << std::endl; // Encrypt - const std::string encrypted = GWrapper::EncryptString(input, "password1"); + const std::string encrypted = GWrapper::EncryptString(input, Key::FromPassword("password1")); std::cout << encrypted << std::endl; // Decrypt - const std::string decrypted = GWrapper::DecryptString(encrypted, "password1"); + const std::string decrypted = GWrapper::DecryptString(encrypted, Key::FromPassword("password1")); std::cout << decrypted << std::endl; return; @@ -28,10 +29,10 @@ void ExampleFiles() { std::cout << "Example on how to encrypt & decrypt any file:" << std::endl; // Encrypt - GWrapper::EncryptFile("main.cpp", "main.cpp.crypt", "password1"); + GWrapper::EncryptFile("main.cpp", "main.cpp.crypt", Key::FromPassword("password1")); // Decrypt - GWrapper::DecryptFile("main.cpp.crypt", "main.cpp.clear", "password1"); + GWrapper::DecryptFile("main.cpp.crypt", "main.cpp.clear", Key::FromPassword("password1")); return; } diff --git a/GCryptLib/include/GCrypt/Feistel.h b/GCryptLib/include/GCrypt/Feistel.h index b6e39bc..9063d0a 100644 --- a/GCryptLib/include/GCrypt/Feistel.h +++ b/GCryptLib/include/GCrypt/Feistel.h @@ -1,6 +1,7 @@ #pragma once #include "GCrypt/Keyset.h" #include "GCrypt/Block.h" +#include "GCrypt/Key.h" #include "GCrypt/Halfblock.h" namespace Leonetienne::GCrypt { @@ -8,7 +9,7 @@ namespace Leonetienne::GCrypt { */ class Feistel { public: - explicit Feistel(const Block& key); + explicit Feistel(const Key& key); Feistel(const Feistel& other) = delete; Feistel(Feistel&& other) noexcept = delete; @@ -17,7 +18,7 @@ namespace Leonetienne::GCrypt { //! Will set the seed-key for this feistel network. //! Roundkeys will be derived from this. - void SetKey(const Block& key); + void SetKey(const Key& key); //! Will encipher a data block via the set seed-key Block Encipher(const Block& data); @@ -31,7 +32,7 @@ namespace Leonetienne::GCrypt { Block Run(const Block& data, bool reverseKeys); //! Arbitrary cipher function - static Halfblock F(Halfblock m, const Block& key); + static Halfblock F(Halfblock m, const Key& key); //! Split a data block into two half blocks (into L and R) static std::pair FeistelSplit(const Block& block); @@ -49,7 +50,7 @@ namespace Leonetienne::GCrypt { static std::string SBox(const std::string& in); //! Will generate a the round keys - void GenerateRoundKeys(const Block& seedKey); + void GenerateRoundKeys(const Key& seedKey); //! Will zero the memory used by the keyset void ZeroKeyMemory(); diff --git a/GCryptLib/include/GCrypt/GCipher.h b/GCryptLib/include/GCrypt/GCipher.h index c4d7120..2764341 100644 --- a/GCryptLib/include/GCrypt/GCipher.h +++ b/GCryptLib/include/GCrypt/GCipher.h @@ -14,22 +14,16 @@ namespace Leonetienne::GCrypt { }; //! Will initialize this cipher with a key - explicit GCipher(const Block& key, const DIRECTION direction); - - //! Will initialize this cipher with a key - explicit GCipher(const std::string& password, const DIRECTION direction); + explicit GCipher(const Key& key, const DIRECTION direction); // Disable copying GCipher(const GCipher& other) = delete; GCipher(GCipher&& other) noexcept = delete; - ~GCipher(); - //! Will digest a data block, and return it Block Digest(const Block& input); private: - Block key; const DIRECTION direction; //! The feistel instance to be used @@ -37,8 +31,5 @@ namespace Leonetienne::GCrypt { //! The last block, required for CBC. Block lastBlock; - - //! Will zero the memory used by the key - void ZeroKeyMemory(); }; } diff --git a/GCryptLib/include/GCrypt/GWrapper.h b/GCryptLib/include/GCrypt/GWrapper.h index edd984b..e10e550 100644 --- a/GCryptLib/include/GCrypt/GWrapper.h +++ b/GCryptLib/include/GCrypt/GWrapper.h @@ -3,6 +3,8 @@ #include "GCrypt/Flexblock.h" #include "GCrypt/Block.h" #include "GCrypt/GCipher.h" +#include "GCrypt/Key.h" + namespace Leonetienne::GCrypt { /** This class is a wrapper to make working with the GhettoCipher @@ -11,25 +13,25 @@ namespace Leonetienne::GCrypt { class GWrapper { public: //! Will encrypt a string and return it hexadecimally encoded. - static std::string EncryptString(const std::string& cleartext, const std::string& password); + static std::string EncryptString(const std::string& cleartext, const Key& key); //! Will decrypt a hexadecimally encoded string. - static std::string DecryptString(const std::string& ciphertext, const std::string& password); + static std::string DecryptString(const std::string& ciphertext, const Key& key); //! Will encrypt a file. //! Returns false if anything goes wrong (like, file-access). //! @filename_in The file to be read. //! @filename_out The file the encrypted version should be saved in. - static bool EncryptFile(const std::string& filename_in, const std::string& filename_out, const std::string& password, bool printProgressReport = false); + static bool EncryptFile(const std::string& filename_in, const std::string& filename_out, const Key& key, bool printProgressReport = false); //! Will decrypt a file. //! Returns false if anything goes wrong (like, file-access). //! @filename_in The file to be read. //! @filename_out The file the decrypted version should be saved in. - static bool DecryptFile(const std::string& filename_in, const std::string& filename_out, const std::string& password, bool printProgressReport = false); + static bool DecryptFile(const std::string& filename_in, const std::string& filename_out, const Key& key, bool printProgressReport = false); //! Will enncrypt or decrypt an entire flexblock of binary data, given a key. - static Flexblock CipherFlexblock(const Flexblock& data, const Block& key, const GCipher::DIRECTION direction); + static Flexblock CipherFlexblock(const Flexblock& data, const Key& key, const GCipher::DIRECTION direction); private: diff --git a/GCryptLib/include/GCrypt/Key.h b/GCryptLib/include/GCrypt/Key.h new file mode 100644 index 0000000..d63dd65 --- /dev/null +++ b/GCryptLib/include/GCrypt/Key.h @@ -0,0 +1,26 @@ +#ifndef GCRYPT_KEY_H +#define GCRYPT_KEY_H +#include "GCrypt/Block.h" +#include + +namespace Leonetienne::GCrypt { + + /* This class represents encryption keys. + You can copy them, create them from data blocks, + or even read from files (to be implemented). + */ + class Key : public Block { + public: + static Key FromPassword(const std::string& password); + Key(); + Key(const Key& k); + Key(const Block& b); + + private: + + }; + +} + +#endif + diff --git a/GCryptLib/include/GCrypt/Keyset.h b/GCryptLib/include/GCrypt/Keyset.h index 4857c37..ab331f6 100644 --- a/GCryptLib/include/GCrypt/Keyset.h +++ b/GCryptLib/include/GCrypt/Keyset.h @@ -1,8 +1,9 @@ #pragma once #include -#include "GCrypt/Block.h" +#include "GCrypt/Key.h" #include "GCrypt/Config.h" namespace Leonetienne::GCrypt { - typedef std::array Keyset; + typedef std::array Keyset; } + diff --git a/GCryptLib/include/GCrypt/Util.h b/GCryptLib/include/GCrypt/Util.h index fc25dcc..05de131 100644 --- a/GCryptLib/include/GCrypt/Util.h +++ b/GCryptLib/include/GCrypt/Util.h @@ -227,9 +227,6 @@ namespace Leonetienne::GCrypt { return ss.str(); } - //! Creates a key of size BLOCK_SIZE from a password of arbitrary length. - Block PasswordToKey(const std::string& in); - //! Will read a file into a flexblock inline Flexblock ReadFileToBits(const std::string& filepath) { // Read file diff --git a/GCryptLib/src/Feistel.cpp b/GCryptLib/src/Feistel.cpp index 167624e..dd14dc4 100644 --- a/GCryptLib/src/Feistel.cpp +++ b/GCryptLib/src/Feistel.cpp @@ -5,7 +5,7 @@ namespace Leonetienne::GCrypt { - Feistel::Feistel(const Block& key) { + Feistel::Feistel(const Key& key) { SetKey(key); return; } @@ -16,7 +16,7 @@ namespace Leonetienne::GCrypt { return; } - void Feistel::SetKey(const Block& key) { + void Feistel::SetKey(const Key& key) { GenerateRoundKeys(key); return; } @@ -59,7 +59,7 @@ namespace Leonetienne::GCrypt { return FeistelCombine(r, l); } - Halfblock Feistel::F(Halfblock m, const Block& key) { + Halfblock Feistel::F(Halfblock m, const Key& key) { // Made-up F function // Expand to full bitwidth @@ -174,7 +174,7 @@ namespace Leonetienne::GCrypt { return subMap[in]; } - void Feistel::GenerateRoundKeys(const Block& seedKey) { + void Feistel::GenerateRoundKeys(const Key& seedKey) { // Clear initial key memory ZeroKeyMemory(); roundKeys = Keyset(); @@ -234,7 +234,7 @@ namespace Leonetienne::GCrypt { Halfblock halfkey1 = F(halfkeys.first, roundKeys[i - 2]); Halfblock halfkey2 = halfkeys.second ^ halfkey1; // I know this is reversible, but it helps to diffuse future round keys. - roundKeys[i] = FeistelCombine(halfkey1, halfkey2); + roundKeys[i] = Key(FeistelCombine(halfkey1, halfkey2)); } return; @@ -248,7 +248,7 @@ namespace Leonetienne::GCrypt { #pragma GCC optimize ("O0") #endif void Feistel::ZeroKeyMemory() { - for (Block& key : roundKeys) { + for (Key& key : roundKeys) { key.reset(); } diff --git a/GCryptLib/src/GCipher.cpp b/GCryptLib/src/GCipher.cpp index 8e30c93..10cebab 100644 --- a/GCryptLib/src/GCipher.cpp +++ b/GCryptLib/src/GCipher.cpp @@ -7,9 +7,8 @@ namespace Leonetienne::GCrypt { - GCipher::GCipher(const Block& key, const DIRECTION direction) + GCipher::GCipher(const Key& key, const DIRECTION direction) : - key { key }, direction { direction }, lastBlock(InitializationVector(key)), // Initialize our lastBlock with some deterministic initial value, based on the key feistel(key) { @@ -17,22 +16,6 @@ namespace Leonetienne::GCrypt { return; } - GCipher::GCipher(const std::string& password, const DIRECTION direction) - : - key { PasswordToKey(password) }, - direction { direction }, - lastBlock(InitializationVector(key)), // Initialize our lastBlock with some deterministic initial value, based on the key feistel(key) { - feistel(key) { - return; - } - - GCipher::~GCipher() { - // Clear key memory - ZeroKeyMemory(); - - return; - } - Block GCipher::Digest(const Block& input) { switch (direction) { @@ -67,23 +50,5 @@ namespace Leonetienne::GCrypt { throw std::runtime_error("Unreachable branch reached."); } - - // These pragmas only work for MSVC and g++, as far as i know. Beware!!! -#if defined _WIN32 || defined _WIN64 -#pragma optimize("", off ) -#elif defined __GNUG__ -#pragma GCC push_options -#pragma GCC optimize ("O0") -#endif - void GCipher::ZeroKeyMemory() { - key.reset(); - return; - } -#if defined _WIN32 || defined _WIN64 -#pragma optimize("", on ) -#elif defined __GNUG__ -#pragma GCC pop_options -#endif - } diff --git a/GCryptLib/src/GHash.cpp b/GCryptLib/src/GHash.cpp index 34864b1..1fcb501 100644 --- a/GCryptLib/src/GHash.cpp +++ b/GCryptLib/src/GHash.cpp @@ -7,7 +7,9 @@ namespace Leonetienne::GCrypt { GHash::GHash() : // Initialize our cipher with a static, but randomly distributed key. cipher( - StringToBitblock("CfRtNdMTP4Y5CWRd"), + // Can't use Key::FromPassword here, because it depends on GHash. + // Instead use a hardcoded key. + Key(StringToBitblock("CfRtNdMTP4Y5CWRd")), GCipher::DIRECTION::ENCIPHER ) { block = InitializationVector(StringToBitblock("3J7IipfQTDJbO8jtasz9PgWui6faPaEMOuVuAqyhB1S2CRcLw5caawewgDUEG1WN")); diff --git a/GCryptLib/src/GWrapper.cpp b/GCryptLib/src/GWrapper.cpp index 386476a..eacc8bb 100644 --- a/GCryptLib/src/GWrapper.cpp +++ b/GCryptLib/src/GWrapper.cpp @@ -4,10 +4,10 @@ namespace Leonetienne::GCrypt { - std::string GWrapper::EncryptString(const std::string& cleartext, const std::string& password) { - // Transform the password to a key - const Block key = PasswordToKey(password); - + std::string GWrapper::EncryptString( + const std::string& cleartext, + const Key& key) + { // Recode the ascii-string to bits const Flexblock cleartext_bits = StringToBits(cleartext); @@ -21,10 +21,10 @@ namespace Leonetienne::GCrypt { return ciphertext; } - std::string GWrapper::DecryptString(const std::string& ciphertext, const std::string& password) { - // Transform the password to a key - const Block key = PasswordToKey(password); - + std::string GWrapper::DecryptString( + const std::string& ciphertext, + const Key& key) + { // Recode the hex-string to bits const Flexblock ciphertext_bits = HexstringToBits(ciphertext); @@ -38,14 +38,16 @@ namespace Leonetienne::GCrypt { return cleartext; } - bool GWrapper::EncryptFile(const std::string& filename_in, const std::string& filename_out, const std::string& password, bool printProgressReport) { + bool GWrapper::EncryptFile( + const std::string& filename_in, + const std::string& filename_out, + const Key& key, + bool printProgressReport) + { try { // Read the file to bits const Flexblock cleartext_bits = ReadFileToBits(filename_in); - // Transform the password to a key - const Block key = PasswordToKey(password); - // Encrypt our cleartext bits const Flexblock ciphertext_bits = CipherFlexblock(cleartext_bits, key, GCipher::DIRECTION::ENCIPHER); @@ -59,14 +61,16 @@ namespace Leonetienne::GCrypt { } } - bool GWrapper::DecryptFile(const std::string& filename_in, const std::string& filename_out, const std::string& password, bool printProgressReport) { + bool GWrapper::DecryptFile( + const std::string& filename_in, + const std::string& filename_out, + const Key& key, + bool printProgressReport) + { try { // Read the file to bits const Flexblock ciphertext_bits = ReadFileToBits(filename_in); - // Transform the password to a key - const Block key = PasswordToKey(password); - // Decrypt the ciphertext bits const Flexblock cleartext_bits = CipherFlexblock(ciphertext_bits, key, GCipher::DIRECTION::DECIPHER); @@ -82,7 +86,7 @@ namespace Leonetienne::GCrypt { Flexblock GWrapper::CipherFlexblock( const Flexblock& data, - const Block& key, + const Key& key, const GCipher::DIRECTION direction) { // Split input into blocks diff --git a/GCryptLib/src/Key.cpp b/GCryptLib/src/Key.cpp new file mode 100644 index 0000000..2bffc67 --- /dev/null +++ b/GCryptLib/src/Key.cpp @@ -0,0 +1,22 @@ +#include "GCrypt/Key.h" +#include "GCrypt/GHash.h" +#include "GCrypt/Util.h" + +namespace Leonetienne::GCrypt { + + Key Key::FromPassword(const std::string& password) { + return GHash::CalculateHashsum( + StringToBits(password) + ); + } + + Key::Key() : Block() { + } + + Key::Key(const Block& b) : Block(b) { + } + + Key::Key(const Key& k) : Block(k) { + } +} + diff --git a/GCryptLib/src/Util.cpp b/GCryptLib/src/Util.cpp index f514451..96e3293 100644 --- a/GCryptLib/src/Util.cpp +++ b/GCryptLib/src/Util.cpp @@ -2,12 +2,5 @@ #include "GCrypt/GHash.h" namespace Leonetienne::GCrypt { - Block PasswordToKey(const std::string& in) { - // We already have a hashing algorithm, so why not use it - // Yeah, this won't work, because it would create an include loop. This method needs to be outsourced to a cpp file.. - - const Block hashedPassword = GHash::CalculateHashsum(StringToBits(in)); - return hashedPassword; - } }