Implemented GPrng pnrg
This commit is contained in:
parent
bedfc91e04
commit
04c67436c4
@ -26,6 +26,8 @@ namespace Leonetienne::GCrypt {
|
|||||||
//! Will decipher a data block via the set seed-key
|
//! Will decipher a data block via the set seed-key
|
||||||
Block Decipher(const Block& data);
|
Block Decipher(const Block& data);
|
||||||
|
|
||||||
|
void operator=(const Feistel& other);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Will run the feistel rounds, with either regular key
|
//! Will run the feistel rounds, with either regular key
|
||||||
//! order or reversed key order
|
//! order or reversed key order
|
||||||
|
@ -23,8 +23,10 @@ namespace Leonetienne::GCrypt {
|
|||||||
//! Will digest a data block, and return it
|
//! Will digest a data block, and return it
|
||||||
Block Digest(const Block& input);
|
Block Digest(const Block& input);
|
||||||
|
|
||||||
|
void operator=(const GCipher& other);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const DIRECTION direction;
|
DIRECTION direction;
|
||||||
|
|
||||||
//! The feistel instance to be used
|
//! The feistel instance to be used
|
||||||
Feistel feistel;
|
Feistel feistel;
|
||||||
|
@ -24,6 +24,8 @@ namespace Leonetienne::GCrypt {
|
|||||||
//! Will calculate a hashsum for `data`.
|
//! Will calculate a hashsum for `data`.
|
||||||
static Block CalculateHashsum(const Flexblock& data);
|
static Block CalculateHashsum(const Flexblock& data);
|
||||||
|
|
||||||
|
void operator=(const GHash& other);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! The cipher to use
|
//! The cipher to use
|
||||||
GCipher cipher;
|
GCipher cipher;
|
||||||
|
63
GCryptLib/include/GCrypt/GPrng.h
Normal file
63
GCryptLib/include/GCrypt/GPrng.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#ifndef GCRYPT_GPRNG_H
|
||||||
|
#define GCRYPT_GPRNG_H
|
||||||
|
|
||||||
|
#include "GCrypt/GHash.h"
|
||||||
|
#include "GCrypt/Util.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace Leonetienne::GCrypt {
|
||||||
|
/** This class implements a pseudo random number generator, based on the GCrypt hash function
|
||||||
|
*/
|
||||||
|
class GPrng {
|
||||||
|
public:
|
||||||
|
//! Will instanciate the prng with a seed. Seed could also be a GCrypt::Key.
|
||||||
|
GPrng(const Block& seed);
|
||||||
|
|
||||||
|
//! Will instanciate the GPrng with no seed. You should really seed it later.
|
||||||
|
GPrng();
|
||||||
|
|
||||||
|
//! Will reset and seed the prng. Seed could also be a GCrypt::Key.
|
||||||
|
void Seed(const Block& seed);
|
||||||
|
|
||||||
|
//! Will return a random bit.
|
||||||
|
bool GetBit();
|
||||||
|
|
||||||
|
//! Will return a randomized instance of any primitive.
|
||||||
|
template <typename T>
|
||||||
|
T GetRandom() {
|
||||||
|
static_assert(std::is_fundamental<T>::value, "Leonetienne::GCrypt::GPrng::GetRandom() may only be used with primitive types!");
|
||||||
|
|
||||||
|
// Pull the required amount of bits
|
||||||
|
std::stringstream ss;
|
||||||
|
for (std::size_t i = 0; i < sizeof(T)*8; i++) {
|
||||||
|
ss << GetBit() ? '1' : '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform to bytes
|
||||||
|
const std::string bytes = BitsToBytes(ss.str());
|
||||||
|
|
||||||
|
// Cram bytes into type
|
||||||
|
T t;
|
||||||
|
memcpy(&t, bytes.data(), sizeof(T));
|
||||||
|
|
||||||
|
// Return our randomized primitive
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Will return a random block
|
||||||
|
Block GetBlock();
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Will generate the next block of random bits
|
||||||
|
void AdvanceBlock();
|
||||||
|
|
||||||
|
GHash hasher;
|
||||||
|
Block seed;
|
||||||
|
std::size_t nextBit = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -240,6 +240,12 @@ namespace Leonetienne::GCrypt {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Feistel::operator=(const Feistel& other) {
|
||||||
|
roundKeys = other.roundKeys;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// These pragmas only work for MSVC and g++, as far as i know. Beware!!!
|
// These pragmas only work for MSVC and g++, as far as i know. Beware!!!
|
||||||
#if defined _WIN32 || defined _WIN64
|
#if defined _WIN32 || defined _WIN64
|
||||||
#pragma optimize("", off )
|
#pragma optimize("", off )
|
||||||
|
@ -50,5 +50,14 @@ namespace Leonetienne::GCrypt {
|
|||||||
|
|
||||||
throw std::runtime_error("Unreachable branch reached.");
|
throw std::runtime_error("Unreachable branch reached.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GCipher::operator=(const GCipher& other) {
|
||||||
|
direction = other.direction;
|
||||||
|
feistel = other.feistel;
|
||||||
|
lastBlock = other.lastBlock;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,5 +55,10 @@ namespace Leonetienne::GCrypt {
|
|||||||
return hasher.GetHashsum();
|
return hasher.GetHashsum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GHash::operator=(const GHash& other) {
|
||||||
|
cipher = other.cipher;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
75
GCryptLib/src/GPrng.cpp
Normal file
75
GCryptLib/src/GPrng.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include "GCrypt/GPrng.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace Leonetienne::GCrypt {
|
||||||
|
|
||||||
|
GPrng::GPrng(const Block& seed) {
|
||||||
|
this->seed = seed;
|
||||||
|
hasher.DigestBlock(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
GPrng::GPrng() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPrng::Seed(const Block& seed) {
|
||||||
|
hasher = GHash();
|
||||||
|
this->seed = seed;
|
||||||
|
hasher.DigestBlock(seed);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GPrng::GetBit() {
|
||||||
|
// If we have no more bits to go, create new ones
|
||||||
|
if (nextBit >= BLOCK_SIZE) {
|
||||||
|
AdvanceBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the next bit.
|
||||||
|
return hasher.GetHashsum()[nextBit++];
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPrng::AdvanceBlock() {
|
||||||
|
// To prevent an attacker from being able
|
||||||
|
// to predict block n, by knowing block n-1, and block n-2,
|
||||||
|
// we will advance the hash function by block n-1 XOR seed.
|
||||||
|
// This way it is impossible for an attacker to know the
|
||||||
|
// state of the hash function, unless the seed is known.
|
||||||
|
|
||||||
|
// Advance the block (Add the current hashsum XOR seed to the hasher)
|
||||||
|
hasher.DigestBlock(Block(hasher.GetHashsum() ^ seed));
|
||||||
|
|
||||||
|
// Reset the pointer
|
||||||
|
nextBit = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block GPrng::GetBlock() {
|
||||||
|
// Getting a block is a bit troublesome.
|
||||||
|
// Just fetching 512 bits would be too much of a performance hog.
|
||||||
|
|
||||||
|
// Slurp up the rest of the current block
|
||||||
|
std::stringstream ss;
|
||||||
|
const std::size_t bitsLeft = BLOCK_SIZE - nextBit;
|
||||||
|
ss << hasher.GetHashsum().to_string().substr(nextBit, bitsLeft);
|
||||||
|
|
||||||
|
// Now we have to advance to the next block
|
||||||
|
AdvanceBlock();
|
||||||
|
|
||||||
|
// Now, grab the remaining bits
|
||||||
|
const std::size_t remainingBits = BLOCK_SIZE - bitsLeft;
|
||||||
|
ss << hasher.GetHashsum().to_string().substr(0, remainingBits);
|
||||||
|
|
||||||
|
// Assert that we have the correct number of bits
|
||||||
|
assert(ss.str().length() == BLOCK_SIZE);
|
||||||
|
|
||||||
|
// Set out bitpointer
|
||||||
|
nextBit = remainingBits;
|
||||||
|
|
||||||
|
// Return our block
|
||||||
|
return Block(ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user