后文算法便是通过理论算法实现的,统称为PRNG(pseudo random number generator)伪随机数生成器,又被称为确定性随机比特生成器(deterministic random bit generator,DRBG)。其中适合于加密应用程序的PRNG称为加密安全的PRNG(CSPRNG)。CSPRNG的一个必要条件是不知道初始种子的敌人在分辨生成器的输出序列和真随机序列时只有可忽略的优势。换句话说,若PRNG只需要通过特定统计测试时,则CSPRNG必须通过种子规模的多项式复杂度内的所有统计测试
// C99 + __uint128_t MWC, 256 bits of state, period approx. 2^255
/* The state must be neither all zero, nor x = y = z = 2^64 - 1, c = MWC_A3 - 1. The condition 0 < c < MWC_A3 - 1 is thus sufficient. */ uint64_t x, y, z, c = 1;
#define MWC_A3 0xff377e26f82da74a
uint64_tinlinenext(){ const__uint128_t t = MWC_A3 * (__uint128_t)x + c; x = y; y = z; c = t >> 64; return z = t; }
/* 32-bit */ structxorshift32_state { uint32_t a; } uint32_txorshift32(struct xorshiift32_state *state){ uint32_t x = state->a; x ^= x << 13; x ^= x >> 17; x ^= x << 5; return state->a=x; }
/* 64-bit */ structxorshift64_state { uint64_t a; } uint64_txorshift64(struct xorshift64_state *state){ uint64_t x = state->a; x ^= x << 13; x ^= x >> 7; x ^= x << 17; return state->a=x; }
/* 128-bit */ structxorshift128_state { uint32_t a, b, c, d; } uint32_txorshift128(struct xorshift128_state *state){ uint32_t t = state->d; uint32_tconst s = state->a; state->d = state->c; state->c = state->b; state->b = s; t ^= t << 11; t ^= t >> 8; return state->a = t ^ s ^ (s >> 19); }
#include<stdint.h> structxorshift64s_state { uint64_t a; } uint64_txorshift64s(struct xorshift64s_state *state){ uint64_t x = state->a; x ^= x >> 12; x ^= x << 25; x ^= x >> 27; state->a = x; return x * UINT64_C(0x2545F4914F6CDD1D); }
/* The state must be seeded so that there is at least one non-zero element in array */ structxorshift1024s_state { uint64_tarray[16]; int index; };
uint64_txorshift1024s(struct xorshift1024s_state *state) { int index = state->index; uint64_tconst s = state->array[index++]; uint64_t t = state->array[index &= 15]; t ^= t << 31; // a t ^= t >> 11; // b t ^= s ^ (s >> 30); // c state->array[index] = t; state->index = index; return t * (uint64_t)1181783497276652981; }
/* The state must be seeded so that it is not all zero */ uint64_txorshift128p(struct xorshift128p_state *state) { uint64_t t = state->a; uint64_tconst s = state->b; state->a = s; t ^= t << 23; // a t ^= t >> 17; // b t ^= s ^ (s >> 26); // c state->b = t; return t + s; }
// Copyright 2018 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.
voidMathRandom::InitializeContext(Isolate* isolate, Handle<Context> native_context){ Handle<FixedDoubleArray> cache = Handle<FixedDoubleArray>::cast( isolate->factory()->NewFixedDoubleArray(kCacheSize)); for (int i = 0; i < kCacheSize; i++) cache->set(i, 0); native_context->set_math_random_cache(*cache); Handle<PodArray<State>> pod = PodArray<State>::New(isolate, 1, AllocationType::kOld); native_context->set_math_random_state(*pod); ResetContext(*native_context); }
voidMathRandom::ResetContext(Context native_context){ native_context.set_math_random_index(Smi::zero()); State state = {0, 0}; PodArray<State>::cast(native_context.math_random_state()).set(0, state); }
Address MathRandom::RefillCache(Isolate* isolate, Address raw_native_context){ Context native_context = Context::cast(Object(raw_native_context)); DisallowHeapAllocation no_gc; PodArray<State> pod = PodArray<State>::cast(native_context.math_random_state()); State state = pod.get(0); // Initialize state if not yet initialized. If a fixed random seed was // requested, use it to reset our state the first time a script asks for // random numbers in this context. This ensures the script sees a consistent // sequence. if (state.s0 == 0 && state.s1 == 0) { uint64_t seed; if (FLAG_random_seed != 0) { seed = FLAG_random_seed; } else { isolate->random_number_generator()->NextBytes(&seed, sizeof(seed)); } state.s0 = base::RandomNumberGenerator::MurmurHash3(seed); state.s1 = base::RandomNumberGenerator::MurmurHash3(~seed); CHECK(state.s0 != 0 || state.s1 != 0); }
FixedDoubleArray cache = FixedDoubleArray::cast(native_context.math_random_cache()); // Create random numbers. for (int i = 0; i < kCacheSize; i++) { // Generate random numbers using xorshift128+. base::RandomNumberGenerator::XorShift128(&state.s0, &state.s1); cache.set(i, base::RandomNumberGenerator::ToDouble(state.s0)); } pod.set(0, state);
// Copyright 2013 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.
RandomNumberGenerator::RandomNumberGenerator() { // Check if embedder supplied an entropy source. { MutexGuard lock_guard(entropy_mutex.Pointer()); if (entropy_source != nullptr) { int64_t seed; if (entropy_source(reinterpret_cast<unsignedchar*>(&seed), sizeof(seed))) { SetSeed(seed); return; } } }
#if V8_OS_CYGWIN || V8_OS_WIN // Use rand_s() to gather entropy on Windows. See: // https://code.google.com/p/v8/issues/detail?id=2905 unsigned first_half, second_half; errno_t result = rand_s(&first_half); DCHECK_EQ(0, result); result = rand_s(&second_half); DCHECK_EQ(0, result); SetSeed((static_cast<int64_t>(first_half) << 32) + second_half); #elif V8_OS_MACOSX || V8_OS_FREEBSD || V8_OS_OPENBSD // Despite its prefix suggests it is not RC4 algorithm anymore. // It always succeeds while having decent performance and // no file descriptor involved. int64_t seed; arc4random_buf(&seed, sizeof(seed)); SetSeed(seed); #else // Gather entropy from /dev/urandom if available. FILE* fp = base::Fopen("/dev/urandom", "rb"); if (fp != nullptr) { int64_t seed; size_t n = fread(&seed, sizeof(seed), 1, fp); base::Fclose(fp); if (n == 1) { SetSeed(seed); return; } }
// We cannot assume that random() or rand() were seeded // properly, so instead of relying on random() or rand(), // we just seed our PRNG using timing data as fallback. // This is weak entropy, but it's sufficient, because // it is the responsibility of the embedder to install // an entropy source using v8::V8::SetEntropySource(), // which provides reasonable entropy, see: // https://code.google.com/p/v8/issues/detail?id=2905 int64_t seed = Time::NowFromSystemTime().ToInternalValue() << 24; seed ^= TimeTicks::HighResolutionNow().ToInternalValue() << 16; seed ^= TimeTicks::Now().ToInternalValue() << 8; SetSeed(seed); #endif// V8_OS_CYGWIN || V8_OS_WIN }
for (uint64_t i = 0; i < max; i++) { if (!excluded.count(i)) { result.push_back(i); } }
// Decrease result vector until it contains values to select or exclude, // whatever needs fewer generator calls. size_t larger_part = static_cast<size_t>( std::max(max - static_cast<uint64_t>(n), static_cast<uint64_t>(n)));
// Excluded set may cause that initial result is already smaller than // larget_part. while (result.size() != larger_part && result.size() > n) { size_t x = static_cast<size_t>(NextDouble() * result.size()); CHECK_LT(x, result.size());
uint64_tRandomNumberGenerator::MurmurHash3(uint64_t h){ h ^= h >> 33; h *= uint64_t{0xFF51AFD7ED558CCD}; h ^= h >> 33; h *= uint64_t{0xC4CEB9FE1A85EC53}; h ^= h >> 33; return h; }
/* * Copyright (C) 2011 Google Inc. All rights reserved. * Copyright (C) 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Google, Inc. ("Google") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY GOOGLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* * Copyright (c) 1996, David Mazieres <dm@uun.org> * Copyright (c) 2008, Damien Miller <djm@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
/* * Arc4 random number generator for OpenBSD. * * This code is derived from section 17.1 of Applied Cryptography, * second edition, which describes a stream cipher allegedly * compatible with RSA Labs "RC4" cipher (the actual description of * which is a trade secret). The same algorithm is used as a stream * cipher called "arcfour" in Tatu Ylonen's ssh package. * * RC4 is a registered trademark of RSA Laboratories. */
// Discard early keystream, as per recommendations in: // http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps for (int i = 0; i < 256; i++) getByte(); m_count = 1600000; }
voidARC4RandomNumberGenerator::stirIfNeeded() { if (m_count <= 0) stir(); }
Author
My name is Micheal Wayne and this is my blog.
I am a front-end software engineer.
Contact: michealwayne@163.com