diff dcrypt/crypto/prngs/PRNGFromHash.d @ 14:5ce3012f1def

Removed some redundancy in code. Added NotSupportedError, a base PRNG class and a class which creates a PRNG from a hash function. Changed the MAC class' finalization methods to digest and hexDigest instead of finish and hexFinish respectively. Also added a base Checksum class, crc32 and adler32 in dcrypt.misc as per request.
author Thomas Dixon <reikon@reikon.us>
date Tue, 18 Nov 2008 18:03:40 -0500
parents
children 703901987976
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcrypt/crypto/prngs/PRNGFromHash.d	Tue Nov 18 18:03:40 2008 -0500
@@ -0,0 +1,74 @@
+/**
+ * This file is part of the dcrypt project.
+ *
+ * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved.
+ * License:   MIT
+ * Authors:   Thomas Dixon
+ */
+
+module dcrypt.crypto.prngs.PRNGFromHash;
+
+import dcrypt.crypto.PRNG;
+import dcrypt.crypto.Hash;
+import dcrypt.crypto.hashes.SHA256;
+
+/** Creates a PRNG from a hash function. */
+class PRNGFromHash : PRNG {
+    private {
+        const uint COUNTER_SIZE = 32;
+        
+        Hash hash;
+        ubyte[] counter,
+                seed,
+                state;
+        uint index;
+    }
+    
+    char[] name() {
+        if (hash is null)
+            throw new NotInitializedError(name()~": PRNG not initialized");
+        
+        return hash.name~"PRNG";
+    }
+    
+    this(Hash hash=null) {
+        this.hash = (hash is null) ? new SHA256() : hash;
+        this.hash.reset();
+        
+        counter = new ubyte[COUNTER_SIZE];
+        seed = new ubyte[this.hash.digestSize];
+        state = new ubyte[this.hash.digestSize];
+        
+        index = this.hash.digestSize; // to force updating of the state
+    }
+    
+    void addEntropy(ubyte[] input) {
+        if (!_initialized) {
+            hash.update(input);
+            seed = hash.digest();
+            _initialized = true;
+        } else
+            throw new NotSupportedError(name()~": state is immutable once initialized");
+    }
+    
+    uint read(ubyte[] output) {
+        if (!_initialized)
+            throw new NotInitializedError(name()~": PRNG not initialized");
+        
+        for (uint i = 0; i < output.length; i++) {
+            if (index == state.length) {
+                hash.update(seed);
+                hash.update(counter);
+                state = hash.digest();
+                
+                // Increment the counter
+                for (uint j = COUNTER_SIZE-1; j >= 0; j--)
+                    if (++counter[j]) break;
+                
+                index = 0;
+            }
+            output[i] = state[index++];
+        }
+        return output.length;
+    }
+}