From edbf36eb6d23ca4015eec0c6c158498677b297b5 Mon Sep 17 00:00:00 2001 From: Leonetienne Date: Wed, 25 May 2022 13:05:25 +0200 Subject: [PATCH] Cipher now using new block class --- GCryptLib/include/GCrypt/Config.h | 2 +- GCryptLib/include/GCrypt/Util.h | 11 ++++ GCryptLib/include/GCrypt/Version.h | 2 +- GCryptLib/src/Feistel.cpp | 87 ++++++++++-------------------- 4 files changed, 41 insertions(+), 61 deletions(-) diff --git a/GCryptLib/include/GCrypt/Config.h b/GCryptLib/include/GCrypt/Config.h index 0bcac82..5340563 100644 --- a/GCryptLib/include/GCrypt/Config.h +++ b/GCryptLib/include/GCrypt/Config.h @@ -8,7 +8,7 @@ namespace Leonetienne::GCrypt { constexpr std::size_t BLOCK_SIZE = 512; // MUST BE > 2 - constexpr std::size_t N_ROUNDS = 10; + constexpr std::size_t N_ROUNDS = 6; } #endif diff --git a/GCryptLib/include/GCrypt/Util.h b/GCryptLib/include/GCrypt/Util.h index bd60300..5398e7f 100644 --- a/GCryptLib/include/GCrypt/Util.h +++ b/GCryptLib/include/GCrypt/Util.h @@ -18,6 +18,17 @@ namespace Leonetienne::GCrypt { return (denominator + (numerator % denominator)) % denominator; } + inline Block Shiftl(const Block& bits, const std::size_t amount) { + std::stringstream ss; + const std::string bitss = bits.ToString(); + + for (std::size_t i = 0; i < bitss.size(); i++) { + ss << bitss[Mod((int)(i + amount), (int)bitss.size())]; + } + + return Block(ss.str()); + } + //! Will perform a wrapping left-bitshift on a bitset template inline SecureBitset Shiftl(const SecureBitset& bits, const std::size_t amount) { diff --git a/GCryptLib/include/GCrypt/Version.h b/GCryptLib/include/GCrypt/Version.h index e6e5330..655c9f3 100644 --- a/GCryptLib/include/GCrypt/Version.h +++ b/GCryptLib/include/GCrypt/Version.h @@ -1,7 +1,7 @@ #ifndef GCRYPT_VERSION_H #define GCRYPT_VERSION_H -#define GCRYPT_VERSION 0.232 +#define GCRYPT_VERSION 0.233 #endif diff --git a/GCryptLib/src/Feistel.cpp b/GCryptLib/src/Feistel.cpp index 9f2d20d..cca9860 100644 --- a/GCryptLib/src/Feistel.cpp +++ b/GCryptLib/src/Feistel.cpp @@ -62,17 +62,19 @@ namespace Leonetienne::GCrypt { Halfblock Feistel::F(Halfblock m, const Key& 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); - m_expanded = (m_expanded); + // Mix up the block a bit + m_expanded.ShiftCellsRightInplace(); + m_expanded.ShiftRowsUpInplace(); - // Matrix-mult with key + // Matrix-mult with key (this is irreversible) m_expanded *= key; + // Now do a bitshift + m_expanded.ShiftBitsLeftInplace(); + // Non-linearly apply subsitution boxes std::stringstream ss; const std::string m_str = m_expanded.ToString(); @@ -180,65 +182,32 @@ namespace Leonetienne::GCrypt { ZeroKeyMemory(); roundKeys = Keyset(); - // Derive the initial two round keys + // Derive all round keys with simple matrix operations + roundKeys[0] = seedKey; - // Compress- substitute, and expand the seed key to form the initial and the second-initial round key - // This action is non-linear and irreversible, and thus strenghtens security. - Halfblock compressedSeed1 = CompressionFunction(seedKey); - //Halfblock compressedSeed2 = CompressionFunction(Shiftl(seedKey, 1)); // Shifting one key by 1 will result in a completely different compression - Halfblock compressedSeed2 = CompressionFunction((seedKey)); // Shifting one key by 1 will result in a completely different compression - - // To add further confusion, let's shift seed1 by 1 aswell (after compression, but before substitution) - // but only if the total number of bits set are a multiple of 3 - // if it is a multiple of 4, we'll shift it by 1 into the opposite direction - const std::size_t setBits1 = compressedSeed1.count(); - - if (setBits1 % 4 == 0) { - //compressedSeed1 = Shiftr(compressedSeed1, 1); - compressedSeed1 = (compressedSeed1); - } - else if (setBits1 % 3 == 0) { - compressedSeed1 = (compressedSeed1); - } - - // Now apply substitution - std::stringstream ssKey1; - std::stringstream ssKey2; - const std::string bitsKey1 = compressedSeed1.to_string(); - const std::string bitsKey2 = compressedSeed2.to_string(); - - for (std::size_t i = 0; i < HALFBLOCK_SIZE; i += 4) { - ssKey1 << SBox(bitsKey1.substr(i, 4)); - ssKey2 << SBox(bitsKey2.substr(i, 4)); - } - - compressedSeed1 = Halfblock(ssKey1.str()); - compressedSeed2 = Halfblock(ssKey2.str()); - - // Now extrapolate them to BLOCK_SIZE (key size) again - // Xor with the original seed key to get rid of the repititions caused by the expansion - roundKeys[0] = ExpansionFunction(compressedSeed1) ^ seedKey; - roundKeys[1] = ExpansionFunction(compressedSeed2) ^ seedKey; - - // Now derive all other round keys - - for (std::size_t i = 2; i < roundKeys.size(); i++) { + for (std::size_t i = 1; i < roundKeys.size(); i++) { // Initialize new round key with last round key - Block newKey = roundKeys[i - 1]; + const Key& lastKey = roundKeys[i - 1]; + roundKeys[i] = lastKey; - // Shift to left by how many bits are set, modulo 8 - //newKey = Shiftl(newKey, newKey.count() % 8); // This action is irreversible - newKey = (newKey); // This action is irreversible + // Stir it good + roundKeys[i].ShiftRowsUpInplace(); - // Split into two halfblocks, - // apply F() to one halfblock with rk[i-2], - // xor the other one with it - // and put them back together - auto halfkeys = FeistelSplit(newKey); - 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. + // Bitshift and matrix-mult 3 times + // (each time jumbles it up pretty good) + // This is irreversible + roundKeys[i].ShiftBitsRightInplace(); + roundKeys[i] *= lastKey; + roundKeys[i].ShiftBitsRightInplace(); + roundKeys[i] *= lastKey; + roundKeys[i].ShiftBitsRightInplace(); + roundKeys[i] *= lastKey; - roundKeys[i] = Key(FeistelCombine(halfkey1, halfkey2)); + // Lastly, do apply some cell shifting, and other mutations + roundKeys[i].ShiftCellsRightInplace(); + roundKeys[i] += lastKey; + roundKeys[i].ShiftColumnsRightInplace(); + roundKeys[i] ^= lastKey; } return;