public static CypherBasedPrngGenerator CreateWithSystemCrngKey( ICryptoPrimitive cryptoPrimitive = null, HashAlgorithm hashAlgorithm = null, CypherCounter initialCounter = null, int outputBufferSize = -1, Func <byte[]> additionalEntropyGetter = null) { return(Create(new CryptoRandomWrapperGenerator().GetRandomBytes(32), cryptoPrimitive, hashAlgorithm, initialCounter, outputBufferSize, additionalEntropyGetter)); }
public static CypherBasedPrngGenerator CreateWithCheapKey( ICryptoPrimitive cryptoPrimitive = null, HashAlgorithm hashAlgorithm = null, CypherCounter initialCounter = null, int outputBufferSize = -1, Func <byte[]> additionalEntropyGetter = null) { return(Create(EntropySources.PortableEntropy.Get32(), cryptoPrimitive, hashAlgorithm, initialCounter, outputBufferSize, additionalEntropyGetter)); }
public static CypherBasedPrngGenerator CreateWithNullKey( ICryptoPrimitive cryptoPrimitive = null, HashAlgorithm hashAlgorithm = null, CypherCounter initialCounter = null, int outputBufferSize = -1, Func <byte[]> additionalEntropyGetter = null) { return(Create(new byte[32], cryptoPrimitive, hashAlgorithm, initialCounter, outputBufferSize, additionalEntropyGetter)); }
/// <summary> /// Alternate constructor with named parameters. /// </summary> public static CypherBasedPrngGenerator Create(byte[] key, ICryptoPrimitive cryptoPrimitive = null, HashAlgorithm hashAlgorithm = null, CypherCounter initialCounter = null, int outputBufferSize = -1, Func <byte[]> additionalEntropyGetter = null) { return(new CypherBasedPrngGenerator(key, cryptoPrimitive ?? BlockCypherCryptoPrimitive.Aes256(), hashAlgorithm ?? SHA512.Create(), initialCounter ?? new CypherCounter(16), outputBufferSize < 0 ? 1024 : outputBufferSize, additionalEntropyGetter)); }
/// <summary> /// Initialise the CPRNG with the given key material, specified encryption algorithm, initial counter and additional entropy source. /// </summary> public CypherBasedPrngGenerator(byte[] key, ICryptoPrimitive cryptoPrimitive, HashAlgorithm hashAlgorithm, CypherCounter initialCounter, int outputBufferSize, Func <byte[]> additionalEntropyGetter) { if (key == null) { throw new ArgumentNullException(nameof(key)); } if (cryptoPrimitive == null) { throw new ArgumentNullException(nameof(cryptoPrimitive)); } if (hashAlgorithm == null) { throw new ArgumentNullException(nameof(hashAlgorithm)); } if (initialCounter == null) { throw new ArgumentNullException(nameof(initialCounter)); } _KeySizeInBytes = cryptoPrimitive.KeySizeBytes; _BlockSizeInBytes = cryptoPrimitive.BlockSizeBytes; if (!(_KeySizeInBytes == 16 || _KeySizeInBytes == 32 || _KeySizeInBytes == 64)) { throw new ArgumentOutOfRangeException(nameof(cryptoPrimitive), _KeySizeInBytes, $"Encryption Algorithm KeySize must be 16, 32 or 64 bytes long."); } if (!(_BlockSizeInBytes == 16 || _BlockSizeInBytes == 32 || _BlockSizeInBytes == 64)) { throw new ArgumentOutOfRangeException(nameof(cryptoPrimitive), _BlockSizeInBytes, $"Encryption Algorithm BlockSize must be 16, 32 or 64 bytes long."); } if (key.Length != _KeySizeInBytes) { throw new ArgumentOutOfRangeException(nameof(key), key.Length, $"Key must be {_KeySizeInBytes} bytes long, based on encryption algorithm used."); } if (hashAlgorithm.HashSize / 8 < _KeySizeInBytes) { throw new ArgumentOutOfRangeException(nameof(hashAlgorithm), hashAlgorithm.HashSize / 8, $"Hash Algorithm Size must be at least cypher Key Size (${_KeySizeInBytes} bytes)."); } if (initialCounter.BlockSizeBytes != _BlockSizeInBytes) { throw new ArgumentOutOfRangeException(nameof(initialCounter), initialCounter.BlockSizeBytes, $"Counter block size must be equal to Crypto Primitive BlockSize."); } _RekeyByteCount = _KeySizeInBytes; _RekeyBlockCount = (int)Math.Ceiling((double)_RekeyByteCount / (double)_BlockSizeInBytes); if (outputBufferSize < 0 || outputBufferSize > MaxRequestBytes) { throw new ArgumentOutOfRangeException(nameof(outputBufferSize), outputBufferSize, $"Output buffer size must be between 0 and {MaxRequestBytes}. A minimum of {_RekeyByteCount + 64} is required to use the buffer."); } // Section 9.4.1 - Initialisation // Main difference from spec: we accept a key rather than waiting for a Reseed event. cryptoPrimitive.Key = new byte[_KeySizeInBytes]; _CryptoPrimitive = cryptoPrimitive; _Counter = initialCounter; _HashFunction = hashAlgorithm; // If no getter is supplied, we still create a function, which returns null. if (additionalEntropyGetter == null) { _AdditionalEntropyGetter = () => null; } else { _AdditionalEntropyGetter = additionalEntropyGetter; } // For the output buffer to be usable, it must be at least the re-key size + 32 bytes (enough for several ints). // The buffer is allocated up front, but not initialised until first call. _OutputBufferBlockCount = 0; if (outputBufferSize > _RekeyByteCount + 32) { int remainder; _OutputBufferBlockCount = DivRem(outputBufferSize, _BlockSizeInBytes, out remainder); if (remainder > 0) { _OutputBufferBlockCount = _OutputBufferBlockCount + 1; } _OutputBuffer = new byte[_OutputBufferBlockCount + _BlockSizeInBytes]; _OutputBufferIndex = _OutputBuffer.Length; } // Difference from spec: re key our cypher immediately with the supplied key. ReseedInternal(key); }
/// <summary> /// Initialise the CPRNG with the given key material, specified encryption algorithm and initial counter. /// </summary> public CypherBasedPrngGenerator(byte[] key, ICryptoPrimitive cryptoPrimitive, HashAlgorithm hashAlgorithm, CypherCounter initialCounter, int outputBufferSize) : this(key, cryptoPrimitive, hashAlgorithm, initialCounter, outputBufferSize, null) { }
/// <summary> /// Initialise the CPRNG with the given key material, specified encryption algorithm and initial counter. /// </summary> public CypherBasedPrngGenerator(byte[] key, ICryptoPrimitive cryptoPrimitive, HashAlgorithm hashAlgorithm, CypherCounter initialCounter) : this(key, cryptoPrimitive, hashAlgorithm, initialCounter, 1024, null) { }