Cipher now using new block class

This commit is contained in:
Leonetienne 2022-05-25 13:05:25 +02:00
parent b5369a3c32
commit edbf36eb6d
No known key found for this signature in database
GPG Key ID: C33879CD92E9708C
4 changed files with 41 additions and 61 deletions

View File

@ -8,7 +8,7 @@ namespace Leonetienne::GCrypt {
constexpr std::size_t BLOCK_SIZE = 512; constexpr std::size_t BLOCK_SIZE = 512;
// MUST BE > 2 // MUST BE > 2
constexpr std::size_t N_ROUNDS = 10; constexpr std::size_t N_ROUNDS = 6;
} }
#endif #endif

View File

@ -18,6 +18,17 @@ namespace Leonetienne::GCrypt {
return (denominator + (numerator % denominator)) % denominator; 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 //! Will perform a wrapping left-bitshift on a bitset
template <std::size_t T> template <std::size_t T>
inline SecureBitset<T> Shiftl(const SecureBitset<T>& bits, const std::size_t amount) { inline SecureBitset<T> Shiftl(const SecureBitset<T>& bits, const std::size_t amount) {

View File

@ -1,7 +1,7 @@
#ifndef GCRYPT_VERSION_H #ifndef GCRYPT_VERSION_H
#define GCRYPT_VERSION_H #define GCRYPT_VERSION_H
#define GCRYPT_VERSION 0.232 #define GCRYPT_VERSION 0.233
#endif #endif

View File

@ -62,17 +62,19 @@ namespace Leonetienne::GCrypt {
Halfblock Feistel::F(Halfblock m, const Key& key) { Halfblock Feistel::F(Halfblock m, const Key& key) {
// Made-up F function // Made-up F function
// Expand to full bitwidth // Expand to full bitwidth
Block m_expanded = ExpansionFunction(m); Block m_expanded = ExpansionFunction(m);
// Shift to left by 1 // Mix up the block a bit
//m_expanded = Shiftl(m_expanded, 1); m_expanded.ShiftCellsRightInplace();
m_expanded = (m_expanded); m_expanded.ShiftRowsUpInplace();
// Matrix-mult with key // Matrix-mult with key (this is irreversible)
m_expanded *= key; m_expanded *= key;
// Now do a bitshift
m_expanded.ShiftBitsLeftInplace();
// Non-linearly apply subsitution boxes // Non-linearly apply subsitution boxes
std::stringstream ss; std::stringstream ss;
const std::string m_str = m_expanded.ToString(); const std::string m_str = m_expanded.ToString();
@ -180,65 +182,32 @@ namespace Leonetienne::GCrypt {
ZeroKeyMemory(); ZeroKeyMemory();
roundKeys = Keyset(); 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 for (std::size_t i = 1; i < roundKeys.size(); i++) {
// 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++) {
// Initialize new round key with last round key // 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 // Stir it good
//newKey = Shiftl(newKey, newKey.count() % 8); // This action is irreversible roundKeys[i].ShiftRowsUpInplace();
newKey = (newKey); // This action is irreversible
// Split into two halfblocks, // Bitshift and matrix-mult 3 times
// apply F() to one halfblock with rk[i-2], // (each time jumbles it up pretty good)
// xor the other one with it // This is irreversible
// and put them back together roundKeys[i].ShiftBitsRightInplace();
auto halfkeys = FeistelSplit(newKey); roundKeys[i] *= lastKey;
Halfblock halfkey1 = F(halfkeys.first, roundKeys[i - 2]); roundKeys[i].ShiftBitsRightInplace();
Halfblock halfkey2 = halfkeys.second ^ halfkey1; // I know this is reversible, but it helps to diffuse future round keys. 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; return;