From 2eb93c064c841dbc7af38633843f450081cc0097 Mon Sep 17 00:00:00 2001 From: Leonetienne Date: Sun, 5 Dec 2021 22:40:36 +0100 Subject: [PATCH] Refactored to feistel class --- Block.h | 5 + Config.h | 4 + Feistel.cpp | 201 +++++++++++++++++++++++++ Feistel.h | 51 +++++++ Feistel.vcxproj | 15 ++ Feistel.vcxproj.filters | 26 ++++ Halfblock.h | 7 + Keyset.h | 6 + Util.h | 78 ++++++++++ all.cpp | 325 ++++++++++++++++++++++++++++++++++++++++ main.cpp | 323 +-------------------------------------- 11 files changed, 722 insertions(+), 319 deletions(-) create mode 100644 Block.h create mode 100644 Config.h create mode 100644 Feistel.cpp create mode 100644 Feistel.h create mode 100644 Halfblock.h create mode 100644 Keyset.h create mode 100644 Util.h create mode 100644 all.cpp diff --git a/Block.h b/Block.h new file mode 100644 index 0000000..eadcd10 --- /dev/null +++ b/Block.h @@ -0,0 +1,5 @@ +#pragma once +#include +#include "Config.h" + +typedef std::bitset Block; diff --git a/Config.h b/Config.h new file mode 100644 index 0000000..db98223 --- /dev/null +++ b/Config.h @@ -0,0 +1,4 @@ +#pragma once + +#define BLOCK_SIZE 128 +#define N_ROUNDS 64 diff --git a/Feistel.cpp b/Feistel.cpp new file mode 100644 index 0000000..62c220e --- /dev/null +++ b/Feistel.cpp @@ -0,0 +1,201 @@ +#include "Feistel.h" +#include "Util.h" +#include "Config.h" + +Feistel::Feistel(const Block& key) +{ + SetKey(key); + return; +} + +Feistel::~Feistel() +{ + ZeroKeyMemory(); + + return; +} + +void Feistel::SetKey(const Block& key) +{ + GenerateRoundKeys(key); + return; +} + +Block Feistel::Encipher(const Block& data) +{ + return Run(data, false); +} + +Block Feistel::Decipher(const Block& data) +{ + return Run(data, true); +} + +Block Feistel::Run(const Block& data, bool reverseKeys) +{ + const auto splitData = FeistelSplit(data); + Halfblock l = splitData.first; + Halfblock r = splitData.second; + + Halfblock tmp; + + for (std::size_t i = 0; i < N_ROUNDS; i++) + { + // Calculate key index + std::size_t keyIndex; + if (reverseKeys) + keyIndex = N_ROUNDS - i - 1; + else + keyIndex = i; + + // Do a feistel round + tmp = r; + r = l ^ F(r, roundKeys[keyIndex]); + l = tmp; + } + + return FeistelCombine(r, l); +} + +Halfblock Feistel::F(Halfblock m, const Block& key) +{ + // Made-up F function + + // Expand to full bitwidth + Block m_expanded = ExpansionFunction(m); + + // Shift to left by 1 + m_expanded = Shiftl(m_expanded, 1); + + // Xor with key + m_expanded ^= key; + + // Non-linearly apply subsitution boxes + std::stringstream ss; + const std::string m_str = m_expanded.to_string(); + + for (std::size_t i = 0; i < m_str.size(); i += 4) + { + ss << SBox(m_str.substr(i, 4)); + } + + m_expanded = Block(ss.str()); + + // Return the compressed version + return CompressionFunction(m_expanded); +} + +std::pair Feistel::FeistelSplit(const Block& block) +{ + const std::string bits = block.to_string(); + + Halfblock l(bits.substr(0, bits.size() / 2)); + Halfblock r(bits.substr(bits.size() / 2)); + + return std::make_pair(l, r); +} + +Block Feistel::FeistelCombine(const Halfblock& l, const Halfblock& r) +{ + return Block(l.to_string() + r.to_string()); +} + +Block Feistel::ExpansionFunction(const Halfblock& block) +{ + std::stringstream ss; + const std::string bits = block.to_string(); + + // We have to double the bits! + for (std::size_t i = 0; i < bits.size(); i += 2) + { + const std::string sub = bits.substr(i, 2); + + if (sub == "00") ss << "1101"; + else if (sub == "01") ss << "1000"; + else if (sub == "10") ss << "0010"; + else if (sub == "11") ss << "0111"; + + } + + return Block(ss.str()); +} + +Halfblock Feistel::CompressionFunction(const Block& block) +{ + std::stringstream ss; + const std::string bits = block.to_string(); + + // We have to double the bits! + for (std::size_t i = 0; i < bits.size(); i += 4) + { + const std::string sub = bits.substr(i, 4); + + if (sub == "0000") ss << "10"; + else if (sub == "0001") ss << "01"; + else if (sub == "0010") ss << "10"; + else if (sub == "0011") ss << "10"; + else if (sub == "0100") ss << "11"; + else if (sub == "0101") ss << "01"; + else if (sub == "0110") ss << "00"; + else if (sub == "0111") ss << "11"; + else if (sub == "1000") ss << "01"; + else if (sub == "1001") ss << "00"; + else if (sub == "1010") ss << "11"; + else if (sub == "1011") ss << "00"; + else if (sub == "1100") ss << "11"; + else if (sub == "1101") ss << "10"; + else if (sub == "1110") ss << "00"; + else if (sub == "1111") ss << "01"; + } + + return Halfblock(ss.str()); +} + +std::string Feistel::SBox(const std::string& in) +{ + if (in == "0000") return "1100"; + else if (in == "0001") return "1000"; + else if (in == "0010") return "0001"; + else if (in == "0011") return "0111"; + else if (in == "0100") return "1011"; + else if (in == "0101") return "0011"; + else if (in == "0110") return "1101"; + else if (in == "0111") return "1111"; + else if (in == "1000") return "0000"; + else if (in == "1001") return "1010"; + else if (in == "1010") return "0100"; + else if (in == "1011") return "1001"; + else if (in == "1100") return "0010"; + else if (in == "1101") return "1110"; + else if (in == "1110") return "0101"; + else /*if (in == "1111")*/ return "0110"; +} + +void Feistel::GenerateRoundKeys(const Block& seedKey) +{ + // Clear initial key memory + ZeroKeyMemory(); + roundKeys = Keyset(); + + // Generate new keys from the seed key + roundKeys[0] = seedKey; + roundKeys[1] = (Shiftl(seedKey, 32) ^ roundKeys[0]); + + for (std::size_t i = 2; i < roundKeys.size(); i++) + { + roundKeys[i] = Shiftl(roundKeys[i - 1], i + 32) ^ roundKeys[i - 2]; + } + + return; +} + +// These pragmas only work for MSVC, as far as i know. Beware!!! +#pragma optimize( "", off ) +void Feistel::ZeroKeyMemory() +{ + for (Block& key : roundKeys) + key.reset(); + + return; +} +#pragma optimize( "", on ) diff --git a/Feistel.h b/Feistel.h new file mode 100644 index 0000000..38f7efa --- /dev/null +++ b/Feistel.h @@ -0,0 +1,51 @@ +#pragma once +#include "Keyset.h" +#include "Block.h" +#include "Halfblock.h" + +class Feistel +{ +public: + Feistel(const Block& key); + ~Feistel(); + + //! Will set the seed-key for this feistel network. + //! Roundkeys will be derived from this. + void SetKey(const Block& key); + + //! Will encipher a data block via the set seed-key + Block Encipher(const Block& data); + + //! Will decipher a data block via the set seed-key + Block Decipher(const Block& data); + +private: + //! Will run the feistel rounds, with either regular key order or reversed key order + Block Run(const Block& data, bool reverseKeys); + + //! Arbitrary cipher function + static Halfblock F(Halfblock m, const Block& key); + + //! Split a data block into two half blocks (into L and R) + static std::pair FeistelSplit(const Block& block); + + //! Combine two half blocks (L and R) into a regular data block + static Block FeistelCombine(const Halfblock& l, const Halfblock& r); + + //! Will expand a halfblock to a fullblock + static Block ExpansionFunction(const Halfblock& block); + + //! Will compress a fullblock to a halfblock + static Halfblock CompressionFunction(const Block& block); + + //! Substitutes four bits by static random others + static std::string SBox(const std::string& in); + + //! Will generate a the round keys + void GenerateRoundKeys(const Block& seedKey); + + //! Will zero the memory used by the keyset + void ZeroKeyMemory(); + + Keyset roundKeys; +}; diff --git a/Feistel.vcxproj b/Feistel.vcxproj index ddc1d1a..6876071 100644 --- a/Feistel.vcxproj +++ b/Feistel.vcxproj @@ -139,8 +139,23 @@ + + true + true + true + true + + + + + + + + + + diff --git a/Feistel.vcxproj.filters b/Feistel.vcxproj.filters index 46d313e..7e418d2 100644 --- a/Feistel.vcxproj.filters +++ b/Feistel.vcxproj.filters @@ -15,8 +15,34 @@ + + Quelldateien + + + Quelldateien + Quelldateien + + + Headerdateien + + + Headerdateien + + + Headerdateien + + + Headerdateien + + + Headerdateien + + + Headerdateien + + \ No newline at end of file diff --git a/Halfblock.h b/Halfblock.h new file mode 100644 index 0000000..fbd2bd8 --- /dev/null +++ b/Halfblock.h @@ -0,0 +1,7 @@ +#pragma once +#include +#include "Config.h" + +#define HALFBLOCK_SIZE (BLOCK_SIZE / 2) + +typedef std::bitset Halfblock; diff --git a/Keyset.h b/Keyset.h new file mode 100644 index 0000000..19a9b11 --- /dev/null +++ b/Keyset.h @@ -0,0 +1,6 @@ +#pragma once +#include +#include "Block.h" +#include "Config.h" + +typedef std::array Keyset; diff --git a/Util.h b/Util.h new file mode 100644 index 0000000..47a988f --- /dev/null +++ b/Util.h @@ -0,0 +1,78 @@ +#pragma once +#include +#include +#include "Block.h" + +//! Mod-operator that works with negative values +inline int Mod(int numerator, int denominator) +{ + return (denominator + (numerator % denominator)) % denominator; +} + +//! Will perform a wrapping left-bitshift on a bitset +template +inline std::bitset Shiftl(const std::bitset& bits, std::size_t amount) +{ + std::stringstream ss; + const std::string bitss = bits.to_string(); + + for (std::size_t i = 0; i < bitss.size(); i++) + ss << bitss[Mod((i + amount), bitss.size())]; + + return std::bitset(ss.str()); +} + +//! Will perform a wrapping right-bitshift on a bitset +template +inline std::bitset Shiftr(const std::bitset& bits, std::size_t amount) +{ + std::stringstream ss; + const std::string bitss = bits.to_string(); + + for (std::size_t i = 0; i < bitss.size(); i++) + ss << bitss[Mod((i - amount), bitss.size())]; + + return std::bitset(ss.str()); +} + +//! Will convert a string to a data block +inline Block StringToBits(const std::string& s) +{ + std::stringstream ss; + + for (std::size_t i = 0; i < s.size(); i++) + ss << std::bitset<8>(s[i]); + + // Pad rest with zeores + for (std::size_t i = s.size() * 8; i < BLOCK_SIZE; i++) + ss << '0'; + + return Block(ss.str()); +} + +//! Will convert a data block to a string +inline std::string BitsToString(const Block& bits) +{ + std::stringstream ss; + + const std::string bitstring = bits.to_string(); + + for (std::size_t i = 0; i < BLOCK_SIZE; i += 8) + { + ss << (char)std::bitset<8>(bitstring.substr(i, 8)).to_ulong(); + } + + return ss.str(); +} + +//! Creates a key of size key-size from a password of arbitrary length. +inline Block PasswordToKey(const std::string& in) +{ + Block b; + + // Segment the password in segments of key-size, and xor them together. + for (std::size_t i = 0; i < in.size(); i += BLOCK_SIZE / 8) + b ^= StringToBits(in.substr(i, BLOCK_SIZE / 8)); + + return b; +} diff --git a/all.cpp b/all.cpp new file mode 100644 index 0000000..0c428ed --- /dev/null +++ b/all.cpp @@ -0,0 +1,325 @@ +#include +#include +#include +#include + +#define BLOCK_SIZE 128 +#define HALFBLOCK_SIZE (BLOCK_SIZE / 2) +#define N_ROUNDS 64 + +typedef std::bitset Block; +typedef std::bitset Halfblock; +typedef std::array Keyset; + +// Will convert a string to a data block +Block StringToBits(const std::string& s); + +// Will convert a data block to a string +std::string BitsToString(const Block& bits); + +// Split a data block into two half blocks (into L and R) +std::pair FeistelSplit(const Block& block); + +// Combine two half blocks (L and R) into a regular data block +Block FeistelCombine(const Halfblock& l, const Halfblock& r); + +// Creates a key of size key-size from a password of arbitrary length. +Block PasswordToKey(const std::string& in); + +// Will generate a keyset from a seed-key +Keyset GenerateRoundkeys(const Block& seedKey); + +// Feistel-cipher +Block Feistel(const Block& data, const Keyset& keys, bool reverseKeyOrder = false); + +// Will expand a halfblock to a fullblock +Block ExpansionFunction(const Halfblock& block); + +// Will compress a fullblock to a halfblock +Halfblock CompressionFunction(const Block& block); + +// Substitutes four bits by static random others +std::string SBox(const std::string& in); + +// Arbitrary cipher function +Halfblock F(Halfblock m, const Block& key); + +template +std::bitset Shiftl(const std::bitset& bits, std::size_t amount); + +template +std::bitset Shiftr(const std::bitset& bits, std::size_t amount); + +std::string DiffusionCheck(const std::string& asciiMessage); + +int Mod(int numerator, int denominator) +{ + return (denominator + (numerator % denominator)) % denominator; +} + + +int main() +{ + const std::string cipher1 = DiffusionCheck("Hello, World :3"); + + std::cout << std::endl; + + const std::string cipher2 = DiffusionCheck("Hello, world :3"); + + std::size_t numDiff = 0; + for (std::size_t i = 0; i < cipher1.size(); i++) + if (cipher1[i] != cipher2[i]) + numDiff++; + std::cout << std::endl; + std::cout << "Total difference between C1 and C2: " << numDiff << std::endl; + + return 0; +} + +std::string DiffusionCheck(const std::string& asciiMessage) +{ + Block message = StringToBits(asciiMessage); + + const Block seedKey = PasswordToKey("Ich bin ein PASSWORT-SCHLÜSSEL!"); + Keyset roundkeys = GenerateRoundkeys(seedKey); + + //std::cout << "Keys: " << std::endl; + //for (std::size_t i = 0; i < roundkeys.size(); i++) + // std::cout << roundkeys[i] << std::endl; + //std::cout << "---" << std::endl; + //exit(0); + + + std::cout << "Message ascii: " << asciiMessage << std::endl; + + std::cout << "Message: " << message << std::endl; + + Block ciphertext = Feistel(message, roundkeys); + std::cout << "Ciphertext: " << ciphertext << std::endl; + + Block decrypted = Feistel(ciphertext, roundkeys, true); + std::cout << "Decrypted: " << decrypted << std::endl; + + const std::string asciiDecrypted = BitsToString(decrypted); + std::cout << "Decrypted ascii: " << asciiDecrypted << std::endl; + + return ciphertext.to_string(); +} + +Block Feistel(const Block& data, const Keyset& keys, bool reverseKeyOrder) +{ + const auto splitData = FeistelSplit(data); + Halfblock l = splitData.first; + Halfblock r = splitData.second; + + Halfblock tmp; + + for (std::size_t i = 0; i < N_ROUNDS; i++) + { + // Calculate key index + std::size_t keyIndex; + if (reverseKeyOrder) + keyIndex = N_ROUNDS - i - 1; + else + keyIndex = i; + + // Do a feistel round + tmp = r; + r = l ^ F(r, keys[keyIndex]); + l = tmp; + } + + return FeistelCombine(r, l); +} + +Halfblock F(Halfblock m, const Block& key) +{ + // Made-up F function + + // Expand to full bitwidht + Block m_expanded = ExpansionFunction(m); + + // Shift to left by 1 + m_expanded = Shiftl(m_expanded, 1); + + // Xor with key + m_expanded ^= key; + + // Non-linearly apply subsitution boxes + std::stringstream ss; + const std::string m_str = m_expanded.to_string(); + + for (std::size_t i = 0; i < m_str.size(); i += 4) + { + ss << SBox(m_str.substr(i, 4)); + } + + m_expanded = Block(ss.str()); + + // Return the compressed version + return CompressionFunction(m_expanded); +} + +Block ExpansionFunction(const Halfblock& block) +{ + std::stringstream ss; + const std::string bits = block.to_string(); + + // We have to double the bits! + for (std::size_t i = 0; i < bits.size(); i += 2) + { + const std::string sub = bits.substr(i, 2); + + if (sub == "00") ss << "1101"; + else if (sub == "01") ss << "1000"; + else if (sub == "10") ss << "0010"; + else /*if (sub == "11")*/ ss << "0111"; + + } + + return Block(ss.str()); +} + +Halfblock CompressionFunction(const Block& block) +{ + std::stringstream ss; + const std::string bits = block.to_string(); + + // We have to double the bits! + for (std::size_t i = 0; i < bits.size(); i += 4) + { + const std::string sub = bits.substr(i, 4); + + if (sub == "0000") ss << "10"; + else if (sub == "0001") ss << "01"; + else if (sub == "0010") ss << "10"; + else if (sub == "0011") ss << "10"; + else if (sub == "0100") ss << "11"; + else if (sub == "0101") ss << "01"; + else if (sub == "0110") ss << "00"; + else if (sub == "0111") ss << "11"; + else if (sub == "1000") ss << "01"; + else if (sub == "1001") ss << "00"; + else if (sub == "1010") ss << "11"; + else if (sub == "1011") ss << "00"; + else if (sub == "1100") ss << "11"; + else if (sub == "1101") ss << "10"; + else if (sub == "1110") ss << "00"; + else /*if (sub == "1111")*/ ss << "01"; + } + + return Halfblock(ss.str()); +} + +std::string SBox(const std::string& in) +{ + if (in == "0000") return "1100"; + else if (in == "0001") return "1000"; + else if (in == "0010") return "0001"; + else if (in == "0011") return "0111"; + else if (in == "0100") return "1011"; + else if (in == "0101") return "0011"; + else if (in == "0110") return "1101"; + else if (in == "0111") return "1111"; + else if (in == "1000") return "0000"; + else if (in == "1001") return "1010"; + else if (in == "1010") return "0100"; + else if (in == "1011") return "1001"; + else if (in == "1100") return "0010"; + else if (in == "1101") return "1110"; + else if (in == "1110") return "0101"; + else /*if (in == "1111")*/ return "0110"; +} + +Block StringToBits(const std::string& s) +{ + std::stringstream ss; + + for (std::size_t i = 0; i < s.size(); i++) + ss << std::bitset<8>(s[i]); + + // Pad rest with zeores + for (std::size_t i = s.size() * 8; i < BLOCK_SIZE; i++) + ss << '0'; + + return Block(ss.str()); +} + +std::string BitsToString(const Block& bits) +{ + std::stringstream ss; + + const std::string bitstring = bits.to_string(); + + for (std::size_t i = 0; i < BLOCK_SIZE; i += 8) + { + ss << (char)std::bitset<8>(bitstring.substr(i, 8)).to_ulong(); + } + + return ss.str(); +} + +std::pair FeistelSplit(const Block& block) +{ + const std::string bits = block.to_string(); + + Halfblock l(bits.substr(0, bits.size() / 2)); + Halfblock r(bits.substr(bits.size() / 2)); + + return std::make_pair(l, r); +} + +Block FeistelCombine(const Halfblock& l, const Halfblock& r) +{ + return Block(l.to_string() + r.to_string()); +} + +Keyset GenerateRoundkeys(const Block& seedKey) +{ + Keyset keys; + + keys[0] = seedKey; + keys[1] = (Shiftl(seedKey, 32) ^ keys[0]); + + for (std::size_t i = 2; i < keys.size(); i++) + { + keys[i] = Shiftl(keys[i-1], i + 32) ^ keys[i-2]; + } + + return keys; +} + +template +std::bitset Shiftl(const std::bitset& bits, std::size_t amount) +{ + std::stringstream ss; + const std::string bitss = bits.to_string(); + + for (std::size_t i = 0; i < bitss.size(); i++) + ss << bitss[Mod((i + amount), bitss.size())]; + + return std::bitset(ss.str()); +} + +template +std::bitset Shiftr(const std::bitset& bits, std::size_t amount) +{ + std::stringstream ss; + const std::string bitss = bits.to_string(); + + for (std::size_t i = 0; i < bitss.size(); i++) + ss << bitss[Mod((i - amount), bitss.size())]; + + return std::bitset(ss.str()); +} + +Block PasswordToKey(const std::string& in) +{ + Block b; + + // Segment the password in segments of key-size, and xor them together. + for (std::size_t i = 0; i < in.size(); i += BLOCK_SIZE / 8) + b ^= StringToBits(in.substr(i, BLOCK_SIZE / 8)); + + return b; +} diff --git a/main.cpp b/main.cpp index e171a21..9daa6a4 100644 --- a/main.cpp +++ b/main.cpp @@ -1,325 +1,10 @@ +#pragma once #include -#include -#include -#include - -#define BLOCK_SIZE 128 -#define HALFBLOCK_SIZE (BLOCK_SIZE / 2) -#define N_ROUNDS 128 - -typedef std::bitset Block; -typedef std::bitset Halfblock; -typedef std::array Keyset; - -// Will convert a string to a data block -Block StringToBits(const std::string& s); - -// Will convert a data block to a string -std::string BitsToString(const Block& bits); - -// Split a data block into two half blocks (into L and R) -std::pair FeistelSplit(const Block& block); - -// Combine two half blocks (L and R) into a regular data block -Block FeistelCombine(const Halfblock& l, const Halfblock& r); - -// Creates a key of size key-size from a password of arbitrary length. -Block PasswordToKey(const std::string& in); - -// Will generate a keyset from a seed-key -Keyset GenerateRoundkeys(const Block& seedKey); - -// Feistel-cipher -Block Feistel(const Block& data, const Keyset& keys, bool reverseKeyOrder = false); - -// Will expand a halfblock to a fullblock -Block ExpansionFunction(const Halfblock& block); - -// Will compress a fullblock to a halfblock -Halfblock CompressionFunction(const Block& block); - -// Substitutes four bits by static random others -std::string SBox(const std::string& in); - -// Arbitrary cipher function -Halfblock F(Halfblock m, const Block& key); - -template -std::bitset Shiftl(const std::bitset& bits, std::size_t amount); - -template -std::bitset Shiftr(const std::bitset& bits, std::size_t amount); - -std::string DiffusionCheck(const std::string& asciiMessage); - -int Mod(int numerator, int denominator) -{ - return (denominator + (numerator % denominator)) % denominator; -} - +#include "Util.h" +#include "Feistel.h" int main() { - const std::string cipher1 = DiffusionCheck("Hello, World :3"); - - std::cout << std::endl; - const std::string cipher2 = DiffusionCheck("Hello, world :3"); - - std::size_t numDiff = 0; - for (std::size_t i = 0; i < cipher1.size(); i++) - if (cipher1[i] != cipher2[i]) - numDiff++; - std::cout << std::endl; - std::cout << "Total difference between C1 and C2: " << numDiff << std::endl; - - return 0; -} - -std::string DiffusionCheck(const std::string& asciiMessage) -{ - Block message = StringToBits(asciiMessage); - - const Block seedKey = PasswordToKey("Ich bin ein PASSWORT-SCHLÜSSEL!"); - Keyset roundkeys = GenerateRoundkeys(seedKey); - - //std::cout << "Keys: " << std::endl; - //for (std::size_t i = 0; i < roundkeys.size(); i++) - // std::cout << roundkeys[i] << std::endl; - //std::cout << "---" << std::endl; - //exit(0); - - - std::cout << "Message ascii: " << asciiMessage << std::endl; - - std::cout << "Message: " << message << std::endl; - - Block ciphertext = Feistel(message, roundkeys); - std::cout << "Ciphertext: " << ciphertext << std::endl; - - Block decrypted = Feistel(ciphertext, roundkeys, true); - std::cout << "Decrypted: " << decrypted << std::endl; - - const std::string asciiDecrypted = BitsToString(decrypted); - std::cout << "Decrypted ascii: " << asciiDecrypted << std::endl; - - return ciphertext.to_string(); -} - -Block Feistel(const Block& data, const Keyset& keys, bool reverseKeyOrder) -{ - const auto splitData = FeistelSplit(data); - Halfblock l = splitData.first; - Halfblock r = splitData.second; - - Halfblock tmp; - - for (std::size_t i = 0; i < N_ROUNDS; i++) - { - // Calculate key index - std::size_t keyIndex; - if (reverseKeyOrder) - keyIndex = N_ROUNDS - i - 1; - else - keyIndex = i; - - // Do a feistel round - tmp = r; - r = l ^ F(r, keys[keyIndex]); - l = tmp; - } - - return FeistelCombine(r, l); -} - -Halfblock F(Halfblock m, const Block& key) -{ - // Made-up F function - - // Expand to full bitwidht - Block m_expanded = ExpansionFunction(m); - - // Shift to left by 1 - m_expanded = Shiftl(m_expanded, 1); - - // Xor with key - m_expanded ^= key; - - // Non-linearly apply subsitution boxes - std::stringstream ss; - const std::string m_str = m_expanded.to_string(); - - for (std::size_t i = 0; i < m_str.size(); i += 4) - { - ss << SBox(m_str.substr(i, 4)); - } - - m_expanded = Block(ss.str()); - - // Return the compressed version - return CompressionFunction(m_expanded); -} - -Block ExpansionFunction(const Halfblock& block) -{ - std::stringstream ss; - const std::string bits = block.to_string(); - - // We have to double the bits! - for (std::size_t i = 0; i < bits.size(); i += 2) - { - const std::string sub = bits.substr(i, 2); - - if (sub == "00") ss << "1101"; - else if (sub == "01") ss << "1000"; - else if (sub == "10") ss << "0010"; - else /*if (sub == "11")*/ ss << "0111"; - - } - - return Block(ss.str()); -} - -Halfblock CompressionFunction(const Block& block) -{ - std::stringstream ss; - const std::string bits = block.to_string(); - - // We have to double the bits! - for (std::size_t i = 0; i < bits.size(); i += 4) - { - const std::string sub = bits.substr(i, 4); - - if (sub == "0000") ss << "10"; - else if (sub == "0001") ss << "01"; - else if (sub == "0010") ss << "10"; - else if (sub == "0011") ss << "10"; - else if (sub == "0100") ss << "11"; - else if (sub == "0101") ss << "01"; - else if (sub == "0110") ss << "00"; - else if (sub == "0111") ss << "11"; - else if (sub == "1000") ss << "01"; - else if (sub == "1001") ss << "00"; - else if (sub == "1010") ss << "11"; - else if (sub == "1011") ss << "00"; - else if (sub == "1100") ss << "11"; - else if (sub == "1101") ss << "10"; - else if (sub == "1110") ss << "00"; - else /*if (sub == "1111")*/ ss << "01"; - } - - return Halfblock(ss.str()); -} - -std::string SBox(const std::string& in) -{ - if (in == "0000") return "1100"; - else if (in == "0001") return "1000"; - else if (in == "0010") return "0001"; - else if (in == "0011") return "0111"; - else if (in == "0100") return "1011"; - else if (in == "0101") return "0011"; - else if (in == "0110") return "1101"; - else if (in == "0111") return "1111"; - else if (in == "1000") return "0000"; - else if (in == "1001") return "1010"; - else if (in == "1010") return "0100"; - else if (in == "1011") return "1001"; - else if (in == "1100") return "0010"; - else if (in == "1101") return "1110"; - else if (in == "1110") return "0101"; - else /*if (in == "1111")*/ return "0110"; -} - -Block StringToBits(const std::string& s) -{ - std::stringstream ss; - - for (std::size_t i = 0; i < s.size(); i++) - ss << std::bitset<8>(s[i]); - - // Pad rest with zeores - for (std::size_t i = s.size() * 8; i < BLOCK_SIZE; i++) - ss << '0'; - - return Block(ss.str()); -} - -std::string BitsToString(const Block& bits) -{ - std::stringstream ss; - - const std::string bitstring = bits.to_string(); - - for (std::size_t i = 0; i < BLOCK_SIZE; i += 8) - { - ss << (char)std::bitset<8>(bitstring.substr(i, 8)).to_ulong(); - } - - return ss.str(); -} - -std::pair FeistelSplit(const Block& block) -{ - const std::string bits = block.to_string(); - - Halfblock l(bits.substr(0, bits.size() / 2)); - Halfblock r(bits.substr(bits.size() / 2)); - - return std::make_pair(l, r); -} - -Block FeistelCombine(const Halfblock& l, const Halfblock& r) -{ - return Block(l.to_string() + r.to_string()); -} - -Keyset GenerateRoundkeys(const Block& seedKey) -{ - Keyset keys; - - keys[0] = seedKey; - keys[1] = (Shiftl(seedKey, 32) ^ keys[0]); - - for (std::size_t i = 2; i < keys.size(); i++) - { - keys[i] = Shiftl(keys[i-1], i + 32) ^ keys[i-2]; - } - - return keys; -} - -template -std::bitset Shiftl(const std::bitset& bits, std::size_t amount) -{ - std::stringstream ss; - const std::string bitss = bits.to_string(); - - for (std::size_t i = 0; i < bitss.size(); i++) - ss << bitss[Mod((i + amount), bitss.size())]; - - return std::bitset(ss.str()); -} - -template -std::bitset Shiftr(const std::bitset& bits, std::size_t amount) -{ - std::stringstream ss; - const std::string bitss = bits.to_string(); - - for (std::size_t i = 0; i < bitss.size(); i++) - ss << bitss[Mod((i - amount), bitss.size())]; - - return std::bitset(ss.str()); -} - -Block PasswordToKey(const std::string& in) -{ - Block b; - - // Segment the password in segments of key-size, and xor them together. - for (std::size_t i = 0; i < in.size(); i += BLOCK_SIZE / 8) - b ^= StringToBits(in.substr(i, BLOCK_SIZE / 8)); - - return b; + return 0; }