Mercurial > projects > dcrypt
view dcrypt/crypto/Hash.d @ 28:ad687db713a4
Further reworked the code for hash padding. Replaced all instances of 'char[]' with 'string' and removed a few 'const' modifiers as per Glenn Haecker's patch for D2 compatibility. Updated CONTRIBUTORS file.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sun, 10 May 2009 22:38:48 -0400 |
parents | 8b5eaf3c2979 |
children | b9ba770b8f16 |
line wrap: on
line source
/** * 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.ByteConverter; public import dcrypt.misc.Bitwise; /** Base class for all cryptographic hash functions */ class Hash { private const enum { MODE_MD=0, // MDx, RipeMD, etc MODE_SHA, MODE_TIGER } protected { ubyte[] buffer; ulong bytes; uint 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 string name(); /** Returns: A copy of this hash object. */ abstract Hash copy(); /** * Introduce data into the hash function. * * Params: * input_ = Data to be processed. * * Returns: Self */ Hash update(void[] input_) { ubyte[] input = cast(ubyte[]) input_; foreach (ubyte i; input) { bytes++; buffer[index++] = i; if (index == blockSize) { transform(buffer); index = 0; } } return this; } /** 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 bits = bytes << 3; // Add the pad marker buffer[index++] = ((mode == MODE_TIGER) ? 0x01 : 0x80); if (index == blockSize) { transform(buffer); index = 0; } // Pad with null bytes while ((index & (blockSize - 1)) != (blockSize - (blockSize >> 3))) { buffer[index++] = 0; if (index == blockSize) { transform(buffer); index = 0; } } // Length padding for (int i = 0; i < blockSize; i+=8, bits>>=8) // little endian buffer[index++] = bits; if (mode == MODE_SHA) buffer[(buffer.length-(blockSize >> 3))..buffer.length].reverse; // big endian transform(buffer); index = 0; } /** * Process all data, pad and finalize. This method will * reset the digest to its original state for 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. */ string hexDigest() { return ByteConverter.hexEncode(digest()); } /** Reset hash to initial state. */ void reset() { bytes = index = 0; } }