view dcrypt/crypto/Hash.d @ 2:71aae178f89a

Added copy() to hash functions. Modified some code style.
author Thomas Dixon <reikon@reikon.us>
date Wed, 13 Aug 2008 22:01:19 -0400
parents 0e08791a1418
children cff9960a019c
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.Util;

/** 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;
        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();
    
    /** Returns: A copy of this hash object. */
    abstract Hash copy();

	/**
	 * 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;
    }
}