Implemented a key class
This commit is contained in:
parent
bb76cbb2d7
commit
9fdc642bd6
@ -3,6 +3,7 @@
|
||||
#include <GCrypt/SecureBitset.h>
|
||||
#include <GCrypt/Util.h>
|
||||
#include <GCrypt/InitializationVector.h>
|
||||
#include <GCrypt/Key.h>
|
||||
|
||||
using namespace Leonetienne::GCrypt;
|
||||
|
||||
@ -14,11 +15,11 @@ void ExampleString() {
|
||||
std::cout << input << std::endl;
|
||||
|
||||
// Encrypt
|
||||
const std::string encrypted = GWrapper::EncryptString(input, "password1");
|
||||
const std::string encrypted = GWrapper::EncryptString(input, Key::FromPassword("password1"));
|
||||
std::cout << encrypted << std::endl;
|
||||
|
||||
// Decrypt
|
||||
const std::string decrypted = GWrapper::DecryptString(encrypted, "password1");
|
||||
const std::string decrypted = GWrapper::DecryptString(encrypted, Key::FromPassword("password1"));
|
||||
std::cout << decrypted << std::endl;
|
||||
|
||||
return;
|
||||
@ -28,10 +29,10 @@ void ExampleFiles() {
|
||||
std::cout << "Example on how to encrypt & decrypt any file:" << std::endl;
|
||||
|
||||
// Encrypt
|
||||
GWrapper::EncryptFile("main.cpp", "main.cpp.crypt", "password1");
|
||||
GWrapper::EncryptFile("main.cpp", "main.cpp.crypt", Key::FromPassword("password1"));
|
||||
|
||||
// Decrypt
|
||||
GWrapper::DecryptFile("main.cpp.crypt", "main.cpp.clear", "password1");
|
||||
GWrapper::DecryptFile("main.cpp.crypt", "main.cpp.clear", Key::FromPassword("password1"));
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "GCrypt/Keyset.h"
|
||||
#include "GCrypt/Block.h"
|
||||
#include "GCrypt/Key.h"
|
||||
#include "GCrypt/Halfblock.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
@ -8,7 +9,7 @@ namespace Leonetienne::GCrypt {
|
||||
*/
|
||||
class Feistel {
|
||||
public:
|
||||
explicit Feistel(const Block& key);
|
||||
explicit Feistel(const Key& key);
|
||||
|
||||
Feistel(const Feistel& other) = delete;
|
||||
Feistel(Feistel&& other) noexcept = delete;
|
||||
@ -17,7 +18,7 @@ namespace Leonetienne::GCrypt {
|
||||
|
||||
//! Will set the seed-key for this feistel network.
|
||||
//! Roundkeys will be derived from this.
|
||||
void SetKey(const Block& key);
|
||||
void SetKey(const Key& key);
|
||||
|
||||
//! Will encipher a data block via the set seed-key
|
||||
Block Encipher(const Block& data);
|
||||
@ -31,7 +32,7 @@ namespace Leonetienne::GCrypt {
|
||||
Block Run(const Block& data, bool reverseKeys);
|
||||
|
||||
//! Arbitrary cipher function
|
||||
static Halfblock F(Halfblock m, const Block& key);
|
||||
static Halfblock F(Halfblock m, const Key& key);
|
||||
|
||||
//! Split a data block into two half blocks (into L and R)
|
||||
static std::pair<Halfblock, Halfblock> FeistelSplit(const Block& block);
|
||||
@ -49,7 +50,7 @@ namespace Leonetienne::GCrypt {
|
||||
static std::string SBox(const std::string& in);
|
||||
|
||||
//! Will generate a the round keys
|
||||
void GenerateRoundKeys(const Block& seedKey);
|
||||
void GenerateRoundKeys(const Key& seedKey);
|
||||
|
||||
//! Will zero the memory used by the keyset
|
||||
void ZeroKeyMemory();
|
||||
|
@ -14,22 +14,16 @@ namespace Leonetienne::GCrypt {
|
||||
};
|
||||
|
||||
//! Will initialize this cipher with a key
|
||||
explicit GCipher(const Block& key, const DIRECTION direction);
|
||||
|
||||
//! Will initialize this cipher with a key
|
||||
explicit GCipher(const std::string& password, const DIRECTION direction);
|
||||
explicit GCipher(const Key& key, const DIRECTION direction);
|
||||
|
||||
// Disable copying
|
||||
GCipher(const GCipher& other) = delete;
|
||||
GCipher(GCipher&& other) noexcept = delete;
|
||||
|
||||
~GCipher();
|
||||
|
||||
//! Will digest a data block, and return it
|
||||
Block Digest(const Block& input);
|
||||
|
||||
private:
|
||||
Block key;
|
||||
const DIRECTION direction;
|
||||
|
||||
//! The feistel instance to be used
|
||||
@ -37,8 +31,5 @@ namespace Leonetienne::GCrypt {
|
||||
|
||||
//! The last block, required for CBC.
|
||||
Block lastBlock;
|
||||
|
||||
//! Will zero the memory used by the key
|
||||
void ZeroKeyMemory();
|
||||
};
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "GCrypt/Flexblock.h"
|
||||
#include "GCrypt/Block.h"
|
||||
#include "GCrypt/GCipher.h"
|
||||
#include "GCrypt/Key.h"
|
||||
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
/** This class is a wrapper to make working with the GhettoCipher
|
||||
@ -11,25 +13,25 @@ namespace Leonetienne::GCrypt {
|
||||
class GWrapper {
|
||||
public:
|
||||
//! Will encrypt a string and return it hexadecimally encoded.
|
||||
static std::string EncryptString(const std::string& cleartext, const std::string& password);
|
||||
static std::string EncryptString(const std::string& cleartext, const Key& key);
|
||||
|
||||
//! Will decrypt a hexadecimally encoded string.
|
||||
static std::string DecryptString(const std::string& ciphertext, const std::string& password);
|
||||
static std::string DecryptString(const std::string& ciphertext, const Key& key);
|
||||
|
||||
//! 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, bool printProgressReport = false);
|
||||
static bool EncryptFile(const std::string& filename_in, const std::string& filename_out, const Key& key, bool printProgressReport = false);
|
||||
|
||||
//! 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, bool printProgressReport = false);
|
||||
static bool DecryptFile(const std::string& filename_in, const std::string& filename_out, const Key& key, bool printProgressReport = false);
|
||||
|
||||
//! Will enncrypt or decrypt an entire flexblock of binary data, given a key.
|
||||
static Flexblock CipherFlexblock(const Flexblock& data, const Block& key, const GCipher::DIRECTION direction);
|
||||
static Flexblock CipherFlexblock(const Flexblock& data, const Key& key, const GCipher::DIRECTION direction);
|
||||
|
||||
private:
|
||||
|
||||
|
26
GCryptLib/include/GCrypt/Key.h
Normal file
26
GCryptLib/include/GCrypt/Key.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef GCRYPT_KEY_H
|
||||
#define GCRYPT_KEY_H
|
||||
#include "GCrypt/Block.h"
|
||||
#include <string>
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
/* This class represents encryption keys.
|
||||
You can copy them, create them from data blocks,
|
||||
or even read from files (to be implemented).
|
||||
*/
|
||||
class Key : public Block {
|
||||
public:
|
||||
static Key FromPassword(const std::string& password);
|
||||
Key();
|
||||
Key(const Key& k);
|
||||
Key(const Block& b);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
#include <array>
|
||||
#include "GCrypt/Block.h"
|
||||
#include "GCrypt/Key.h"
|
||||
#include "GCrypt/Config.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
typedef std::array<Block, N_ROUNDS> Keyset;
|
||||
typedef std::array<Key, N_ROUNDS> Keyset;
|
||||
}
|
||||
|
||||
|
@ -227,9 +227,6 @@ namespace Leonetienne::GCrypt {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
//! Creates a key of size BLOCK_SIZE from a password of arbitrary length.
|
||||
Block PasswordToKey(const std::string& in);
|
||||
|
||||
//! Will read a file into a flexblock
|
||||
inline Flexblock ReadFileToBits(const std::string& filepath) {
|
||||
// Read file
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
Feistel::Feistel(const Block& key) {
|
||||
Feistel::Feistel(const Key& key) {
|
||||
SetKey(key);
|
||||
return;
|
||||
}
|
||||
@ -16,7 +16,7 @@ namespace Leonetienne::GCrypt {
|
||||
return;
|
||||
}
|
||||
|
||||
void Feistel::SetKey(const Block& key) {
|
||||
void Feistel::SetKey(const Key& key) {
|
||||
GenerateRoundKeys(key);
|
||||
return;
|
||||
}
|
||||
@ -59,7 +59,7 @@ namespace Leonetienne::GCrypt {
|
||||
return FeistelCombine(r, l);
|
||||
}
|
||||
|
||||
Halfblock Feistel::F(Halfblock m, const Block& key) {
|
||||
Halfblock Feistel::F(Halfblock m, const Key& key) {
|
||||
// Made-up F function
|
||||
|
||||
// Expand to full bitwidth
|
||||
@ -174,7 +174,7 @@ namespace Leonetienne::GCrypt {
|
||||
return subMap[in];
|
||||
}
|
||||
|
||||
void Feistel::GenerateRoundKeys(const Block& seedKey) {
|
||||
void Feistel::GenerateRoundKeys(const Key& seedKey) {
|
||||
// Clear initial key memory
|
||||
ZeroKeyMemory();
|
||||
roundKeys = Keyset();
|
||||
@ -234,7 +234,7 @@ namespace Leonetienne::GCrypt {
|
||||
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.
|
||||
|
||||
roundKeys[i] = FeistelCombine(halfkey1, halfkey2);
|
||||
roundKeys[i] = Key(FeistelCombine(halfkey1, halfkey2));
|
||||
}
|
||||
|
||||
return;
|
||||
@ -248,7 +248,7 @@ namespace Leonetienne::GCrypt {
|
||||
#pragma GCC optimize ("O0")
|
||||
#endif
|
||||
void Feistel::ZeroKeyMemory() {
|
||||
for (Block& key : roundKeys) {
|
||||
for (Key& key : roundKeys) {
|
||||
key.reset();
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,8 @@
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
GCipher::GCipher(const Block& key, const DIRECTION direction)
|
||||
GCipher::GCipher(const Key& key, const DIRECTION direction)
|
||||
:
|
||||
key { key },
|
||||
direction { direction },
|
||||
lastBlock(InitializationVector(key)), // Initialize our lastBlock with some deterministic initial value, based on the key
|
||||
feistel(key) {
|
||||
@ -17,22 +16,6 @@ namespace Leonetienne::GCrypt {
|
||||
return;
|
||||
}
|
||||
|
||||
GCipher::GCipher(const std::string& password, const DIRECTION direction)
|
||||
:
|
||||
key { PasswordToKey(password) },
|
||||
direction { direction },
|
||||
lastBlock(InitializationVector(key)), // Initialize our lastBlock with some deterministic initial value, based on the key feistel(key) {
|
||||
feistel(key) {
|
||||
return;
|
||||
}
|
||||
|
||||
GCipher::~GCipher() {
|
||||
// Clear key memory
|
||||
ZeroKeyMemory();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Block GCipher::Digest(const Block& input) {
|
||||
|
||||
switch (direction) {
|
||||
@ -67,23 +50,5 @@ namespace Leonetienne::GCrypt {
|
||||
|
||||
throw std::runtime_error("Unreachable branch reached.");
|
||||
}
|
||||
|
||||
// These pragmas only work for MSVC and g++, as far as i know. Beware!!!
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
#pragma optimize("", off )
|
||||
#elif defined __GNUG__
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("O0")
|
||||
#endif
|
||||
void GCipher::ZeroKeyMemory() {
|
||||
key.reset();
|
||||
return;
|
||||
}
|
||||
#if defined _WIN32 || defined _WIN64
|
||||
#pragma optimize("", on )
|
||||
#elif defined __GNUG__
|
||||
#pragma GCC pop_options
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,9 @@ namespace Leonetienne::GCrypt {
|
||||
GHash::GHash() :
|
||||
// Initialize our cipher with a static, but randomly distributed key.
|
||||
cipher(
|
||||
StringToBitblock("CfRtNdMTP4Y5CWRd"),
|
||||
// Can't use Key::FromPassword here, because it depends on GHash.
|
||||
// Instead use a hardcoded key.
|
||||
Key(StringToBitblock("CfRtNdMTP4Y5CWRd")),
|
||||
GCipher::DIRECTION::ENCIPHER
|
||||
) {
|
||||
block = InitializationVector(StringToBitblock("3J7IipfQTDJbO8jtasz9PgWui6faPaEMOuVuAqyhB1S2CRcLw5caawewgDUEG1WN"));
|
||||
|
@ -4,10 +4,10 @@
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
std::string GWrapper::EncryptString(const std::string& cleartext, const std::string& password) {
|
||||
// Transform the password to a key
|
||||
const Block key = PasswordToKey(password);
|
||||
|
||||
std::string GWrapper::EncryptString(
|
||||
const std::string& cleartext,
|
||||
const Key& key)
|
||||
{
|
||||
// Recode the ascii-string to bits
|
||||
const Flexblock cleartext_bits = StringToBits(cleartext);
|
||||
|
||||
@ -21,10 +21,10 @@ namespace Leonetienne::GCrypt {
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
std::string GWrapper::DecryptString(const std::string& ciphertext, const std::string& password) {
|
||||
// Transform the password to a key
|
||||
const Block key = PasswordToKey(password);
|
||||
|
||||
std::string GWrapper::DecryptString(
|
||||
const std::string& ciphertext,
|
||||
const Key& key)
|
||||
{
|
||||
// Recode the hex-string to bits
|
||||
const Flexblock ciphertext_bits = HexstringToBits(ciphertext);
|
||||
|
||||
@ -38,14 +38,16 @@ namespace Leonetienne::GCrypt {
|
||||
return cleartext;
|
||||
}
|
||||
|
||||
bool GWrapper::EncryptFile(const std::string& filename_in, const std::string& filename_out, const std::string& password, bool printProgressReport) {
|
||||
bool GWrapper::EncryptFile(
|
||||
const std::string& filename_in,
|
||||
const std::string& filename_out,
|
||||
const Key& key,
|
||||
bool printProgressReport)
|
||||
{
|
||||
try {
|
||||
// Read the file to bits
|
||||
const Flexblock cleartext_bits = ReadFileToBits(filename_in);
|
||||
|
||||
// Transform the password to a key
|
||||
const Block key = PasswordToKey(password);
|
||||
|
||||
// Encrypt our cleartext bits
|
||||
const Flexblock ciphertext_bits = CipherFlexblock(cleartext_bits, key, GCipher::DIRECTION::ENCIPHER);
|
||||
|
||||
@ -59,14 +61,16 @@ namespace Leonetienne::GCrypt {
|
||||
}
|
||||
}
|
||||
|
||||
bool GWrapper::DecryptFile(const std::string& filename_in, const std::string& filename_out, const std::string& password, bool printProgressReport) {
|
||||
bool GWrapper::DecryptFile(
|
||||
const std::string& filename_in,
|
||||
const std::string& filename_out,
|
||||
const Key& key,
|
||||
bool printProgressReport)
|
||||
{
|
||||
try {
|
||||
// Read the file to bits
|
||||
const Flexblock ciphertext_bits = ReadFileToBits(filename_in);
|
||||
|
||||
// Transform the password to a key
|
||||
const Block key = PasswordToKey(password);
|
||||
|
||||
// Decrypt the ciphertext bits
|
||||
const Flexblock cleartext_bits = CipherFlexblock(ciphertext_bits, key, GCipher::DIRECTION::DECIPHER);
|
||||
|
||||
@ -82,7 +86,7 @@ namespace Leonetienne::GCrypt {
|
||||
|
||||
Flexblock GWrapper::CipherFlexblock(
|
||||
const Flexblock& data,
|
||||
const Block& key,
|
||||
const Key& key,
|
||||
const GCipher::DIRECTION direction)
|
||||
{
|
||||
// Split input into blocks
|
||||
|
22
GCryptLib/src/Key.cpp
Normal file
22
GCryptLib/src/Key.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "GCrypt/Key.h"
|
||||
#include "GCrypt/GHash.h"
|
||||
#include "GCrypt/Util.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
|
||||
Key Key::FromPassword(const std::string& password) {
|
||||
return GHash::CalculateHashsum(
|
||||
StringToBits(password)
|
||||
);
|
||||
}
|
||||
|
||||
Key::Key() : Block() {
|
||||
}
|
||||
|
||||
Key::Key(const Block& b) : Block(b) {
|
||||
}
|
||||
|
||||
Key::Key(const Key& k) : Block(k) {
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,5 @@
|
||||
#include "GCrypt/GHash.h"
|
||||
|
||||
namespace Leonetienne::GCrypt {
|
||||
Block PasswordToKey(const std::string& in) {
|
||||
// We already have a hashing algorithm, so why not use it
|
||||
// Yeah, this won't work, because it would create an include loop. This method needs to be outsourced to a cpp file..
|
||||
|
||||
const Block hashedPassword = GHash::CalculateHashsum(StringToBits(in));
|
||||
return hashedPassword;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user