Mercurial > projects > dcrypt
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; + } +}