01: package org.bouncycastle.crypto.prng;
02:
03: import org.bouncycastle.crypto.Digest;
04:
05: /**
06: * Random generation based on the digest with counter. Calling addSeedMaterial will
07: * always increase the entropy of the hash.
08: * <p>
09: * Internal access to the digest is synchronized so a single one of these can be shared.
10: * </p>
11: */
12: public class DigestRandomGenerator implements RandomGenerator {
13: private long counter;
14: private Digest digest;
15: private byte[] state;
16:
17: // public constructors
18: public DigestRandomGenerator(Digest digest) {
19: this .digest = digest;
20: this .state = new byte[digest.getDigestSize()];
21: this .counter = 1;
22: }
23:
24: public void addSeedMaterial(byte[] inSeed) {
25: synchronized (this ) {
26: digestUpdate(inSeed);
27: }
28: }
29:
30: public void addSeedMaterial(long rSeed) {
31: synchronized (this ) {
32: for (int i = 0; i != 8; i++) {
33: digestUpdate((byte) rSeed);
34: rSeed >>>= 8;
35: }
36: }
37: }
38:
39: public void nextBytes(byte[] bytes) {
40: nextBytes(bytes, 0, bytes.length);
41: }
42:
43: public void nextBytes(byte[] bytes, int start, int len) {
44: synchronized (this ) {
45: int stateOff = 0;
46:
47: digestDoFinal(state);
48:
49: int end = start + len;
50: for (int i = start; i != end; i++) {
51: if (stateOff == state.length) {
52: digestUpdate(counter++);
53: digestUpdate(state);
54: digestDoFinal(state);
55: stateOff = 0;
56: }
57: bytes[i] = state[stateOff++];
58: }
59:
60: digestUpdate(counter++);
61: digestUpdate(state);
62: }
63: }
64:
65: private void digestUpdate(long seed) {
66: for (int i = 0; i != 8; i++) {
67: digest.update((byte) seed);
68: seed >>>= 8;
69: }
70: }
71:
72: private void digestUpdate(byte[] inSeed) {
73: digest.update(inSeed, 0, inSeed.length);
74: }
75:
76: private void digestDoFinal(byte[] result) {
77: digest.doFinal(result, 0);
78: }
79: }
|