/** * 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; }
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); }