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; }