/// <summary> /// Set up the seeding algorithms /// </summary> private static void Initialize() { sm_rdtscAtFirstCall = LCPRNG_MMIX.Next(RDTSC8()); // Temporal: Related to when in time this initialization occurred. Not super // accurate ( around 100ns i believe). var medium = (long)DateTime.Now.Ticks; // Temporal: Related to when(-ish) this object was loaded by .NET. This is // affected by what other objects in the program have already been instantiated. // Since this is Framework, we assume a varied instantiation order, yet // admittedly (potentially?) constant for each specific program. Please review // GetHashCode for more info on how this value is determined. // // This is a boxing operation: var course1 = LCPRNG_MMIX.Next(sm_instantiationSeed.GetHashCode()); // This is not a boxing operation: var course2 = LCPRNG_MMIX.Next(sm_lock.GetHashCode()); // These bytes are generated in part based on the crypto seeding algorithm, // thereby adding significant randomness var buf = new byte[8]; sm_masterRng.GetBytes(buf); var crypto = BitConverter.ToInt64(buf, 0); // So merge the two, guessing that we needed the swapped version sm_instantiationSeed = LCPRNG_MMIX.Next(medium ^ course1 ^ course2 ^ crypto); }
/// <summary> /// Except for one-time initialization, this consists of one compare, one interlocked /// increment, a multiply and add, and a cast. Provides a value affected by /// instantiation count run through Knuth's values for a 64-bit linear congruential /// generator. Initialization uses three different time values merged together /// non-destructively. /// </summary> /// <returns> /// A seed that will be statistically different each time this is called. /// </returns> /// <remarks> /// This is not suitable for cryptography. Knowing when the program was started can /// significantly compromise the secret of this algorithm. /// </remarks> public static ulong FastULong() { // Very quickly attribute the fact that this is a "+1" operation (i.e. allow // multiple rapid invocations yield different results) Interlocked.Increment(ref sm_instantiationSeed); sm_instantiationSeed = LCPRNG_MMIX.Next(sm_instantiationSeed); return((ulong)(sm_instantiationSeed ^ sm_rdtscAtFirstCall ^ sm_rdtscAtStaticInitialization)); }