std::unique_ptr<RSA_PrivateKey> make_openssl_rsa_private_key(RandomNumberGenerator& rng, size_t rsa_bits) { if (rsa_bits > INT_MAX) throw Internal_Error("rsa_bits overflow"); secure_vector<uint8_t> seed(BOTAN_SYSTEM_RNG_POLL_REQUEST); rng.randomize(seed.data(), seed.size()); RAND_seed(seed.data(), seed.size()); std::unique_ptr<BIGNUM, std::function<void (BIGNUM*)>> bn(BN_new(), BN_free); if(!bn) throw OpenSSL_Error("BN_new"); if(!BN_set_word(bn.get(), RSA_F4)) throw OpenSSL_Error("BN_set_word"); std::unique_ptr<RSA, std::function<void (RSA*)>> rsa(RSA_new(), RSA_free); if(!rsa) throw OpenSSL_Error("RSA_new"); if(!RSA_generate_key_ex(rsa.get(), rsa_bits, bn.get(), nullptr)) throw OpenSSL_Error("RSA_generate_key_ex"); uint8_t* der = nullptr; int bytes = i2d_RSAPrivateKey(rsa.get(), &der); if(bytes < 0) throw OpenSSL_Error("i2d_RSAPrivateKey"); const secure_vector<uint8_t> keydata(der, der + bytes); memset(der, 0, bytes); free(der); return std::unique_ptr<Botan::RSA_PrivateKey> (new RSA_PrivateKey(AlgorithmIdentifier(), keydata)); }
std::string generate_passhash9(const std::string& pass, RandomNumberGenerator& rng, uint16_t work_factor, uint8_t alg_id) { BOTAN_ARG_CHECK(work_factor > 0 && work_factor < 512, "Invalid Passhash9 work factor"); std::unique_ptr<MessageAuthenticationCode> prf = get_pbkdf_prf(alg_id); if(!prf) throw Invalid_Argument("Passhash9: Algorithm id " + std::to_string(alg_id) + " is not defined"); PKCS5_PBKDF2 kdf(prf.release()); // takes ownership of pointer secure_vector<uint8_t> salt(SALT_BYTES); rng.randomize(salt.data(), salt.size()); const size_t kdf_iterations = WORK_FACTOR_SCALE * work_factor; secure_vector<uint8_t> blob; blob.push_back(alg_id); blob.push_back(get_byte(0, work_factor)); blob.push_back(get_byte(1, work_factor)); blob += salt; blob += kdf.derive_key(PASSHASH9_PBKDF_OUTPUT_LEN, pass, salt.data(), salt.size(), kdf_iterations).bits_of(); return MAGIC_PREFIX + base64_encode(blob); }
/* * EME1 Pad Operation */ SecureVector<byte> EME1::pad(const byte in[], size_t in_length, size_t key_length, RandomNumberGenerator& rng) const { key_length /= 8; if(key_length < in_length + 2*Phash.size() + 1) throw Invalid_Argument("EME1: Input is too large"); SecureVector<byte> out(key_length); rng.randomize(&out[0], Phash.size()); out.copy(Phash.size(), &Phash[0], Phash.size()); out[out.size() - in_length - 1] = 0x01; out.copy(out.size() - in_length, in, in_length); mgf->mask(&out[0], Phash.size(), &out[Phash.size()], out.size() - Phash.size()); mgf->mask(&out[Phash.size()], out.size() - Phash.size(), &out[0], Phash.size()); return out; }
/* * OAEP Pad Operation */ secure_vector<byte> OAEP::pad(const byte in[], size_t in_length, size_t key_length, RandomNumberGenerator& rng) const { key_length /= 8; if(key_length < in_length + 2*m_Phash.size() + 1) throw Invalid_Argument("OAEP: Input is too large"); secure_vector<byte> out(key_length); rng.randomize(out.data(), m_Phash.size()); buffer_insert(out, m_Phash.size(), m_Phash.data(), m_Phash.size()); out[out.size() - in_length - 1] = 0x01; buffer_insert(out, out.size() - in_length, in, in_length); mgf1_mask(*m_hash, out.data(), m_Phash.size(), &out[m_Phash.size()], out.size() - m_Phash.size()); mgf1_mask(*m_hash, &out[m_Phash.size()], out.size() - m_Phash.size(), out.data(), m_Phash.size()); return out; }
void MazeServer::setGlobalSeed(unsigned int seed) { RandomNumberGenerator globalGenerator; globalGenerator.setSeed(seed); for (unsigned int i = 0; i < COUNT_RANDOM_NUMBER_GENERATORS; ++i) _randomGenerators[i].setSeed(globalGenerator.randomize()); }
std::vector<RTSS_Share> RTSS_Share::split(byte M, byte N, const byte S[], u16bit S_len, const byte identifier[16], RandomNumberGenerator& rng) { if(M == 0 || N == 0 || M > N) throw Encoding_Error("RTSS_Share::split: M == 0 or N == 0 or M > N"); SHA_256 hash; // always use SHA-256 when generating shares std::vector<RTSS_Share> shares(N); // Create RTSS header in each share for(byte i = 0; i != N; ++i) { shares[i].m_contents += std::make_pair(identifier, 16); shares[i].m_contents += rtss_hash_id(hash.name()); shares[i].m_contents += M; shares[i].m_contents += get_byte(0, S_len); shares[i].m_contents += get_byte(1, S_len); } // Choose sequential values for X starting from 1 for(byte i = 0; i != N; ++i) shares[i].m_contents.push_back(i+1); // secret = S || H(S) secure_vector<byte> secret(S, S + S_len); secret += hash.process(S, S_len); for(size_t i = 0; i != secret.size(); ++i) { std::vector<byte> coefficients(M-1); rng.randomize(coefficients.data(), coefficients.size()); for(byte j = 0; j != N; ++j) { const byte X = j + 1; byte sum = secret[i]; byte X_i = X; for(size_t k = 0; k != coefficients.size(); ++k) { sum ^= gfp_mul(X_i, coefficients[k]); X_i = gfp_mul(X_i, X); } shares[j].m_contents.push_back(sum); } } return shares; }
void randomize_support(u32bit n, std::vector<gf2m> & L, RandomNumberGenerator & rng) { unsigned int i, j; gf2m tmp; for (i = 0; i < n; ++i) { gf2m rnd; rng.randomize(reinterpret_cast<byte*>(&rnd), sizeof(rnd)); j = rnd % n; // no rejection sampling, but for useful code-based parameters with n <= 13 this seem tolerable tmp = L[j]; L[j] = L[i]; L[i] = tmp; } }
std::map<std::string, double> algorithm_benchmark(const std::string& name, u32bit milliseconds, Timer& timer, RandomNumberGenerator& rng, Algorithm_Factory& af) { std::vector<std::string> providers = af.providers_of(name); std::map<std::string, double> all_results; if(providers.empty()) // no providers, nothing to do return all_results; const u64bit ns_per_provider = ((u64bit)milliseconds * 1000 * 1000) / providers.size(); std::vector<byte> buf(16 * 1024); rng.randomize(&buf[0], buf.size()); for(u32bit i = 0; i != providers.size(); ++i) { const std::string provider = providers[i]; std::pair<u64bit, u64bit> results(0, 0); if(const BlockCipher* proto = af.prototype_block_cipher(name, provider)) { std::auto_ptr<BlockCipher> block_cipher(proto->clone()); results = bench_block_cipher(block_cipher.get(), timer, ns_per_provider, &buf[0], buf.size()); } else if(const StreamCipher* proto = af.prototype_stream_cipher(name, provider)) { std::auto_ptr<StreamCipher> stream_cipher(proto->clone()); results = bench_stream_cipher(stream_cipher.get(), timer, ns_per_provider, &buf[0], buf.size()); } else if(const HashFunction* proto = af.prototype_hash_function(name, provider)) { std::auto_ptr<HashFunction> hash(proto->clone()); results = bench_hash(hash.get(), timer, ns_per_provider, &buf[0], buf.size()); } else if(const MessageAuthenticationCode* proto = af.prototype_mac(name, provider)) { std::auto_ptr<MessageAuthenticationCode> mac(proto->clone()); results = bench_mac(mac.get(), timer, ns_per_provider, &buf[0], buf.size()); } if(results.first && results.second) { /* 953.67 == 1000 * 1000 * 1000 / 1024 / 1024 - the conversion factor from bytes per nanosecond to mebibytes per second. */ double speed = (953.67 * results.first) / results.second; all_results[provider] = speed; } } return all_results; }
void RandomNumberGenerator::reseed_from_rng(RandomNumberGenerator& rng, size_t poll_bits) { secure_vector<uint8_t> buf(poll_bits / 8); rng.randomize(buf.data(), buf.size()); this->add_entropy(buf.data(), buf.size()); }
std::vector<RTSS_Share> RTSS_Share::split(uint8_t M, uint8_t N, const uint8_t S[], uint16_t S_len, const std::vector<uint8_t>& identifier, const std::string& hash_fn, RandomNumberGenerator& rng) { if(M <= 1 || N <= 1 || M > N || N >= 255) throw Invalid_Argument("RTSS_Share::split: Invalid N or M"); if(identifier.size() > 16) throw Invalid_Argument("RTSS_Share::split Invalid identifier size"); const uint8_t hash_id = rtss_hash_id(hash_fn); std::unique_ptr<HashFunction> hash; if(hash_id > 0) hash = HashFunction::create_or_throw(hash_fn); // secret = S || H(S) secure_vector<uint8_t> secret(S, S + S_len); if(hash) secret += hash->process(S, S_len); if(secret.size() >= 0xFFFE) throw Encoding_Error("RTSS_Share::split secret too large for TSS format"); // +1 byte for the share ID const uint16_t share_len = static_cast<uint16_t>(secret.size() + 1); secure_vector<uint8_t> share_header(RTSS_HEADER_SIZE); copy_mem(&share_header[0], identifier.data(), identifier.size()); share_header[16] = hash_id; share_header[17] = M; share_header[18] = get_byte(0, share_len); share_header[19] = get_byte(1, share_len); // Create RTSS header in each share std::vector<RTSS_Share> shares(N); for(uint8_t i = 0; i != N; ++i) { shares[i].m_contents.reserve(share_header.size() + share_len); shares[i].m_contents = share_header; } // Choose sequential values for X starting from 1 for(uint8_t i = 0; i != N; ++i) shares[i].m_contents.push_back(i+1); for(size_t i = 0; i != secret.size(); ++i) { std::vector<uint8_t> coefficients(M-1); rng.randomize(coefficients.data(), coefficients.size()); for(uint8_t j = 0; j != N; ++j) { const uint8_t X = j + 1; uint8_t sum = secret[i]; uint8_t X_i = X; for(size_t k = 0; k != coefficients.size(); ++k) { sum ^= gfp_mul(X_i, coefficients[k]); X_i = gfp_mul(X_i, X); } shares[j].m_contents.push_back(sum); } } return shares; }