summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2015-11-16 12:59:04 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2015-11-16 12:59:04 +0700
commitae976da8e118d814e83d6272800d56b6007abf9d (patch)
tree1382d0e897d7d796551bcae4c15c4f45e84b4368 /crypto
parentRename/delete some files (diff)
downloadBouncyCastle.NET-ed25519-ae976da8e118d814e83d6272800d56b6007abf9d.tar.xz
More delete/move/rename
Diffstat (limited to 'crypto')
-rw-r--r--crypto/src/crypto/prng/CtrSP800Drbg.cs495
-rw-r--r--crypto/src/crypto/prng/HMacSP800Drbg.cs196
-rw-r--r--crypto/src/crypto/prng/HashSP800Drbg.cs295
-rw-r--r--crypto/src/crypto/prng/IEntropySource.cs29
-rw-r--r--crypto/src/crypto/prng/IEntropySourceProvider.cs19
-rw-r--r--crypto/src/crypto/prng/drbg/ISP80090Drbg.cs (renamed from crypto/src/crypto/prng/drbg/SP80090Drbg.cs)0
6 files changed, 48 insertions, 986 deletions
diff --git a/crypto/src/crypto/prng/CtrSP800Drbg.cs b/crypto/src/crypto/prng/CtrSP800Drbg.cs
deleted file mode 100644
index 089cd17cd..000000000
--- a/crypto/src/crypto/prng/CtrSP800Drbg.cs
+++ /dev/null
@@ -1,495 +0,0 @@
-using System;
-
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Utilities;
-using Org.BouncyCastle.Utilities.Encoders;
-
-namespace Org.BouncyCastle.Crypto.Prng.Drbg
-{
-	/**
-	 * A SP800-90A CTR DRBG.
-	 */
-	public class CtrSP800Drbg: SP80090Drbg
-	{
-	    private static readonly long       TDEA_RESEED_MAX = 1L << (32 - 1);
-		private static readonly long       AES_RESEED_MAX = 1L << (48 - 1);
-		private static readonly int        TDEA_MAX_BITS_REQUEST = 1 << (13 - 1);
-		private static readonly int        AES_MAX_BITS_REQUEST = 1 << (19 - 1);
-
-	    private IEntropySource        _entropySource;
-	    private IBlockCipher          _engine;
-	    private int                   _keySizeInBits;
-	    private int                   _seedLength;
-	    private int                   _securityStrength;
-
-	    // internal state
-	    private byte[]                _Key;
-	    private byte[]                _V;
-	    private long                  _reseedCounter = 0;
-	    private bool                  _isTDEA = false;
-
-	    /**
-	     * Construct a SP800-90A CTR DRBG.
-	     * <p>
-	     * Minimum entropy requirement is the security strength requested.
-	     * </p>
-	     * @param engine underlying block cipher to use to support DRBG
-	     * @param keySizeInBits size of the key to use with the block cipher.
-	     * @param securityStrength security strength required (in bits)
-	     * @param entropySource source of entropy to use for seeding/reseeding.
-	     * @param personalizationString personalization string to distinguish this DRBG (may be null).
-	     * @param nonce nonce to further distinguish this DRBG (may be null).
-	     */
-	    public CtrSP800Drbg(IBlockCipher engine, int keySizeInBits, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce)
-	    {
-	        _entropySource = entropySource;
-	        _engine = engine;     
-	        
-	        _keySizeInBits = keySizeInBits;
-	        _securityStrength = securityStrength;
-	        _seedLength = keySizeInBits + engine.GetBlockSize() * 8;
-	        _isTDEA = isTDEA(engine);
-
-	        if (securityStrength > 256)
-	        {
-	            throw new ArgumentException("Requested security strength is not supported by the derivation function");
-	        }
-
-	        if (getMaxSecurityStrength(engine, keySizeInBits) < securityStrength)
-	        {
-	            throw new ArgumentException("Requested security strength is not supported by block cipher and key size");
-	        }
-
-	        if (entropySource.EntropySize < securityStrength)
-	        {
-	            throw new ArgumentException("Not enough entropy for security strength required");
-	        }
-
-	        byte[] entropy = getEntropy();  // Get_entropy_input
-
-	        CTR_DRBG_Instantiate_algorithm(entropy, nonce, personalizationString);
-	    }
-
-	    private void CTR_DRBG_Instantiate_algorithm(byte[] entropy, byte[] nonce,
-	            byte[] personalisationString)
-	    {
-	        byte[] seedMaterial = Arrays.Concatenate(entropy, nonce, personalisationString);
-	        byte[] seed = Block_Cipher_df(seedMaterial, _seedLength);
-
-	        int outlen = _engine.GetBlockSize();
-
-	        _Key = new byte[(_keySizeInBits + 7) / 8];
-	        _V = new byte[outlen];
-
-	         // _Key & _V are modified by this call
-	        CTR_DRBG_Update(seed, _Key, _V); 
-
-	        _reseedCounter = 1;
-	    }
-
-	    private void CTR_DRBG_Update(byte[] seed, byte[] key, byte[] v)
-	    {
-	        byte[] temp = new byte[seed.Length];
-	        byte[] outputBlock = new byte[_engine.GetBlockSize()];
-	        
-	        int i=0;
-	        int outLen = _engine.GetBlockSize();
-
-	        _engine.Init(true, new KeyParameter(expandKey(key)));
-	        while (i*outLen < seed.Length)
-	        {
-	            addOneTo(v);
-	            _engine.ProcessBlock(v, 0, outputBlock, 0);
-
-	            int bytesToCopy = ((temp.Length - i * outLen) > outLen)
-	                    ? outLen : (temp.Length - i * outLen);
-	            
-	            Array.Copy(outputBlock, 0, temp, i * outLen, bytesToCopy);
-	            ++i;
-	        }
-
-	        XOR(temp, seed, temp, 0);
-
-	        Array.Copy(temp, 0, key, 0, key.Length);
-	        Array.Copy(temp, key.Length, v, 0, v.Length);
-	    }
-	    
-	    private void CTR_DRBG_Reseed_algorithm(byte[] additionalInput)
-	    {
-	        byte[] seedMaterial = Arrays.Concatenate(getEntropy(), additionalInput);
-
-	        seedMaterial = Block_Cipher_df(seedMaterial, _seedLength);
-
-	        CTR_DRBG_Update(seedMaterial, _Key, _V);
-
-	        _reseedCounter = 1;
-	    }
-
-	    private void XOR(byte[] output, byte[] a, byte[] b, int bOff)
-	    {
-				for (int i=0; i< output.Length; i++) 
-	        {
-					output[i] = (byte)(a[i] ^ b[i+bOff]);
-	        }
-	    }
-	    
-	    private void addOneTo(byte[] longer)
-	    {
-	        int carry = 1;
-	        for (int i = 1; i <= longer.Length; i++) // warning
-	        {
-	            int res = (longer[longer.Length - i] & 0xff) + carry;
-	            carry = (res > 0xff) ? 1 : 0;
-	            longer[longer.Length - i] = (byte)res;
-	        }
-	    } 
-
-	    private byte[] getEntropy()
-	    {
-	        byte[] entropy = _entropySource.GetEntropy();
-	        if (entropy.Length < (_securityStrength + 7) / 8)
-	        {
-	            throw new InvalidOperationException("Insufficient entropy provided by entropy source");
-	        }
-	        return entropy;
-	    }
-
-	    // -- Internal state migration ---
-	    
-	    private static readonly byte[] K_BITS = Hex.Decode("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
-
-	    // 1. If (number_of_bits_to_return > max_number_of_bits), then return an
-	    // ERROR_FLAG.
-	    // 2. L = len (input_string)/8.
-	    // 3. N = number_of_bits_to_return/8.
-	    // Comment: L is the bitstring represention of
-	    // the integer resulting from len (input_string)/8.
-	    // L shall be represented as a 32-bit integer.
-	    //
-	    // Comment : N is the bitstring represention of
-	    // the integer resulting from
-	    // number_of_bits_to_return/8. N shall be
-	    // represented as a 32-bit integer.
-	    //
-	    // 4. S = L || N || input_string || 0x80.
-	    // 5. While (len (S) mod outlen)
-	    // Comment : Pad S with zeros, if necessary.
-	    // 0, S = S || 0x00.
-	    //
-	    // Comment : Compute the starting value.
-	    // 6. temp = the Null string.
-	    // 7. i = 0.
-	    // 8. K = Leftmost keylen bits of 0x00010203...1D1E1F.
-	    // 9. While len (temp) < keylen + outlen, do
-	    //
-	    // IV = i || 0outlen - len (i).
-	    //
-	    // 9.1
-	    //
-	    // temp = temp || BCC (K, (IV || S)).
-	    //
-	    // 9.2
-	    //
-	    // i = i + 1.
-	    //
-	    // 9.3
-	    //
-	    // Comment : i shall be represented as a 32-bit
-	    // integer, i.e., len (i) = 32.
-	    //
-	    // Comment: The 32-bit integer represenation of
-	    // i is padded with zeros to outlen bits.
-	    //
-	    // Comment: Compute the requested number of
-	    // bits.
-	    //
-	    // 10. K = Leftmost keylen bits of temp.
-	    //
-	    // 11. X = Next outlen bits of temp.
-	    //
-	    // 12. temp = the Null string.
-	    //
-	    // 13. While len (temp) < number_of_bits_to_return, do
-	    //
-	    // 13.1 X = Block_Encrypt (K, X).
-	    //
-	    // 13.2 temp = temp || X.
-	    //
-	    // 14. requested_bits = Leftmost number_of_bits_to_return of temp.
-	    //
-	    // 15. Return SUCCESS and requested_bits.
-	    private byte[] Block_Cipher_df(byte[] inputString, int bitLength)
-	    {
-	        int outLen = _engine.GetBlockSize();
-	        int L = inputString.Length; // already in bytes
-	        int N = bitLength / 8;
-	        // 4 S = L || N || inputstring || 0x80
-	        int sLen = 4 + 4 + L + 1;
-	        int blockLen = ((sLen + outLen - 1) / outLen) * outLen;
-	        byte[] S = new byte[blockLen];
-	        copyIntToByteArray(S, L, 0);
-	        copyIntToByteArray(S, N, 4);
-	        Array.Copy(inputString, 0, S, 8, L);
-	        S[8 + L] = (byte)0x80;
-	        // S already padded with zeros
-
-	        byte[] temp = new byte[_keySizeInBits / 8 + outLen];
-	        byte[] bccOut = new byte[outLen];
-
-	        byte[] IV = new byte[outLen]; 
-	        
-	        int i = 0;
-	        byte[] K = new byte[_keySizeInBits / 8];
-	        Array.Copy(K_BITS, 0, K, 0, K.Length);
-
-	        while (i*outLen*8 < _keySizeInBits + outLen *8)
-	        {
-	            copyIntToByteArray(IV, i, 0);
-	            BCC(bccOut, K, IV, S);
-
-	            int bytesToCopy = ((temp.Length - i * outLen) > outLen)
-	                    ? outLen
-	                    : (temp.Length - i * outLen);
-	            
-	            Array.Copy(bccOut, 0, temp, i * outLen, bytesToCopy);
-	            ++i;
-	        }
-
-	        byte[] X = new byte[outLen];
-	        Array.Copy(temp, 0, K, 0, K.Length);
-	        Array.Copy(temp, K.Length, X, 0, X.Length);
-
-	        temp = new byte[bitLength / 2];
-
-	        i = 0;
-	        _engine.Init(true, new KeyParameter(expandKey(K)));
-
-	        while (i * outLen < temp.Length)
-	        {
-	            _engine.ProcessBlock(X, 0, X, 0);
-
-	            int bytesToCopy = ((temp.Length - i * outLen) > outLen)
-	                    ? outLen
-	                    : (temp.Length - i * outLen);
-
-	            Array.Copy(X, 0, temp, i * outLen, bytesToCopy);
-	            i++;
-	        }
-
-	        return temp;
-	    }
-
-	    /*
-	    * 1. chaining_value = 0^outlen    
-	    *    . Comment: Set the first chaining value to outlen zeros.
-	    * 2. n = len (data)/outlen.
-	    * 3. Starting with the leftmost bits of data, split the data into n blocks of outlen bits 
-	    *    each, forming block(1) to block(n). 
-	    * 4. For i = 1 to n do
-	    * 4.1 input_block = chaining_value ^ block(i) .
-	    * 4.2 chaining_value = Block_Encrypt (Key, input_block).
-	    * 5. output_block = chaining_value.
-	    * 6. Return output_block. 
-	     */
-	    private void BCC(byte[] bccOut, byte[] k, byte[] iV, byte[] data)
-	    {
-	        int outlen = _engine.GetBlockSize();
-	        byte[] chainingValue = new byte[outlen]; // initial values = 0
-	        int n = data.Length / outlen;
-
-	        byte[] inputBlock = new byte[outlen];
-
-	        _engine.Init(true, new KeyParameter(expandKey(k)));
-
-	        _engine.ProcessBlock(iV, 0, chainingValue, 0);
-
-	        for (int i = 0; i < n; i++)
-	        {
-	            XOR(inputBlock, chainingValue, data, i*outlen);
-	            _engine.ProcessBlock(inputBlock, 0, chainingValue, 0);
-	        }
-
-	        Array.Copy(chainingValue, 0, bccOut, 0, bccOut.Length);
-	    }
-
-	    private void copyIntToByteArray(byte[] buf, int value, int offSet)
-	    {
-	        buf[offSet + 0] = ((byte)(value >> 24));
-	        buf[offSet + 1] = ((byte)(value >> 16));
-	        buf[offSet + 2] = ((byte)(value >> 8));
-	        buf[offSet + 3] = ((byte)(value));
-	    }
-
-	    /**
-	     * Return the block size (in bits) of the DRBG.
-	     *
-	     * @return the number of bits produced on each internal round of the DRBG.
-	     */
-	    public int BlockSize
-	    {
-			get {
-				return _V.Length * 8;
-			}
-	    }
-
-	    /**
-	     * Populate a passed in array with random data.
-	     *
-	     * @param output output array for generated bits.
-	     * @param additionalInput additional input to be added to the DRBG in this step.
-	     * @param predictionResistant true if a reseed should be forced, false otherwise.
-	     *
-	     * @return number of bits generated, -1 if a reseed required.
-	     */
-	    public int Generate(byte[] output, byte[] additionalInput, bool predictionResistant)
-	    {
-	        if (_isTDEA)
-	        {
-	            if (_reseedCounter > TDEA_RESEED_MAX)
-	            {
-	                return -1;
-	            }
-
-	            if (Utils.isTooLarge(output, TDEA_MAX_BITS_REQUEST / 8))
-	            {
-	                throw new ArgumentException("Number of bits per request limited to " + TDEA_MAX_BITS_REQUEST);
-	            }
-	        }
-	        else
-	        {
-	            if (_reseedCounter > AES_RESEED_MAX)
-	            {
-	                return -1;
-	            }
-
-	            if (Utils.isTooLarge(output, AES_MAX_BITS_REQUEST / 8))
-	            {
-	                throw new ArgumentException("Number of bits per request limited to " + AES_MAX_BITS_REQUEST);
-	            }
-	        }
-
-	        if (predictionResistant)
-	        {
-	            CTR_DRBG_Reseed_algorithm(additionalInput);
-	            additionalInput = null;
-	        }
-
-	        if (additionalInput != null)
-	        {
-	            additionalInput = Block_Cipher_df(additionalInput, _seedLength);
-	            CTR_DRBG_Update(additionalInput, _Key, _V);
-	        }
-	        else
-	        {
-	            additionalInput = new byte[_seedLength];
-	        }
-
-	        byte[] tmp = new byte[_V.Length];
-
-	        _engine.Init(true, new KeyParameter(expandKey(_Key)));
-
-				for (int i = 0; i <= output.Length / tmp.Length; i++)
-	        {
-					int bytesToCopy = ((output.Length - i * tmp.Length) > tmp.Length)
-						? tmp.Length
-	                    : (output.Length - i * _V.Length);
-
-	            if (bytesToCopy != 0)
-	            {
-	                addOneTo(_V);
-
-						_engine.ProcessBlock(_V, 0, tmp, 0);
-
-						Array.Copy(tmp, 0, output, i * tmp.Length, bytesToCopy);
-	            }
-	        }
-
-	        CTR_DRBG_Update(additionalInput, _Key, _V);
-
-	        _reseedCounter++;
-
-	        return output.Length * 8;
-	    }
-
-	    /**
-	      * Reseed the DRBG.
-	      *
-	      * @param additionalInput additional input to be added to the DRBG in this step.
-	      */
-	    public void Reseed(byte[] additionalInput)
-	    {
-	        CTR_DRBG_Reseed_algorithm(additionalInput);
-	    }
-
-	    private bool isTDEA(IBlockCipher cipher)
-	    {
-	        return cipher.AlgorithmName.Equals("DESede") || cipher.AlgorithmName.Equals("TDEA");
-	    }
-
-	    private int getMaxSecurityStrength(IBlockCipher cipher, int keySizeInBits)
-	    {
-	        if (isTDEA(cipher) && keySizeInBits == 168)
-	        {
-	            return 112;
-	        }
-	        if (cipher.AlgorithmName.Equals("AES"))
-	        {
-	            return keySizeInBits;
-	        }
-
-	        return -1;
-	    }
-
-	    byte[] expandKey(byte[] key)
-	    {
-	        if (_isTDEA)
-	        {
-	            // expand key to 192 bits.
-	            byte[] tmp = new byte[24];
-
-	            padKey(key, 0, tmp, 0);
-	            padKey(key, 7, tmp, 8);
-	            padKey(key, 14, tmp, 16);
-
-	            return tmp;
-	        }
-	        else
-	        {
-	            return key;
-	        }
-	    }
-
-	    /**
-	     * Pad out a key for TDEA, setting odd parity for each byte.
-	     *
-	     * @param keyMaster
-	     * @param keyOff
-	     * @param tmp
-	     * @param tmpOff
-	     */
-	    private void padKey(byte[] keyMaster, int keyOff, byte[] tmp, int tmpOff)
-	    {
-	        tmp[tmpOff + 0] = (byte)(keyMaster[keyOff + 0] & 0xfe);
-	        tmp[tmpOff + 1] = (byte)((keyMaster[keyOff + 0] << 7) | ((keyMaster[keyOff + 1] & 0xfc) >> 1));
-	        tmp[tmpOff + 2] = (byte)((keyMaster[keyOff + 1] << 6) | ((keyMaster[keyOff + 2] & 0xf8) >> 2));
-	        tmp[tmpOff + 3] = (byte)((keyMaster[keyOff + 2] << 5) | ((keyMaster[keyOff + 3] & 0xf0) >> 3));
-	        tmp[tmpOff + 4] = (byte)((keyMaster[keyOff + 3] << 4) | ((keyMaster[keyOff + 4] & 0xe0) >> 4));
-	        tmp[tmpOff + 5] = (byte)((keyMaster[keyOff + 4] << 3) | ((keyMaster[keyOff + 5] & 0xc0) >> 5));
-	        tmp[tmpOff + 6] = (byte)((keyMaster[keyOff + 5] << 2) | ((keyMaster[keyOff + 6] & 0x80) >> 6));
-	        tmp[tmpOff + 7] = (byte)(keyMaster[keyOff + 6] << 1);
-
-	        for (int i = tmpOff; i <= tmpOff + 7; i++)
-	        {
-	            int b = tmp[i];
-	            tmp[i] = (byte)((b & 0xfe) |
-	                            ((((b >> 1) ^
-	                            (b >> 2) ^
-	                            (b >> 3) ^
-	                            (b >> 4) ^
-	                            (b >> 5) ^
-	                            (b >> 6) ^
-	                            (b >> 7)) ^ 0x01) & 0x01));
-	        }
-	    }
-	}
-}
diff --git a/crypto/src/crypto/prng/HMacSP800Drbg.cs b/crypto/src/crypto/prng/HMacSP800Drbg.cs
deleted file mode 100644
index b2903766f..000000000
--- a/crypto/src/crypto/prng/HMacSP800Drbg.cs
+++ /dev/null
@@ -1,196 +0,0 @@
-using System;
-
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Utilities;
-
-namespace Org.BouncyCastle.Crypto.Prng.Drbg
-{
-	/**
-	 * A SP800-90A HMAC DRBG.
-	 */
-	public class HMacSP800Drbg: SP80090Drbg
-	{
-	    private readonly static long       RESEED_MAX = 1L << (48 - 1);
-		private readonly static int        MAX_BITS_REQUEST = 1 << (19 - 1);
-
-	    private byte[] _K;
-	    private byte[] _V;
-	    private long   _reseedCounter;
-	    private IEntropySource _entropySource;
-	    private IMac _hMac;
-	    private int _securityStrength;
-
-	    /**
-	     * Construct a SP800-90A Hash DRBG.
-	     * <p>
-	     * Minimum entropy requirement is the security strength requested.
-	     * </p>
-	     * @param hMac Hash MAC to base the DRBG on.
-	     * @param securityStrength security strength required (in bits)
-	     * @param entropySource source of entropy to use for seeding/reseeding.
-	     * @param personalizationString personalization string to distinguish this DRBG (may be null).
-	     * @param nonce nonce to further distinguish this DRBG (may be null).
-	     */
-	    public HMacSP800Drbg(IMac hMac, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce)
-	    {
-	        if (securityStrength > Utils.getMaxSecurityStrength(hMac))
-	        {
-	            throw new ArgumentException("Requested security strength is not supported by the derivation function");
-	        }
-
-	        if (entropySource.EntropySize < securityStrength)
-	        {
-	            throw new ArgumentException("Not enough entropy for security strength required");
-	        }
-
-	        _securityStrength = securityStrength;
-	        _entropySource = entropySource;
-	        _hMac = hMac;
-
-	        byte[] entropy = getEntropy();
-	        byte[] seedMaterial = Arrays.Concatenate(entropy, nonce, personalizationString);
-
-	        _K = new byte[hMac.GetMacSize()];
-	        _V = new byte[_K.Length];
-	        Arrays.Fill(_V, (byte)1);
-
-	        hmac_DRBG_Update(seedMaterial);
-
-	        _reseedCounter = 1;
-	    }
-
-	    private void hmac_DRBG_Update(byte[] seedMaterial)
-	    {
-	        hmac_DRBG_Update_Func(seedMaterial, (byte)0x00);
-	        if (seedMaterial != null)
-	        {
-	            hmac_DRBG_Update_Func(seedMaterial, (byte)0x01);
-	        }
-	    }
-
-	    private void hmac_DRBG_Update_Func(byte[] seedMaterial, byte vValue)
-	    {
-	        _hMac.Init(new KeyParameter(_K));
-
-	        _hMac.BlockUpdate(_V, 0, _V.Length);
-	        _hMac.Update(vValue);
-
-	        if (seedMaterial != null)
-	        {
-	            _hMac.BlockUpdate(seedMaterial, 0, seedMaterial.Length);
-	        }
-
-	        _hMac.DoFinal(_K, 0);
-
-	        _hMac.Init(new KeyParameter(_K));
-	        _hMac.BlockUpdate(_V, 0, _V.Length);
-
-	        _hMac.DoFinal(_V, 0);
-	    }
-
-	    /**
-	     * Return the block size (in bits) of the DRBG.
-	     *
-	     * @return the number of bits produced on each round of the DRBG.
-	     */
-	    public int BlockSize
-	    {
-			get {
-				return _V.Length * 8;
-			}
-	    }
-
-	    /**
-	     * Populate a passed in array with random data.
-	     *
-	     * @param output output array for generated bits.
-	     * @param additionalInput additional input to be added to the DRBG in this step.
-	     * @param predictionResistant true if a reseed should be forced, false otherwise.
-	     *
-	     * @return number of bits generated, -1 if a reseed required.
-	     */
-	    public int Generate(byte[] output, byte[] additionalInput, bool predictionResistant)
-	    {
-	        int numberOfBits = output.Length * 8;
-
-	        if (numberOfBits > MAX_BITS_REQUEST)
-	        {
-	            throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST);
-	        }
-
-	        if (_reseedCounter > RESEED_MAX)
-	        {
-	            return -1;
-	        }
-
-	        if (predictionResistant)
-	        {
-	            Reseed(additionalInput);
-	            additionalInput = null;
-	        }
-
-	        // 2.
-	        if (additionalInput != null)
-	        {
-	            hmac_DRBG_Update(additionalInput);
-	        }
-
-	        // 3.
-	        byte[] rv = new byte[output.Length];
-
-	        int m = output.Length / _V.Length;
-
-	        _hMac.Init(new KeyParameter(_K));
-
-	        for (int i = 0; i < m; i++)
-	        {
-	            _hMac.BlockUpdate(_V, 0, _V.Length);
-	            _hMac.DoFinal(_V, 0);
-
-	            Array.Copy(_V, 0, rv, i * _V.Length, _V.Length);
-	        }
-
-	        if (m * _V.Length < rv.Length)
-	        {
-					_hMac.BlockUpdate(_V, 0, _V.Length);
-	            _hMac.DoFinal(_V, 0);
-
-	            Array.Copy(_V, 0, rv, m * _V.Length, rv.Length - (m * _V.Length));
-	        }
-
-	        hmac_DRBG_Update(additionalInput);
-
-	        _reseedCounter++;
-
-	        Array.Copy(rv, 0, output, 0, output.Length);
-
-	        return numberOfBits;
-	    }
-
-	    /**
-	      * Reseed the DRBG.
-	      *
-	      * @param additionalInput additional input to be added to the DRBG in this step.
-	      */
-	    public void Reseed(byte[] additionalInput)
-	    {
-	        byte[] entropy = getEntropy();
-	        byte[] seedMaterial = Arrays.Concatenate(entropy, additionalInput);
-
-	        hmac_DRBG_Update(seedMaterial);
-
-	        _reseedCounter = 1;
-	    }
-
-	    private byte[] getEntropy()
-	    {
-	        byte[] entropy = _entropySource.GetEntropy();
-
-	        if (entropy.Length < (_securityStrength + 7) / 8)
-	        {
-	            throw new InvalidOperationException("Insufficient entropy provided by entropy source");
-	        }
-	        return entropy;
-	    }
-	}
-}
diff --git a/crypto/src/crypto/prng/HashSP800Drbg.cs b/crypto/src/crypto/prng/HashSP800Drbg.cs
deleted file mode 100644
index b2b386f17..000000000
--- a/crypto/src/crypto/prng/HashSP800Drbg.cs
+++ /dev/null
@@ -1,295 +0,0 @@
-using System;
-using System.Collections;
-
-using Org.BouncyCastle.Utilities;
-
-namespace Org.BouncyCastle.Crypto.Prng.Drbg
-{
-	/**
-	 * A SP800-90A Hash DRBG.
-	 */
-	public class HashSP800Drbg: SP80090Drbg
-	{
-	    private readonly static byte[]     ONE = { 0x01 };
-
-		private readonly static long       RESEED_MAX = 1L << (48 - 1);
-		private readonly static int        MAX_BITS_REQUEST = 1 << (19 - 1);
-
-		private static readonly IDictionary seedlens = Platform.CreateHashtable();
-
-		static HashSP800Drbg()
-	    {
-				seedlens.Add("SHA-1", 440);
-				seedlens.Add("SHA-224", 440);
-				seedlens.Add("SHA-256", 440);
-				seedlens.Add("SHA-512/256", 440);
-				seedlens.Add("SHA-512/224", 440);
-				seedlens.Add("SHA-384", 888);
-				seedlens.Add("SHA-512", 888);
-
-	    }
-
-	    private IDigest        _digest;
-	    private byte[]         _V;
-	    private byte[]         _C;
-	    private long           _reseedCounter;
-	    private IEntropySource _entropySource;
-	    private int            _securityStrength;
-	    private int            _seedLength;
-
-	    /**
-	     * Construct a SP800-90A Hash DRBG.
-	     * <p>
-	     * Minimum entropy requirement is the security strength requested.
-	     * </p>
-	     * @param digest  source digest to use for DRB stream.
-	     * @param securityStrength security strength required (in bits)
-	     * @param entropySource source of entropy to use for seeding/reseeding.
-	     * @param personalizationString personalization string to distinguish this DRBG (may be null).
-	     * @param nonce nonce to further distinguish this DRBG (may be null).
-	     */
-	    public HashSP800Drbg(IDigest digest, int securityStrength, IEntropySource entropySource, byte[] personalizationString, byte[] nonce)
-	    {
-	        if (securityStrength > Utils.getMaxSecurityStrength(digest))
-	        {
-	            throw new ArgumentException("Requested security strength is not supported by the derivation function");
-	        }
-
-	        if (entropySource.EntropySize < securityStrength)
-	        {
-	            throw new ArgumentException("Not enough entropy for security strength required");
-	        }
-
-	        _digest = digest;
-	        _entropySource = entropySource;
-	        _securityStrength = securityStrength;
-	        _seedLength = (int)seedlens[digest.AlgorithmName];
-
-	        // 1. seed_material = entropy_input || nonce || personalization_string.
-	        // 2. seed = Hash_df (seed_material, seedlen).
-	        // 3. V = seed.
-	        // 4. C = Hash_df ((0x00 || V), seedlen). Comment: Preceed V with a byte
-	        // of zeros.
-	        // 5. reseed_counter = 1.
-	        // 6. Return V, C, and reseed_counter as the initial_working_state
-
-	        byte[] entropy = getEntropy();
-	        byte[] seedMaterial = Arrays.Concatenate(entropy, nonce, personalizationString);
-	        byte[] seed = Utils.hash_df(_digest, seedMaterial, _seedLength);
-
-	        _V = seed;
-	        byte[] subV = new byte[_V.Length + 1];
-	        Array.Copy(_V, 0, subV, 1, _V.Length);
-	        _C = Utils.hash_df(_digest, subV, _seedLength);
-
-	        _reseedCounter = 1;
-	    }
-
-	    /**
-	     * Return the block size (in bits) of the DRBG.
-	     *
-	     * @return the number of bits produced on each internal round of the DRBG.
-	     */
-	    public int BlockSize
-	    {
-			get {
-				return _digest.GetDigestSize () * 8;
-			}
-	    }
-
-	    /**
-	     * Populate a passed in array with random data.
-	     *
-	     * @param output output array for generated bits.
-	     * @param additionalInput additional input to be added to the DRBG in this step.
-	     * @param predictionResistant true if a reseed should be forced, false otherwise.
-	     *
-	     * @return number of bits generated, -1 if a reseed required.
-	     */
-	    public int Generate(byte[] output, byte[] additionalInput, bool predictionResistant)
-	    {
-	        // 1. If reseed_counter > reseed_interval, then return an indication that a
-	        // reseed is required.
-	        // 2. If (additional_input != Null), then do
-	        // 2.1 w = Hash (0x02 || V || additional_input).
-	        // 2.2 V = (V + w) mod 2^seedlen
-	        // .
-	        // 3. (returned_bits) = Hashgen (requested_number_of_bits, V).
-	        // 4. H = Hash (0x03 || V).
-	        // 5. V = (V + H + C + reseed_counter) mod 2^seedlen
-	        // .
-	        // 6. reseed_counter = reseed_counter + 1.
-	        // 7. Return SUCCESS, returned_bits, and the new values of V, C, and
-	        // reseed_counter for the new_working_state.
-	        int numberOfBits = output.Length*8;
-
-	        if (numberOfBits > MAX_BITS_REQUEST)
-	        {
-	            throw new ArgumentException("Number of bits per request limited to " + MAX_BITS_REQUEST);
-	        }
-
-	        if (_reseedCounter > RESEED_MAX)
-	        {
-	            return -1;
-	        }
-
-	        if (predictionResistant)
-	        {   
-	            Reseed(additionalInput);
-	            additionalInput = null;
-	        }
-
-	        // 2.
-	        if (additionalInput != null)
-	        {
-	            byte[] newInput = new byte[1 + _V.Length + additionalInput.Length];
-	            newInput[0] = 0x02;
-	            Array.Copy(_V, 0, newInput, 1, _V.Length);
-	            // TODO: inOff / inLength
-	            Array.Copy(additionalInput, 0, newInput, 1 + _V.Length, additionalInput.Length);
-	            byte[] w = hash(newInput);
-
-	            addTo(_V, w);
-	        }
-	        
-	        // 3.
-	        byte[] rv = hashgen(_V, numberOfBits);
-	        
-	        // 4.
-	        byte[] subH = new byte[_V.Length + 1];
-	        Array.Copy(_V, 0, subH, 1, _V.Length);
-	        subH[0] = 0x03;
-	        
-	        byte[] H = hash(subH);
-	        
-	        // 5.
-	        addTo(_V, H);
-	        addTo(_V, _C);
-	        byte[] c = new byte[4];
-	        c[0] = (byte)(_reseedCounter >> 24);
-	        c[1] = (byte)(_reseedCounter >> 16);
-	        c[2] = (byte)(_reseedCounter >> 8);
-	        c[3] = (byte)_reseedCounter;
-	        
-	        addTo(_V, c);
-
-	        _reseedCounter++;
-
-	        Array.Copy(rv, 0, output, 0, output.Length);
-
-	        return numberOfBits;
-	    }
-
-	    private byte[] getEntropy()
-	    {
-	        byte[] entropy = _entropySource.GetEntropy();
-	        if (entropy.Length < (_securityStrength + 7) / 8)
-	        {
-	            throw new InvalidOperationException("Insufficient entropy provided by entropy source");
-	        }
-	        return entropy;
-	    }
-
-	    // this will always add the shorter length byte array mathematically to the
-	    // longer length byte array.
-	    // be careful....
-	    private void addTo(byte[] longer, byte[] shorter)
-	    {
-	        int carry = 0;
-	        for (int i=1;i <= shorter.Length; i++) // warning
-	        {
-	            int res = (longer[longer.Length-i] & 0xff) + (shorter[shorter.Length-i] & 0xff) + carry;
-	            carry = (res > 0xff) ? 1 : 0;
-	            longer[longer.Length-i] = (byte)res;
-	        }
-	        
-	        for (int i=shorter.Length+1;i <= longer.Length; i++) // warning
-	        {
-	            int res = (longer[longer.Length-i] & 0xff) + carry;
-	            carry = (res > 0xff) ? 1 : 0;
-	            longer[longer.Length-i] = (byte)res;
-	        }
-	    }
-
-	    /**
-	      * Reseed the DRBG.
-	      *
-	      * @param additionalInput additional input to be added to the DRBG in this step.
-	      */
-	    public void Reseed(byte[] additionalInput)
-	    {
-	        // 1. seed_material = 0x01 || V || entropy_input || additional_input.
-	        //
-	        // 2. seed = Hash_df (seed_material, seedlen).
-	        //
-	        // 3. V = seed.
-	        //
-	        // 4. C = Hash_df ((0x00 || V), seedlen).
-	        //
-	        // 5. reseed_counter = 1.
-	        //
-	        // 6. Return V, C, and reseed_counter for the new_working_state.
-	        //
-	        // Comment: Precede with a byte of all zeros.
-	        byte[] entropy = getEntropy();
-	        byte[] seedMaterial = Arrays.Concatenate(ONE, _V, entropy, additionalInput);
-	        byte[] seed = Utils.hash_df(_digest, seedMaterial, _seedLength);
-
-	        _V = seed;
-	        byte[] subV = new byte[_V.Length + 1];
-	        subV[0] = 0x00;
-	        Array.Copy(_V, 0, subV, 1, _V.Length);
-	        _C = Utils.hash_df(_digest, subV, _seedLength);
-
-	        _reseedCounter = 1;
-	    }
-	    
-	    private byte[] hash(byte[] input)
-	    {
-	        byte[] hash = new byte[_digest.GetDigestSize()];
-	        doHash(input, hash);
-	        return hash;
-	    }
-
-	    private void doHash(byte[] input, byte[] output)
-	    {
-	        _digest.BlockUpdate(input, 0, input.Length);
-	        _digest.DoFinal(output, 0);
-	    }
-
-	    // 1. m = [requested_number_of_bits / outlen]
-	    // 2. data = V.
-	    // 3. W = the Null string.
-	    // 4. For i = 1 to m
-	    // 4.1 wi = Hash (data).
-	    // 4.2 W = W || wi.
-	    // 4.3 data = (data + 1) mod 2^seedlen
-	    // .
-	    // 5. returned_bits = Leftmost (requested_no_of_bits) bits of W.
-	    private byte[] hashgen(byte[] input, int lengthInBits)
-	    {
-	        int digestSize = _digest.GetDigestSize();
-	        int m = (lengthInBits / 8) / digestSize;
-
-	        byte[] data = new byte[input.Length];
-	        Array.Copy(input, 0, data, 0, input.Length);
-
-	        byte[] W = new byte[lengthInBits / 8];
-
-	        byte[] dig = new byte[_digest.GetDigestSize()];
-	        for (int i = 0; i <= m; i++)
-	        {
-	            doHash(data, dig);
-
-	            int bytesToCopy = ((W.Length - i * dig.Length) > dig.Length)
-	                    ? dig.Length
-	                    : (W.Length - i * dig.Length);
-	            Array.Copy(dig, 0, W, i * dig.Length, bytesToCopy);
-
-	            addTo(data, ONE);
-	        }
-
-	        return W;
-	    }    
-	}
-}
diff --git a/crypto/src/crypto/prng/IEntropySource.cs b/crypto/src/crypto/prng/IEntropySource.cs
new file mode 100644
index 000000000..33ce1b801
--- /dev/null
+++ b/crypto/src/crypto/prng/IEntropySource.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+	/// <summary>
+	/// Base interface describing an entropy source for a DRGB.
+	/// </summary>
+	public interface IEntropySource
+	{
+		/// <summary>
+		/// Return whether or not this entropy source is regarded as prediction resistant.
+		/// </summary>
+		/// <value><c>true</c> if this instance is prediction resistant; otherwise, <c>false</c>.</value>
+		bool IsPredictionResistant { get; }
+
+		/// <summary>
+		/// Return a byte array of entropy.
+		/// </summary>
+		/// <returns>The entropy bytes.</returns>
+		byte[] GetEntropy();
+
+		/// <summary>
+		/// Return the number of bits of entropy this source can produce.
+		/// </summary>
+		/// <value>The size, in bits, of the return value of getEntropy.</value>
+		int EntropySize { get; }
+	}
+}
+
diff --git a/crypto/src/crypto/prng/IEntropySourceProvider.cs b/crypto/src/crypto/prng/IEntropySourceProvider.cs
new file mode 100644
index 000000000..990c6497b
--- /dev/null
+++ b/crypto/src/crypto/prng/IEntropySourceProvider.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /// <summary>
+    /// Base interface describing a provider of entropy sources.
+    /// </summary>
+    public interface IEntropySourceProvider
+    {
+        /// <summary>
+        /// Return an entropy source providing a block of entropy.
+        /// </summary>
+        /// <param name="bitsRequired">The size of the block of entropy required.</param>
+        /// <returns>An entropy source providing bitsRequired blocks of entropy.</returns>
+        IEntropySource Get(int bitsRequired);
+    }
+}
diff --git a/crypto/src/crypto/prng/drbg/SP80090Drbg.cs b/crypto/src/crypto/prng/drbg/ISP80090Drbg.cs
index c39cf365f..c39cf365f 100644
--- a/crypto/src/crypto/prng/drbg/SP80090Drbg.cs
+++ b/crypto/src/crypto/prng/drbg/ISP80090Drbg.cs