diff --git a/Feistel.cpp b/Feistel.cpp index 62c220e..ab825ec 100644 --- a/Feistel.cpp +++ b/Feistel.cpp @@ -21,17 +21,17 @@ void Feistel::SetKey(const Block& key) return; } -Block Feistel::Encipher(const Block& data) +Block Feistel::Encipher(const Block& data) const { return Run(data, false); } -Block Feistel::Decipher(const Block& data) +Block Feistel::Decipher(const Block& data) const { return Run(data, true); } -Block Feistel::Run(const Block& data, bool reverseKeys) +Block Feistel::Run(const Block& data, bool reverseKeys) const { const auto splitData = FeistelSplit(data); Halfblock l = splitData.first; @@ -173,6 +173,8 @@ std::string Feistel::SBox(const std::string& in) void Feistel::GenerateRoundKeys(const Block& seedKey) { + // Generate round keys via output feedback modus (OFM) method + // Clear initial key memory ZeroKeyMemory(); roundKeys = Keyset(); @@ -190,7 +192,7 @@ void Feistel::GenerateRoundKeys(const Block& seedKey) } // These pragmas only work for MSVC, as far as i know. Beware!!! -#pragma optimize( "", off ) +#pragma optimize("", off ) void Feistel::ZeroKeyMemory() { for (Block& key : roundKeys) @@ -198,4 +200,4 @@ void Feistel::ZeroKeyMemory() return; } -#pragma optimize( "", on ) +#pragma optimize("", on ) diff --git a/Feistel.h b/Feistel.h index 7b16689..d133131 100644 --- a/Feistel.h +++ b/Feistel.h @@ -8,7 +8,11 @@ class Feistel { public: - Feistel(const Block& key); + explicit Feistel(const Block& key); + + Feistel(const Feistel& other) = delete; + Feistel(Feistel&& other) noexcept = delete; + ~Feistel(); //! Will set the seed-key for this feistel network. @@ -16,14 +20,14 @@ public: void SetKey(const Block& key); //! Will encipher a data block via the set seed-key - Block Encipher(const Block& data); + Block Encipher(const Block& data) const; //! Will decipher a data block via the set seed-key - Block Decipher(const Block& data); + Block Decipher(const Block& data) const; private: //! Will run the feistel rounds, with either regular key order or reversed key order - Block Run(const Block& data, bool reverseKeys); + Block Run(const Block& data, bool reverseKeys) const; //! Arbitrary cipher function static Halfblock F(Halfblock m, const Block& key); diff --git a/Feistel.vcxproj b/Feistel.vcxproj index 6876071..ce3f24a 100644 --- a/Feistel.vcxproj +++ b/Feistel.vcxproj @@ -146,12 +146,15 @@ true + + + diff --git a/Feistel.vcxproj.filters b/Feistel.vcxproj.filters index 7e418d2..dc966f1 100644 --- a/Feistel.vcxproj.filters +++ b/Feistel.vcxproj.filters @@ -24,6 +24,9 @@ Quelldateien + + Quelldateien + @@ -44,5 +47,11 @@ Headerdateien + + Headerdateien + + + Headerdateien + \ No newline at end of file diff --git a/FeistelMan.cpp b/FeistelMan.cpp new file mode 100644 index 0000000..a24631b --- /dev/null +++ b/FeistelMan.cpp @@ -0,0 +1,114 @@ +#include "FeistelMan.h" +#include "Util.h" +#include + +FeistelMan::FeistelMan(const Block& key) + : + key { key } +{ + + return; +} + +FeistelMan::FeistelMan(const std::string& password) +{ + key = PasswordToKey(password); + + return; +} + +FeistelMan::~FeistelMan() +{ + // Clear key memory + ZeroKeyMemory(); + + return; +} + +void FeistelMan::SetKey(const Block& key) +{ + ZeroKeyMemory(); + + this->key = key; + return; +} + +void FeistelMan::SetPassword(const std::string& password) +{ + ZeroKeyMemory(); + + key = PasswordToKey(password); + return; +} + +Flexblock FeistelMan::Encipher(const Flexblock& data) const +{ + // Split cleartext into blocks + std::vector blocks; + + for (std::size_t i = 0; i < data.size(); i += BLOCK_SIZE) + blocks.push_back(Block( + PadStringToLength(data.substr(i, BLOCK_SIZE), BLOCK_SIZE, '0', false)) + ); + + // Encrypt individual blocks using cipher block chaining + Feistel feistel(key); + + for (std::size_t i = 0; i < blocks.size(); i++) + { + const Block& lastBlock = (i>0) ? blocks[i-1] : emptyBlock; + blocks[i] = feistel.Encipher(blocks[i] ^ lastBlock); + } + + // Concatenate ciphertext blocks back into a flexblock + std::stringstream ss; + for (Block& b : blocks) + ss << b; + + // Return it + return ss.str(); +} + +Flexblock FeistelMan::Decipher(const Flexblock& data) const +{ + // Split ciphertext into blocks + std::vector blocks; + + for (std::size_t i = 0; i < data.size(); i += BLOCK_SIZE) + blocks.push_back(Block( + PadStringToLength(data.substr(i, BLOCK_SIZE), BLOCK_SIZE, '0', false)) + ); + + // Decrypt individual blocks + Feistel feistel(key); + + // We can't do this in-loop for decryption, because we are decrypting the blocks in-place. + Block lastBlock = emptyBlock; + + for (std::size_t i = 0; i < blocks.size(); i++) + { + Block tmpCopy = blocks[i]; + + blocks[i] = feistel.Decipher(blocks[i]) ^ lastBlock; + + lastBlock = std::move(tmpCopy); + } + + // Concatenate ciphertext blocks back into a flexblock + std::stringstream ss; + for (Block& b : blocks) + ss << b; + + // Return it + return ss.str(); +} + +#pragma optimize("", off ) +void FeistelMan::ZeroKeyMemory() +{ + key.reset(); + return; +} +#pragma optimize("", on ) + +const Block FeistelMan::emptyBlock; diff --git a/FeistelMan.h b/FeistelMan.h new file mode 100644 index 0000000..ad242ff --- /dev/null +++ b/FeistelMan.h @@ -0,0 +1,38 @@ +#pragma once +#include "Feistel.h" +#include "Flexblock.h" + +/** Class to apply a block cipher to messages of arbitrary length in a distributed manner +*/ +class FeistelMan +{ +public: + explicit FeistelMan(const Block& key); + explicit FeistelMan(const std::string& password); + + FeistelMan(const FeistelMan& other) = delete; + FeistelMan(FeistelMan&& other) noexcept = delete; + + ~FeistelMan(); + + //! Will set the key + void SetKey(const Block& key); + + //! Will set the key from a password + void SetPassword(const std::string& password); + + //! Will encipher a flexblock of data + Flexblock Encipher(const Flexblock& data) const; + + //! Will decipher a flexblock of data + Flexblock Decipher(const Flexblock& data) const; + +private: + Block key; + + //! Will zero the memory used by the key + void ZeroKeyMemory(); + + // Initial value for cipher block chaining + static const Block emptyBlock; +}; diff --git a/Flexblock.h b/Flexblock.h new file mode 100644 index 0000000..66c75e0 --- /dev/null +++ b/Flexblock.h @@ -0,0 +1,5 @@ +#pragma once +#include + +//! A "bitset" of variable length +typedef std::string Flexblock; diff --git a/main.cpp b/main.cpp index 9daa6a4..f054497 100644 --- a/main.cpp +++ b/main.cpp @@ -1,10 +1,27 @@ #pragma once #include #include "Util.h" -#include "Feistel.h" +#include "FeistelMan.h" int main() { + FeistelMan feistel("Password yo"); + + const std::string message = "I am a veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery long message!"; + + std::cout << "Cleartext: " << message << std::endl; + + // Encrypt + const Flexblock ciphertext = feistel.Encipher(StringToBits(message)); + const std::string cipherHex = BitsToHexstring(ciphertext); + + std::cout << "Ciphertext: " << cipherHex << std::endl; + + + // Decrypt + const Flexblock cleartextBits = feistel.Decipher(HexstringToBits(cipherHex)); + std::cout << "Decrypted: " << BitsToString(cleartextBits) << std::endl; + return 0; }