/**
   * Generates a user-specified number of random bytes.
   *
   * @param bytes the array to be filled in with random bytes.
   */
  public synchronized void engineNextBytes(byte[] result) {
    int index = 0;
    int todo;
    byte[] output = remainder;

    if (state == null) {
      if (seeder == null) {
        seeder = new SecureRandom(SeedGenerator.getSystemEntropy());
        seeder.engineSetSeed(engineGenerateSeed(DIGEST_SIZE));
      }

      byte[] seed = new byte[DIGEST_SIZE];
      seeder.engineNextBytes(seed);
      state = digest.digest(seed);
    }

    // Use remainder from last time
    int r = remCount;
    if (r > 0) {
      // How many bytes?
      todo =
          (result.length - index) < (DIGEST_SIZE - r) ? (result.length - index) : (DIGEST_SIZE - r);
      // Copy the bytes, zero the buffer
      for (int i = 0; i < todo; i++) {
        result[i] = output[r];
        output[r++] = 0;
      }
      remCount += todo;
      index += todo;
    }

    // If we need more bytes, make them.
    while (index < result.length) {
      // Step the state
      digest.update(state);
      output = digest.digest();
      updateState(state, output);

      // How many bytes?
      todo = (result.length - index) > DIGEST_SIZE ? DIGEST_SIZE : result.length - index;
      // Copy the bytes, zero the buffer
      for (int i = 0; i < todo; i++) {
        result[index++] = output[i];
        output[i] = 0;
      }
      remCount += todo;
    }

    // Store remainder for next time
    remainder = output;
    remCount %= DIGEST_SIZE;
  }
Beispiel #2
0
 static {
   /*
    * Call to SeedGenerator.generateSeed() to add additional
    * seed material (likely from the Native implementation).
    */
   seeder = new SecureRandom(SeedGenerator.getSystemEntropy());
   byte[] b = new byte[DIGEST_SIZE];
   SeedGenerator.generateSeed(b);
   seeder.engineSetSeed(b);
 }