Mercurial > projects > dcrypt
view dcrypt/crypto/Hash.d @ 32:2b4bccdc8387
Added version() statements to play nice with D2's current feelings about const. Changed a few methods (addEntropy and read in the base PRNG class, and the constructor for ParametersWithIV) to accept void[] in place of ubyte[].
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Tue, 12 May 2009 22:09:33 -0400 |
parents | 21847420b1ac |
children | b9f8aa42a547 |
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); } /** Play nice with D2's idea of const. */ version (D_Version2) { this (string input_) { return this(cast(ubyte[])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_; uint i, partLength; index = bytes & (blockSize - 1); bytes += input.length; partLength = blockSize - index; if (input.length >= partLength) { buffer[index..index+partLength] = input[0..partLength]; transform(buffer); for (i = partLength; i + (blockSize - 1) < input.length; i+=blockSize) transform(input[i..i+blockSize]); index = 0; } else i = 0; if (input.length - i) buffer[index..index+(input.length-i)] = input[i..input.length]; return this; } /** Play nice with D2's idea of const. */ version (D_Version2) { Hash update(string input_) { return update(cast(ubyte[])input_); } } /** 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; index = bytes & (blockSize - 1); // 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. */ char[] hexDigest() { return ByteConverter.hexEncode(digest()); } /** Reset hash to initial state. */ void reset() { bytes = index = 0; } }