Added class for hashing, that is now used for password to key transformation
This commit is contained in:
parent
f3b6dc155c
commit
6dce12b6ee
34
GCryptLib/include/GCrypt/Hasher.h
Normal file
34
GCryptLib/include/GCrypt/Hasher.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef GCRYPT_HASHER_H
|
||||||
|
#define GCRYPT_HASHER_H
|
||||||
|
|
||||||
|
#include "GCrypt/Flexblock.h"
|
||||||
|
#include "GCrypt/Block.h"
|
||||||
|
#include "GCrypt/Cipher.h"
|
||||||
|
|
||||||
|
namespace Leonetienne::GCrypt {
|
||||||
|
/** This class implements a hash function, based on the GCrypt cipher
|
||||||
|
*/
|
||||||
|
class Hasher {
|
||||||
|
public:
|
||||||
|
Hasher();
|
||||||
|
|
||||||
|
//! Will add the hash value of `data` to the hashsum
|
||||||
|
void Digest(const Block& data);
|
||||||
|
|
||||||
|
//! Will return the current hashsum
|
||||||
|
const Block& GetHashsum() const;
|
||||||
|
|
||||||
|
//! Will calculate a hashsum for `data`.
|
||||||
|
static Block CalculateHashsum(const Flexblock& data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! The cipher to use
|
||||||
|
Cipher cipher;
|
||||||
|
|
||||||
|
//! The current state of the hashsum
|
||||||
|
Block block;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
#pragma once
|
#ifndef GCRYPT_UTIL_H
|
||||||
|
#define GCRYPT_UTIL_H
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -78,7 +80,7 @@ namespace Leonetienne::GCrypt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pad rest with zeores
|
// Pad rest with zeores
|
||||||
return Block(PadStringToLength(ss.str(), 128, '0', false));
|
return Block(PadStringToLength(ss.str(), BLOCK_SIZE, '0', false));
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Will convert a string to a flexible data block
|
//! Will convert a string to a flexible data block
|
||||||
@ -226,43 +228,7 @@ namespace Leonetienne::GCrypt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Creates a key of size BLOCK_SIZE from a password of arbitrary length.
|
//! Creates a key of size BLOCK_SIZE from a password of arbitrary length.
|
||||||
//! Note that if your password is shorter (in bits) than BLOCK_SIZE, the rest of the key will be padded with 0 (see next line!).
|
Block PasswordToKey(const std::string& in);
|
||||||
//! To provide a better initial key, (and to get rid of padding zeroes), the raw result (b) will be xor'd with an initialization vector based on b.
|
|
||||||
//! : return b ^ iv(b)
|
|
||||||
inline Block PasswordToKey(const std::string& in) {
|
|
||||||
// Let's provide a nice initial value to be sure even a password of length 0 results in a proper key
|
|
||||||
Block b = InitializationVector(StringToBitblock("3J7IipfQTDJbO8jtasz9PgWui6faPaEMOuVuAqyhB1S2CRcLw5caawewgDUEG1WN"));
|
|
||||||
|
|
||||||
// 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) {
|
|
||||||
const Block fragment = StringToBitblock(
|
|
||||||
PadStringToLength(in.substr(i, BLOCK_SIZE / 8), BLOCK_SIZE / 8, 0, false)
|
|
||||||
);
|
|
||||||
|
|
||||||
// To provide confusion, xor the blocks together
|
|
||||||
// To provide diffusion, hash fragment to fragment' first
|
|
||||||
b ^= Block(Cipher(fragment, Cipher::CIPHER_DIRECTION::ENCIPHER).Digest(fragment).to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Will reduce a flexblock (they are of arbitrary length) to a single block.
|
|
||||||
//! This single block should change completely, if a single bit in the input flexblock changes anywhere.
|
|
||||||
inline Block ReductionFunction_Flexblock2Block(const Flexblock& in) {
|
|
||||||
Block b; // No initialization vector needed here
|
|
||||||
|
|
||||||
// Segment the input in segments of BLOCK_SIZE, and xor them together.
|
|
||||||
for (std::size_t i = 0; i < in.size(); i += BLOCK_SIZE) {
|
|
||||||
const Block fragment = Block(PadStringToLength(in.substr(i, BLOCK_SIZE), BLOCK_SIZE, 0, false));
|
|
||||||
|
|
||||||
// To provide confusion, xor the blocks together
|
|
||||||
// To provide diffusion, hash fragment to fragment' first
|
|
||||||
b ^= Block(Cipher(fragment, Cipher::CIPHER_DIRECTION::ENCIPHER).Digest(fragment).to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Will read a file into a flexblock
|
//! Will read a file into a flexblock
|
||||||
inline Flexblock ReadFileToBits(const std::string& filepath) {
|
inline Flexblock ReadFileToBits(const std::string& filepath) {
|
||||||
@ -307,3 +273,5 @@ namespace Leonetienne::GCrypt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
57
GCryptLib/src/Hasher.cpp
Normal file
57
GCryptLib/src/Hasher.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include "GCrypt/Hasher.h"
|
||||||
|
#include "GCrypt/Util.h"
|
||||||
|
#include "GCrypt/InitializationVector.h"
|
||||||
|
|
||||||
|
namespace Leonetienne::GCrypt {
|
||||||
|
|
||||||
|
Hasher::Hasher() :
|
||||||
|
// Initialize our cipher with a static, but randomly distributed key.
|
||||||
|
cipher(
|
||||||
|
StringToBitblock("CfRtNdMTP4Y5CWRd"),
|
||||||
|
Cipher::CIPHER_DIRECTION::ENCIPHER
|
||||||
|
) {
|
||||||
|
block = InitializationVector(StringToBitblock("3J7IipfQTDJbO8jtasz9PgWui6faPaEMOuVuAqyhB1S2CRcLw5caawewgDUEG1WN"));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hasher::Digest(const Block& data) {
|
||||||
|
// Encipher the current block, and xor it on the current hashsum
|
||||||
|
block ^= cipher.Digest(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Block& Hasher::GetHashsum() const {
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block Hasher::CalculateHashsum(const Flexblock& data) {
|
||||||
|
// Split input into blocks
|
||||||
|
std::vector<Block> 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))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an additional block, containing the length of the input
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << data.length();
|
||||||
|
const Block lengthBlock = StringToBitblock(ss.str());
|
||||||
|
blocks.push_back(lengthBlock);
|
||||||
|
|
||||||
|
// Create hasher instance
|
||||||
|
Hasher hasher;
|
||||||
|
|
||||||
|
// Digest all blocks
|
||||||
|
for (Block& block : blocks) {
|
||||||
|
hasher.Digest(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the total hashsum
|
||||||
|
return hasher.GetHashsum();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
13
GCryptLib/src/Util.cpp
Normal file
13
GCryptLib/src/Util.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "GCrypt/Util.h"
|
||||||
|
#include "GCrypt/Hasher.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 = Hasher::CalculateHashsum(StringToBits(in));
|
||||||
|
return hashedPassword;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user