diff --git a/ExampleApp/main.cpp b/ExampleApp/main.cpp index 43ce13f..382fd3c 100644 --- a/ExampleApp/main.cpp +++ b/ExampleApp/main.cpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include using namespace GhettoCipher; diff --git a/GhettoCrypt/GhettoCipherWrapper.cpp b/GhettoCrypt/GhettoCryptWrapper.cpp similarity index 95% rename from GhettoCrypt/GhettoCipherWrapper.cpp rename to GhettoCrypt/GhettoCryptWrapper.cpp index b40e6c2..6821782 100644 --- a/GhettoCrypt/GhettoCipherWrapper.cpp +++ b/GhettoCrypt/GhettoCryptWrapper.cpp @@ -1,4 +1,4 @@ -#include "GhettoCipherWrapper.h" +#include "GhettoCryptWrapper.h" #include "Cipher.h" #include "Util.h" diff --git a/GhettoCrypt/GhettoCipherWrapper.h b/GhettoCrypt/GhettoCryptWrapper.h similarity index 100% rename from GhettoCrypt/GhettoCipherWrapper.h rename to GhettoCrypt/GhettoCryptWrapper.h diff --git a/INCLUDE/GhettoCipher.cpp b/INCLUDE/GhettoCipher.cpp deleted file mode 100644 index 045a5f7..0000000 --- a/INCLUDE/GhettoCipher.cpp +++ /dev/null @@ -1,453 +0,0 @@ -/* -* BSD 2-Clause License -* -* Copyright (c) 2021, Leon Etienne -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "GhettoCipher.h" - -/*** ./../GhettoCrypt/Cipher.cpp ***/ - -#include - -GhettoCipher::Cipher::Cipher(const Block& key) - : - key { key } -{ - - return; -} - -GhettoCipher::Cipher::Cipher(const std::string& password) -{ - key = PasswordToKey(password); - - return; -} - -GhettoCipher::Cipher::~Cipher() -{ - // Clear key memory - ZeroKeyMemory(); - - return; -} - -void GhettoCipher::Cipher::SetKey(const Block& key) -{ - ZeroKeyMemory(); - - this->key = key; - return; -} - -void GhettoCipher::Cipher::SetPassword(const std::string& password) -{ - ZeroKeyMemory(); - - key = PasswordToKey(password); - return; -} - -GhettoCipher::Flexblock GhettoCipher::Cipher::Encipher(const Flexblock& data, bool printProgress) 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++) - { - // Print reports if desired. If we have > 1000 blocks, print one report every 100 blocks. Otherwise for every 10th block. - if ((i % ((blocks.size() > 1000)? 100 : 10) == 0) && (printProgress)) - std::cout << "Encrypting... (Block " << i << " / " << blocks.size() << " - " << ((float)i*100 / blocks.size()) << "%)" << std::endl; - - 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(); -} - -GhettoCipher::Flexblock GhettoCipher::Cipher::Decipher(const Flexblock& data, bool printProgress) 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++) - { - // Print reports if desired. If we have > 1000 blocks, print one report every 100 blocks. Otherwise for every 10th block. - if ((i % ((blocks.size() > 1000) ? 100 : 10) == 0) && (printProgress)) - std::cout << "Decrypting... (Block " << i << " / " << blocks.size() << " - " << ((float)i*100/ blocks.size()) << "%)" << std::endl; - - 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(); -} - -#if defined _WIN32 || defined _WIN64 -#pragma optimize("", off ) -#endif -void GhettoCipher::Cipher::ZeroKeyMemory() -{ - key.reset(); - return; -} -#if defined _WIN32 || defined _WIN64 -#pragma optimize("", on ) -#endif - -const GhettoCipher::Block GhettoCipher::Cipher::emptyBlock; - - -/*** ./../GhettoCrypt/Feistel.cpp ***/ - - -GhettoCipher::Feistel::Feistel(const Block& key) -{ - SetKey(key); - return; -} - -GhettoCipher::Feistel::~Feistel() -{ - ZeroKeyMemory(); - - return; -} - -void GhettoCipher::Feistel::SetKey(const Block& key) -{ - GenerateRoundKeys(key); - return; -} - -GhettoCipher::Block GhettoCipher::Feistel::Encipher(const Block& data) const -{ - return Run(data, false); -} - -GhettoCipher::Block GhettoCipher::Feistel::Decipher(const Block& data) const -{ - return Run(data, true); -} - -GhettoCipher::Block GhettoCipher::Feistel::Run(const Block& data, bool reverseKeys) const -{ - const auto splitData = FeistelSplit(data); - GhettoCipher::Halfblock l = splitData.first; - GhettoCipher::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); -} - -GhettoCipher::Halfblock GhettoCipher::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 GhettoCipher::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); -} - -GhettoCipher::Block GhettoCipher::Feistel::FeistelCombine(const Halfblock& l, const Halfblock& r) -{ - return Block(l.to_string() + r.to_string()); -} - -GhettoCipher::Block GhettoCipher::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()); -} - -GhettoCipher::Halfblock GhettoCipher::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 GhettoCipher::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 GhettoCipher::Feistel::GenerateRoundKeys(const Block& seedKey) -{ - // Generate round keys via output feedback modus (OFM) method - - // 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!!! -#if defined _WIN32 || defined _WIN64 -#pragma optimize("", off ) -#endif -void GhettoCipher::Feistel::ZeroKeyMemory() -{ - for (Block& key : roundKeys) - key.reset(); - - return; -} -#if defined _WIN32 || defined _WIN64 -#pragma optimize("", on ) -#endif - - -/*** ./../GhettoCrypt/GhettoCipherWrapper.cpp ***/ - - -std::string GhettoCipher::GhettoCryptWrapper::EncryptString(const std::string& cleartext, const std::string& password) -{ - // Instanciate our cipher and supply a key - Cipher cipher(password); - - // Recode the ascii-string to bits - const Flexblock cleartext_bits = StringToBits(cleartext); - - // Encrypt our cleartext bits - const Flexblock ciphertext_bits = cipher.Encipher(cleartext_bits); - - // Recode the ciphertext bits to a hex-string - const std::string ciphertext = BitsToHexstring(ciphertext_bits); - - // Return it - return ciphertext; -} - -std::string GhettoCipher::GhettoCryptWrapper::DecryptString(const std::string& ciphertext, const std::string& password) -{ - // Instanciate our cipher and supply a key - Cipher cipher(password); - - // Recode the hex-string to bits - const Flexblock ciphertext_bits = HexstringToBits(ciphertext); - - // Decrypt the ciphertext bits - const std::string cleartext_bits = cipher.Decipher(ciphertext_bits); - - // Recode the cleartext bits to an ascii-string - const std::string cleartext = BitsToString(cleartext_bits); - - // Return it - return cleartext; -} - -bool GhettoCipher::GhettoCryptWrapper::EncryptFile(const std::string& filename_in, const std::string& filename_out, const std::string& password) -{ - try - { - // Read the file to bits - const Flexblock cleartext_bits = ReadFileToBits(filename_in); - - // Instanciate our cipher and supply a key - Cipher cipher(password); - - // Encrypt our cleartext bits - const Flexblock ciphertext_bits = cipher.Encipher(cleartext_bits); - - // Write our ciphertext bits to file - WriteBitsToFile(filename_out, ciphertext_bits); - - return true; - } - catch (std::runtime_error&) - { - return false; - } -} - -bool GhettoCipher::GhettoCryptWrapper::DecryptFile(const std::string& filename_in, const std::string& filename_out, const std::string& password) -{ - try - { - // Read the file to bits - const Flexblock ciphertext_bits = ReadFileToBits(filename_in); - - // Instanciate our cipher and supply a key - Cipher cipher(password); - - // Decrypt the ciphertext bits - const Flexblock cleartext_bits = cipher.Decipher(ciphertext_bits); - - // Write our cleartext bits to file - WriteBitsToFile(filename_out, cleartext_bits); - - return true; - } - catch (std::runtime_error&) - { - return false; - } -} - diff --git a/INCLUDE/GhettoCipher.h b/INCLUDE/GhettoCipher.h deleted file mode 100644 index eda0227..0000000 --- a/INCLUDE/GhettoCipher.h +++ /dev/null @@ -1,475 +0,0 @@ -/* -* BSD 2-Clause License -* -* Copyright (c) 2021, Leon Etienne -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* 1. Redistributions of source code must retain the above copyright notice, this -* list of conditions and the following disclaimer. -* -* 2. Redistributions in binary form must reproduce the above copyright notice, -* this list of conditions and the following disclaimer in the documentation -* and/or other materials provided with the distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -/*** ./../GhettoCrypt/GhettoCipherWrapper.h ***/ - -#pragma once -#include - -namespace GhettoCipher -{ - /** This class is a wrapper to make working with the GhettoCipher super easy with a python-like syntax - */ - class GhettoCryptWrapper - { - public: - //! Will encrypt a string and return it hexadecimally encoded. - static std::string EncryptString(const std::string& cleartext, const std::string& password); - - //! Will decrypt a hexadecimally encoded string. - static std::string DecryptString(const std::string& ciphertext, const std::string& password); - - //! 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); - - //! 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); - - private: - // No instanciation! >:( - GhettoCryptWrapper(); - }; -} - -/*** ./../GhettoCrypt/Flexblock.h ***/ - -#pragma once -#include - -namespace GhettoCipher -{ - //! A "bitset" of variable length - typedef std::string Flexblock; -} - -/*** ./../GhettoCrypt/Config.h ***/ - -#pragma once - -namespace GhettoCipher -{ - constexpr int BLOCK_SIZE = 128; - constexpr int N_ROUNDS = 64; -} - -/*** ./../GhettoCrypt/Halfblock.h ***/ - -#pragma once -#include - -namespace GhettoCipher -{ - constexpr int HALFBLOCK_SIZE = (BLOCK_SIZE / 2); - typedef std::bitset Halfblock; -} - -/*** ./../GhettoCrypt/Block.h ***/ - -#pragma once -#include - -namespace GhettoCipher -{ - typedef std::bitset Block; -} - -/*** ./../GhettoCrypt/Util.h ***/ - -#pragma once -#include -#include -#include - -namespace GhettoCipher -{ - //! 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()); - } - - inline std::string PadStringToLength(const std::string& str, const std::size_t len, const char pad, const bool padLeft = true) - { - // Fast-reject: Already above padded length - if (str.length() >= len) - return str; - - std::stringstream ss; - - // Pad left: - if (padLeft) - { - for (std::size_t i = 0; i < len - str.size(); i++) - ss << pad; - ss << str; - } - // Pad right: - else - { - ss << str; - for (std::size_t i = 0; i < len - str.size(); i++) - ss << pad; - } - - return ss.str(); - } - - //! Will convert a string to a fixed data block - inline Block StringToBitblock(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 - return Block(PadStringToLength(ss.str(), 128, '0', false)); - } - - //! Will convert a string to a flexible data block - inline Flexblock StringToBits(const std::string& s) - { - std::stringstream ss; - - for (std::size_t i = 0; i < s.size(); i++) - ss << std::bitset<8>(s[i]); - - return Flexblock(ss.str()); - } - - //! Will convert a fixed data block to a string - inline std::string BitblockToString(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(); - } - - //! Will convert a flexible data block to a string - inline std::string BitsToString(const Flexblock& bits) - { - std::stringstream ss; - - const std::string bitstring = bits; - - for (std::size_t i = 0; i < bits.size(); i += 8) - { - ss << (char)std::bitset<8>(bitstring.substr(i, 8)).to_ulong(); - } - - return ss.str(); - } - - //! Turns a fixed data block into a hex-string - inline std::string BitblockToHexstring(const Block& b) - { - std::stringstream ss; - const std::string charset = "0123456789abcdef"; - const std::string bstr = b.to_string(); - - for (std::size_t i = 0; i < bstr.size(); i += 4) - ss << charset[std::bitset<4>(bstr.substr(i, 4)).to_ulong()]; - - return ss.str(); - } - - //! Turns a flexible data block into a hex-string - inline std::string BitsToHexstring(const Flexblock& b) - { - std::stringstream ss; - const std::string charset = "0123456789abcdef"; - const std::string bstr = b; - - for (std::size_t i = 0; i < bstr.size(); i += 4) - ss << charset[std::bitset<4>(bstr.substr(i, 4)).to_ulong()]; - - return ss.str(); - } - - - //! Turns a hex string into a fixed data block - inline Block HexstringToBitblock(const std::string& hexstring) - { - std::stringstream ss; - - for (std::size_t i = 0; i < hexstring.size(); i++) - { - const char c = hexstring[i]; - - // Get value - std::size_t value; - if ((c >= '0') && (c <= '9')) - // Is it a number? - value = (c - '0') + 0; - else if ((c >= 'a') && (c <= 'f')) - // Else, it is a lowercase letter - value = (c - 'a') + 10; - else - throw std::logic_error("non-hex string detected in HexstringToBits()"); - - // Append to our bits - ss << std::bitset<4>(value); - } - - return Block(ss.str()); - } - - //! Turns a hex string into a flexible data block - inline Flexblock HexstringToBits(const std::string& hexstring) - { - std::stringstream ss; - - for (std::size_t i = 0; i < hexstring.size(); i++) - { - const char c = hexstring[i]; - - // Get value - std::size_t value; - if ((c >= '0') && (c <= '9')) - // Is it a number? - value = (c - '0') + 0; - else if ((c >= 'a') && (c <= 'f')) - // Else, it is a lowercase letter - value = (c - 'a') + 10; - else - throw std::logic_error("non-hex string detected in HexstringToBits()"); - - // Append to our bits - ss << std::bitset<4>(value); - } - - 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 ^= StringToBitblock(in.substr(i, BLOCK_SIZE / 8)); - - return b; - } - - //! Will read a file into a flexblock - inline Flexblock ReadFileToBits(const std::string& filepath) - { - // Read file - std::ifstream ifs(filepath, std::ios::binary); - - if (!ifs.good()) - throw std::runtime_error("Unable to open ifilestream!"); - - std::stringstream ss; - std::copy( - std::istreambuf_iterator(ifs), - std::istreambuf_iterator(), - std::ostreambuf_iterator(ss) - ); - - ifs.close(); - - const std::string bytes = ss.str(); - - // Convert bytes to bits - return StringToBits(bytes); - } - - //! Will save bits to a binary file - inline void WriteBitsToFile(const std::string& filepath, const Flexblock& bits) - { - // Convert bits to bytes - const std::string bytes = BitsToString(bits); - - // Write bits to file - std::ofstream ofs(filepath, std::ios::binary); - - if (!ofs.good()) - throw std::runtime_error("Unable to open ofilestream!"); - - ofs.write(bytes.data(), bytes.length()); - ofs.close(); - - return; - } -} - -/*** ./../GhettoCrypt/Keyset.h ***/ - -#pragma once -#include - -namespace GhettoCipher -{ - typedef std::array Keyset; -} - -/*** ./../GhettoCrypt/Feistel.h ***/ - -#pragma once - -namespace GhettoCipher -{ - /** Class to perform a feistel block chipher - */ - class Feistel - { - public: - 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. - //! 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) const; - - //! Will decipher a data block via the set seed-key - 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) const; - - //! 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; - }; -} - -/*** ./../GhettoCrypt/Cipher.h ***/ - -#pragma once - -namespace GhettoCipher -{ - /** Class to apply a block cipher to messages of arbitrary length in a distributed manner - */ - class Cipher - { - public: - explicit Cipher(const Block& key); - explicit Cipher(const std::string& password); - - Cipher(const Cipher& other) = delete; - Cipher(Cipher&& other) noexcept = delete; - - ~Cipher(); - - //! 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, bool printProgress = false) const; - - //! Will decipher a flexblock of data - Flexblock Decipher(const Flexblock& data, bool printProgress = false) 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/INCLUDE/generate.sh b/INCLUDE/generate.sh index 5f6191f..0352527 100644 --- a/INCLUDE/generate.sh +++ b/INCLUDE/generate.sh @@ -1,7 +1,8 @@ # Compile single-header -deggl -i ../GhettoCrypt/*.cpp --out GhettoCipher --loc --license-file ../LICENSE +deggl -i ../GhettoCrypt/*.cpp --out GhettoCrypt --loc --license-file ../LICENSE + # Verify that this builds cleanly via g++ echo "Verifying build..." -g++ GhettoCipher.cpp -c -S -o - -Wall > /dev/null +g++ GhettoCrypt.cpp -c -S -o - -Wall > /dev/null echo "If you saw no compiler errors, everything's good!" diff --git a/readme.md b/readme.md index 94117d8..53d4fb6 100644 --- a/readme.md +++ b/readme.md @@ -25,6 +25,38 @@ It's pretty ghetto, you know? * For data obfuscation * If your only other option would be no encryption at all +## How do i use this? +##### Working with strings +```c++ +using namespace GhettoCipher; + +// Get some string +const std::string input = "I am a super secret message!"; +std::cout << input << std::endl; + +// Encrypt +const std::string encrypted = GhettoCryptWrapper::EncryptString(input, "password1"); +std::cout << encrypted << std::endl; + +// Decrypt +const std::string decrypted = GhettoCryptWrapper::DecryptString(encrypted, "password1"); +std::cout << decrypted << std::endl; +``` + +##### Working with files +```c++ +using namespace GhettoCipher; + +// Encrypt +GhettoCryptWrapper::EncryptFile("main.cpp", "main.cpp.crypt", "password1"); + +// Decrypt +GhettoCryptWrapper::DecryptFile("main.cpp.crypt", "main.cpp.clear", "password1"); +``` + +If you want to do more complex stuff use the cipher-class [`GhettoCipher::Cipher`](https://github.com/Leonetienne/GhettoCrypt/blob/master/GhettoCrypt/Cipher.h) aswell as the conversion methods in [Util.h](https://github.com/Leonetienne/GhettoCrypt/blob/master/GhettoCrypt/Util.h). This way you can cipher on bitlevel. Examples on how to do this are in [GhettoCryptWrapper.cpp](https://github.com/Leonetienne/GhettoCrypt/blob/master/GhettoCrypt/GhettoCipherWrapper.cpp). +Without saying, this is more advanced and not as-easy as the methods supplied in the wrapper. + ### I am not kidding, don't use this for critical stuff! Homebrew ciphers are most often shit! Especially mine!🦯