diff dcrypt/crypto/Hash.d @ 0:0e08791a1418

Initial import.
author Thomas Dixon <reikon@reikon.us>
date Sun, 10 Aug 2008 14:20:17 -0400
parents
children 71aae178f89a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcrypt/crypto/Hash.d	Sun Aug 10 14:20:17 2008 -0400
@@ -0,0 +1,110 @@
+/**
+ * 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.Hash;
+
+public import dcrypt.misc.Util;
+
+/** Base class for all cryptographic hash functions */
+class Hash {
+	private const enum {
+		MODE_MD=0, // MDx, RipeMD, etc
+		MODE_SHA,
+		MODE_TIGER
+	}
+	private ubyte[] buffer;
+	uint bytes,
+		 index;
+	
+	this (void[] input_=null) {
+		buffer = new ubyte[blockSize];
+        ubyte[] input = cast(ubyte[]) input_;
+        if (input)
+            update(input);
+	}
+
+	/** Returns: The block size of the hash function in bytes. */
+	abstract uint blockSize();
+	
+	/** Returns: The output size of the hash function in bytes. */
+	abstract uint digestSize();
+	
+	/** Returns: The name of the algorithm we're implementing. */
+	abstract char[] name();
+	
+	/**
+	 * Introduce data into the hash function.
+	 * 
+	 * Params:
+	 *     input_ = Data to be processed.
+	 */
+	void update(void[] input_) {
+		ubyte[] input = cast(ubyte[]) input_;
+		foreach (ubyte i; input)
+			update(i);
+	}
+	
+	void update(ubyte input) {
+		bytes++;
+		buffer[index++] = input;
+		if (index == blockSize) {
+			transform(buffer);
+			index = 0;
+		}
+	}
+	
+	/** Hash function's internal transformation. */
+	protected abstract void transform(ubyte[] input);
+    
+	/** 
+	 * Pad message in the respective manner.
+	 * 
+	 * Params:
+	 *     mode = Mode constant dictating in which manner
+	 *            to pad the message.
+	 */
+	protected void padMessage(uint mode) {
+		ulong length = bytes << 3;
+		
+		update(((mode == MODE_TIGER) ? 0x01 : 0x80));
+        uint count = (blockSize-(blockSize >> 3));
+        if (index > count)
+            while (index != 0)
+                    update(0);
+        while (index < (count + ((blockSize == 128) ? 8 : 0)))
+            update(0);
+        if (mode == MODE_SHA)
+            for (int i = 56; i >= 0; i-=8) // big endian
+                update(length >> i);
+        else
+            for (int i = 0; i < 64; i+=8) // little endian
+                update(length >> i);
+    }
+    
+    /**
+     * Process all data, pad and finalize. This method will
+     * reset the digest to its original state ofr subsequent use.
+     * 
+     * Returns: Binary representation of the hash in bytes.
+     */
+    abstract ubyte[] digest();
+    
+    /**
+     * Same as digest() but returns hash value in hex.
+     * 
+     * Returns: Representation of the final hash value in hex.
+     */
+    char[] hexDigest() {
+        return Util.ubytesToHex(digest());
+    }
+    
+    /** Reset hash to initial state. */
+    void reset() {
+        bytes = index = 0;
+    }
+}