Ejemplo n.º 1
0
        public void CheapEntropyIsDifferentOnSubsequentCalls_32Bytes()
        {
            var e1 = CheapEntropy.Get32();
            var e2 = CheapEntropy.Get32();

            CollectionAssert.AreNotEqual(e1, e2);
        }
Ejemplo n.º 2
0
        private static (byte[] seed, string description) DeriveSeed()
        {
            var seedLength = GetKeysizeBytesForCryptoPrimitive();
            var sha512     = SHA512.Create();

            if (String.IsNullOrEmpty(seed))
            {
                // No seed provided: generate one!
                return(
                    sha512.ComputeHash(
                        StaticLocalEntropy.Get32().GetAwaiter().GetResult().Concat(CheapEntropy.Get32()).ToArray()
                        ).EnsureArraySize(seedLength)
                    , "System environment."
                    );
            }
            if (seed.IsHexString() && seed.Length == seedLength * 2)
            {
                // A hex string of required bytes.
                return(seed.ParseFromHexString(), $"{seedLength} byte hex seed.");
            }
            else if (File.Exists(seed))
            {
                // A file reference: get the SHA512 hash of it as a seed.
                using (var stream = new FileStream(seed, FileMode.Open, FileAccess.Read, FileShare.Read, 64 * 1024))
                    return(
                        sha512.ComputeHash(stream).EnsureArraySize(seedLength),
                        "SHA512 hash of file."
                        );
            }
            else
            {
                // Assume a random set of characters: get the SHA512 hash of the UTF8 string as a seed.
                return(
                    sha512.ComputeHash(Encoding.UTF8.GetBytes(seed)).EnsureArraySize(seedLength),
                    "SHA512 hash of random string / password / passphrase."
                    );
            }
        }
Ejemplo n.º 3
0
        private static GeneratorAndDescription CreateRandomGenerator()
        {
            var result = new GeneratorAndDescription();

            if (generatorType == Generator.StockRandom)
            {
                result.Description             = "deterministic PRNG - " + typeof(Rand).Namespace + "." + typeof(Rand).Name;
                var(seed, description)         = DeriveSeed();
                result.SeedDescription         = description;
                result.Generator               = new StandardRandomWrapperGenerator(new Rand(BitConverter.ToInt32(seed, 0)));
                result.WaitForGeneratorReady   = () => { };
                result.WaitForGeneratorStopped = () => { };
            }
            else if (generatorType == Generator.CryptoRandom)
            {
                result.Description             = "non-deterministic CPRNG - " + typeof(RandomNumberGenerator).Namespace + "." + typeof(RandomNumberGenerator).Name;
                result.SeedDescription         = "No seed required";
                result.Generator               = new CryptoRandomWrapperGenerator();
                result.WaitForGeneratorReady   = () => { };
                result.WaitForGeneratorStopped = () => { };
            }
            else if (generatorType == Generator.TerningerCypher)
            {
                var primitive     = GetCryptoPrimitive();
                var hash          = GetHashAlgorithm();
                var counter       = new CypherCounter(primitive.BlockSizeBytes);
                var entropyGetter = GetEntropyGetter();
                var(seed, description)         = DeriveSeed();
                result.Description             = $"{(nonDeterministic ? "non-" : "")}deterministic PRNG - " + typeof(CypherBasedPrngGenerator).Namespace + "." + typeof(CypherBasedPrngGenerator).Name;
                result.ExtraDescription        = $"Using crypto primitive: {cryptoPrimitive}, hash: {hashAlgorithm}";
                result.SeedDescription         = description;
                result.Generator               = CypherBasedPrngGenerator.Create(key: seed, cryptoPrimitive: primitive, hashAlgorithm: hash, initialCounter: counter, additionalEntropyGetter: entropyGetter);
                result.WaitForGeneratorReady   = () => { };
                result.WaitForGeneratorStopped = () => { };
            }
            else if (generatorType == Generator.TerningerPooled)
            {
                var(seed, description) = DeriveSeed();
                result.SeedDescription = description;

                // Accumulator.
                var accKey = SHA512.Create().ComputeHash(
                    StaticLocalEntropy.Get32().GetAwaiter().GetResult().Concat(CheapEntropy.Get32()).ToArray()
                    ).EnsureArraySize(32);
                var accPrng = CypherBasedPrngGenerator.Create(accKey, CryptoPrimitive.Aes256(), SHA512.Create());
                var acc     = new EntropyAccumulator(linearPools, randomPools, accPrng, SHA512.Create);

                // Generator.
                var primitive = GetCryptoPrimitive();
                var hash      = GetHashAlgorithm();
                var genPrng   = CypherBasedPrngGenerator.Create(new byte[32], primitive, hash);
                IEnumerable <IEntropySource> sources = new IEntropySource[] {
                    new UserSuppliedSource(seed),
                    new CurrentTimeSource(),
                    new TimerSource(),
                    new GCMemorySource(),
                    new CryptoRandomSource(),
                    new NetworkStatsSource(),
                    new ProcessStatsSource(),
                };
                if (includeNetworkSources)
                {
                    sources = sources.Concat(new IEntropySource[] {
                        new PingStatsSource(),
                        new ExternalWebContentSource(),
                        new AnuExternalRandomSource(),
                        new BeaconNistExternalRandomSource(),
                        new HotbitsExternalRandomSource(),
                        new RandomNumbersInfoExternalRandomSource(),
                        new RandomOrgExternalRandomSource(),
                    });
                }
                // As the pooled generator will be churning out entropy as fast as it can, we increase the reseed rate by polling faster and forcing reseeds more frequently.
                var config = new PooledEntropyCprngGenerator.PooledGeneratorConfig()
                {
                    MaximumBytesGeneratedBeforeReseed      = Int32.MaxValue,
                    PollWaitTimeInNormalPriority           = TimeSpan.FromSeconds(1),
                    EntropyToTriggerReseedInNormalPriority = 64,
                };
                var generator = new PooledEntropyCprngGenerator(sources, acc, genPrng, config);
                result.Generator             = generator;
                result.Description           = $"non-deterministic CPRNG - " + typeof(PooledEntropyCprngGenerator).Namespace + "." + typeof(PooledEntropyCprngGenerator).Name;
                result.ExtraDescription      = $"Using {linearPools}+{randomPools} pools (linear+random), {sources.Count()} entropy sources, crypto primitive: {cryptoPrimitive}, hash: {hashAlgorithm}";
                result.WaitForGeneratorReady = () => {
                    generator.StartAndWaitForFirstSeed().Wait(TimeSpan.FromSeconds(60));
                };
                result.WaitForGeneratorStopped = () => {
                    generator.Stop().Wait(TimeSpan.FromSeconds(60));
                };
            }
            else
            {
                throw new Exception("Unexpected Generator type: " + generatorType);
            }
            return(result);
        }
Ejemplo n.º 4
0
        public async Task CypherGenerator_LocalAndCheapKeyWithExtraEntropy()
        {
            var key = SHA256.Create().ComputeHash((await StaticLocalEntropy.Get32()).Concat(CheapEntropy.Get32()).ToArray());
            var rng = CypherBasedPrngGenerator.Create(key, additionalEntropyGetter: CheapEntropy.Get16);

            await FuzzGenerator(10000, 1, 64, rng, nameof(CypherBasedPrngGenerator) + "_LocalAndCheapKeyAndExtraEntropy");
        }