This repository has been archived on 2022-02-10. You can view files and clone it, but cannot push or open issues or pull requests.
fortuna/generator.cpp
surtur 444660bf89
All checks were successful
continuous-integration/drone/push Build is passing
feat(generator): add constructor/destructor
* initialize_generator() is now a private method
* call initialize_generator() inside the constructor of the Generator
* move full struct declaration to generator.h
* have a private field named G of type G_state
* remove explicit instantiation of Generator from fortuna constructor -
  Generator is a private field of fortuna
* remove direct initialize_generator() call from fortuna constructor
* remove get_state() calls as G_state G is now a private field
* refactor get_state() to simply return the *private field G_state G*
* refactor do_crypto() - I know, this should have been split to a
  separate commit - remove function parameters and useless assignments
  inside its body to reflect that once it accesses k and ctr (of the
  G_state G), it won't be necessary for them to be passed as parameters,
  since *G_state G is now a private field*...
2021-11-20 22:31:54 +01:00

118 lines
2.7 KiB
C++

#ifndef FORTUNA_GENERATOR_CPP
#define FORTUNA_GENERATOR_CPP
#include <cmath>
#include <cassert>
#include <cstdint>
#include <stdexcept>
#include <cryptopp/hex.h>
#include <cryptopp/filters.h>
#include <cryptopp/sha3.h>
#include <fmt/core.h>
#include "generator.h"
namespace fortuna {
namespace generator {
Generator::Generator() /*noexcept*/ {
initialize_generator();
}
Generator::~Generator() = default;
void Generator::initialize_generator(){
G.k = 0;
G.ctr = 0;
fmt::print("Generator initialized\n");
// TODO(me): rm this, it's here just so it's called
do_sha("fortuna");
};
auto Generator::get_state() -> G_state {
return G;
}
auto Generator::reseed(const std::string& s) -> void {
std::string to_be_hashed = std::to_string(G.k) + s;
// TODO(me): wrap do_sha in a try-catch
std::string a = do_sha(to_be_hashed);
// str, size, base
G.k = stol(a,nullptr,10);
G.ctr++;
}
auto Generator::do_sha(const std::string& k_n_s) -> std::string {
/* do sha256 */
using CryptoPP::HexEncoder;
using CryptoPP::HashFilter;
using CryptoPP::StringSink;
std::string digest;
// no reason not to go for Keccak
CryptoPP::SHA3_256 sha3_256;
digest.erase();
std::string to_compare =
"8eccfbbbc9df48b4272e6237ce45aad8fbe59629b4963c4dcda5716e61bb34e1";
CryptoPP::StringSource bar(k_n_s,true,
new HashFilter(sha3_256,new HexEncoder(new StringSink(digest),false))
);
assert(digest == to_compare);
fmt::print("{}\n", digest);
digest.erase();
// return digest;
// TODO(me)
// do not return the proper digest just yet, too long to fit into
// int64_t. G.k has to be a 256bit-wide type. for now just return a
// small enough number
return "42";
}
auto Generator::do_crypto() -> std::string {
/* this function calls the block cipher
* returns a string of k*(16 bytes);
* do whatever atm */
return "";
}
auto Generator::generate_blocks(unsigned int k_blocks) -> std::string {
assert ((G.ctr!=0) && "Counter is not 0, generator has been seeded");
std::string r = "";
for (int i = 0; i < k_blocks; ++i) {
r += do_crypto();
G.ctr++;
}
return r;
}
auto Generator::generate_random_data(uint n) -> std::string {
std::string r = "";
if (n < 0){
/* this should not be possible */
fmt::print("[*] error: n cannot be < 0\n");
throw std::invalid_argument("n cannot be < 0");
} else if (n > pow(2,20)){
fmt::print("[*] error: n cannot be > 2^20\n");
throw std::invalid_argument("n cannot be > 2^20");
}
/* do magic to compute r
* r ← first-n-bytes(GenerateBlocks(G, ceil(n/16) )) */
std::string rr = generate_blocks(ceil(n/16));
r = rr.substr(0,n);
/* re-key */
// TODO: check conversions
G.k = stoul(generate_blocks(2));
return r;
};
} // namespace generator
} // namespace fortuna
#endif