Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.bouncycastle.crypto.prng.drbg;
  
  
A SP800-90A Hash DRBG.
 
 public class HashSP800DRBG
     implements SP80090DRBG
 {
     private final static byte[]     ONE = { 0x01 };
 
     private final static long       RESEED_MAX = 1L << (48 - 1);
     private final static int        MAX_BITS_REQUEST = 1 << (19 - 1);
 
     private final static Hashtable  seedlens = new Hashtable();
 
     static
     {
         .put("SHA-1", Integers.valueOf(440));
         .put("SHA-224", Integers.valueOf(440));
         .put("SHA-256", Integers.valueOf(440));
         .put("SHA-512/256", Integers.valueOf(440));
         .put("SHA-512/224", Integers.valueOf(440));
         .put("SHA-384", Integers.valueOf(888));
         .put("SHA-512", Integers.valueOf(888));
     }
 
     private Digest        _digest;
     private byte[]        _V;
     private byte[]        _C;
     private long          _reseedCounter;
     private EntropySource _entropySource;
     private int           _securityStrength;
     private int           _seedLength;

    
Construct a SP800-90A Hash DRBG.

Minimum entropy requirement is the security strength requested.

Parameters:
digest source digest to use for DRB stream.
securityStrength security strength required (in bits)
entropySource source of entropy to use for seeding/reseeding.
personalizationString personalization string to distinguish this DRBG (may be null).
nonce nonce to further distinguish this DRBG (may be null).
 
     public HashSP800DRBG(Digest digestint securityStrengthEntropySource entropySourcebyte[] personalizationStringbyte[] nonce)
     {
         if (securityStrength > Utils.getMaxSecurityStrength(digest))
         {
             throw new IllegalArgumentException("Requested security strength is not supported by the derivation function");
         }
 
         if (entropySource.entropySize() < securityStrength)
         {
             throw new IllegalArgumentException("Not enough entropy for security strength required");
         }
 
          = digest;
          = entropySource;
          = securityStrength;
          = ((Integer).get(digest.getAlgorithmName())).intValue();
 
         // 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 = entropySource.getEntropy();
         byte[] seedMaterial = Arrays.concatenate(entropynoncepersonalizationString);
         byte[] seed = Utils.hash_df(seedMaterial);
 
          = seed;
         byte[] subV = new byte[. + 1];
         System.arraycopy(, 0, subV, 1, .);
          = Utils.hash_df(subV);
 
          = 1;
     }

    
Return the block size (in bits) of the DRBG.

Returns:
the number of bits produced on each internal round of the DRBG.
 
     public int getBlockSize()
     {
         return .getDigestSize() * 8;
     }

    
Populate a passed in array with random data.

Parameters:
output output array for generated bits.
additionalInput additional input to be added to the DRBG in this step.
predictionResistant true if a reseed should be forced, false otherwise.
Returns:
number of bits generated, -1 if a reseed required.
    public int generate(byte[] outputbyte[] additionalInputboolean 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 > )
        {
            throw new IllegalArgumentException("Number of bits per request limited to " + );
        }
        if ( > )
        {
            return -1;
        }
        if (predictionResistant)
        {   
            reseed(additionalInput);
            additionalInput = null;
        }
        // 2.
        if (additionalInput != null)
        {
            byte[] newInput = new byte[1 + . + additionalInput.length];
            newInput[0] = 0x02;
            System.arraycopy(, 0, newInput, 1, .);
            // TODO: inOff / inLength
            System.arraycopy(additionalInput, 0, newInput, 1 + .additionalInput.length);
            byte[] w = hash(newInput);
            addTo(w);
        }
        
        // 3.
        byte[] rv = hashgen(numberOfBits);
        
        // 4.
        byte[] subH = new byte[. + 1];
        System.arraycopy(, 0, subH, 1, .);
        subH[0] = 0x03;
        
        byte[] H = hash(subH);
        
        // 5.
        addTo(H);
        addTo();
        byte[] c = new byte[4];
        c[0] = (byte)( >> 24);
        c[1] = (byte)( >> 16);
        c[2] = (byte)( >> 8);
        c[3] = (byte);
        
        addTo(c);
        ++;
        System.arraycopy(rv, 0, output, 0, output.length);
        return numberOfBits;
    }
    // this will always add the shorter length byte array mathematically to the
    // longer length byte array.
    // be careful....
    private void addTo(byte[] longerbyte[] shorter)
    {
        int carry = 0;
        for (int i=1;i <= shorter.lengthi++) // 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.lengthi++) // warning
        {
            int res = (longer[longer.length-i] & 0xff) + carry;
            carry = (res > 0xff) ? 1 : 0;
            longer[longer.length-i] = (byte)res;
        }
    }

    
Reseed the DRBG.

Parameters:
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(entropyadditionalInput);
        byte[] seed = Utils.hash_df(seedMaterial);
         = seed;
        byte[] subV = new byte[. + 1];
        subV[0] = 0x00;
        System.arraycopy(, 0, subV, 1, .);
         = Utils.hash_df(subV);
         = 1;
    }
    
    private byte[] hash(byte[] input)
    {
        byte[] hash = new byte[.getDigestSize()];
        doHash(inputhash);
        return hash;
    }
    private void doHash(byte[] inputbyte[] output)
    {
        .update(input, 0, input.length);
        .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[] inputint lengthInBits)
    {
        int digestSize = .getDigestSize();
        int m = (lengthInBits / 8) / digestSize;
        byte[] data = new byte[input.length];
        System.arraycopy(input, 0, data, 0, input.length);
        byte[] W = new byte[lengthInBits / 8];
        byte[] dig = new byte[.getDigestSize()];
        for (int i = 0; i <= mi++)
        {
            doHash(datadig);
            int bytesToCopy = ((W.length - i * dig.length) > dig.length)
                    ? dig.length
                    : (W.length - i * dig.length);
            System.arraycopy(dig, 0, Wi * dig.lengthbytesToCopy);
            addTo(data);
        }
        return W;
    }    
New to GrepCode? Check out our FAQ X