Mercurial > projects > dcrypt
comparison dcrypt/crypto/prngs/PRNGFromHash.d @ 27:8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sat, 09 May 2009 23:29:20 -0400 |
parents | 703901987976 |
children | ad687db713a4 |
comparison
equal
deleted
inserted
replaced
26:176c933827a8 | 27:8b5eaf3c2979 |
---|---|
10 | 10 |
11 import dcrypt.crypto.PRNG; | 11 import dcrypt.crypto.PRNG; |
12 import dcrypt.crypto.Hash; | 12 import dcrypt.crypto.Hash; |
13 | 13 |
14 /** Creates a PRNG from a hash function. */ | 14 /** Creates a PRNG from a hash function. */ |
15 class PRNGFromHash : PRNG { | 15 class PRNGFromHash : PRNG |
16 private { | 16 { |
17 private | |
18 { | |
17 const uint COUNTER_SIZE = 32; | 19 const uint COUNTER_SIZE = 32; |
18 | 20 |
19 Hash hash; | 21 Hash hash; |
20 ubyte[] counter, | 22 ubyte[] counter, |
21 seed, | 23 seed, |
22 state; | 24 state; |
23 uint index; | 25 uint index; |
24 } | 26 } |
25 | 27 |
26 char[] name() { | 28 char[] name() |
29 { | |
27 if (hash is null) | 30 if (hash is null) |
28 throw new NotInitializedError(name()~": PRNG not initialized"); | 31 throw new NotInitializedError(name()~": PRNG not initialized"); |
29 | 32 |
30 return hash.name~"PRNG"; | 33 return hash.name~"PRNG"; |
31 } | 34 } |
32 | 35 |
33 this(Hash hash) { | 36 this(Hash hash) |
37 { | |
34 if (hash is null) | 38 if (hash is null) |
35 throw new InvalidParameterError( | 39 throw new InvalidParameterError( |
36 name()~": Invalid parameter passed to constructor."); | 40 name()~": Invalid parameter passed to constructor."); |
41 | |
37 this.hash = hash; | 42 this.hash = hash; |
38 this.hash.reset(); | 43 this.hash.reset(); |
39 | 44 |
40 counter = new ubyte[COUNTER_SIZE]; | 45 counter = new ubyte[COUNTER_SIZE]; |
41 seed = new ubyte[this.hash.digestSize]; | 46 seed = new ubyte[this.hash.digestSize]; |
42 state = new ubyte[this.hash.digestSize]; | 47 state = new ubyte[this.hash.digestSize]; |
43 | 48 |
44 index = this.hash.digestSize; // to force updating of the state | 49 index = this.hash.digestSize; // to force updating of the state |
45 } | 50 } |
46 | 51 |
47 void addEntropy(ubyte[] input) { | 52 void addEntropy(ubyte[] input) |
48 if (!_initialized) { | 53 { |
54 if (!_initialized) | |
55 { | |
49 hash.update(input); | 56 hash.update(input); |
50 seed = hash.digest(); | 57 seed = hash.digest(); |
51 _initialized = true; | 58 _initialized = true; |
52 } else | 59 } else |
53 throw new NotSupportedError(name()~": state is immutable once initialized"); | 60 throw new NotSupportedError(name()~": state is immutable once initialized"); |
54 } | 61 } |
55 | 62 |
56 uint read(ubyte[] output) { | 63 uint read(ubyte[] output) |
64 { | |
57 if (!_initialized) | 65 if (!_initialized) |
58 throw new NotInitializedError(name()~": PRNG not initialized"); | 66 throw new NotInitializedError(name()~": PRNG not initialized"); |
59 | 67 |
60 for (uint i = 0; i < output.length; i++) { | 68 for (uint i = 0; i < output.length; i++) |
61 if (index == state.length) { | 69 { |
70 if (index == state.length) | |
71 { | |
62 hash.update(seed); | 72 hash.update(seed); |
63 hash.update(counter); | 73 hash.update(counter); |
64 state = hash.digest(); | 74 state = hash.digest(); |
65 | 75 |
66 // Increment the counter | 76 // Increment the counter |
69 | 79 |
70 index = 0; | 80 index = 0; |
71 } | 81 } |
72 output[i] = state[index++]; | 82 output[i] = state[index++]; |
73 } | 83 } |
84 | |
74 return output.length; | 85 return output.length; |
75 } | 86 } |
76 } | 87 } |