Mercurial > projects > dcrypt
view dcrypt/crypto/macs/HMAC.d @ 6:5cb17e09d685
Minor edits to the unittests of hash functions and ciphers. Added AES and test vectors.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sat, 16 Aug 2008 22:43:22 -0400 |
parents | 3de3a2de13a0 |
children | 5ce3012f1def |
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.macs.HMAC; import dcrypt.crypto.MAC; import dcrypt.crypto.Hash; import dcrypt.crypto.params.SymmetricKey; import dcrypt.crypto.errors.NotInitializedError; version (UnitTest) { import dcrypt.crypto.hashes.SHA1; } /** * Implementation of Keyed-Hash Message Authentication Code (HMAC) * * Conforms: RFC 2104 * References: http://www.faqs.org/rfcs/rfc2104.html */ class HMAC : MAC { private { ubyte[] ipad, opad, key; Hash inner, outer; bool initialized; } this (Hash hash, void[] key=null) { hash.reset(); inner = hash; outer = hash.copy(); ipad = new ubyte[blockSize]; opad = new ubyte[blockSize]; reset(); if (key) init(new SymmetricKey(key)); // I'm lazy. } void init(CipherParameters params) { SymmetricKey keyParams = cast(SymmetricKey)params; if (!keyParams) throw new InvalidParameterError( name()~": Invalid parameter passed to init"); if (keyParams.key.length > blockSize) { inner.update(keyParams.key); key = inner.digest(); } else key = keyParams.key; foreach (uint i, ubyte j; key) { ipad[i] ^= j; opad[i] ^= j; } inner.update(ipad); outer.update(opad); initialized = true; } void update(void[] input_) { if (!initialized) throw new NotInitializedError( name()~": MAC not initialized."); inner.update(input_); } char[] name() { return inner.name~"/HMAC"; } void reset() { ipad[] = 0x36; opad[] = 0x5c; inner.reset(); outer.reset(); } uint blockSize() { return inner.blockSize; } uint macSize() { return inner.digestSize; } ubyte[] finish() { outer.update(inner.digest()); ubyte[] r = outer.digest(); reset(); return r; } char[] hexFinish() { return Util.ubytesToHex(finish()); } HMAC copy() { // Ghetto... oh so ghetto :\ HMAC h = new HMAC(inner.copy()); h.inner = inner.copy(); h.outer = outer.copy(); h.initialized = true; return h; } version (UnitTest) { unittest { static char[][] test_keys = [ "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4a656665", // Jefe? "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"~ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"~ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"~ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ]; static char[][] test_inputs = [ "4869205468657265", "7768617420646f2079612077616e7420666f72206e6f7468696e673f", "dd", "54657374205573696e67204c6172676572205468616e20426c6f63"~ "6b2d53697a65204b6579202d2048617368204b6579204669727374" ]; static const int[] test_repeat = [ 1, 1, 50, 1 ]; static const char[][] test_results = [ "b617318655057264e28bc0b6fb378c8ef146be00", "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", "125d7342b9ac11cd91a39af48aa17b4f63f175d3", "aa4ae5e15272d00e95705637ce8a3b55ed402112" ]; HMAC h = new HMAC(new SHA1()); foreach (uint i, char[] k; test_keys) { h.init(new SymmetricKey(Util.hexToUbytes(k))); for (int j = 0; j < test_repeat[i]; j++) h.update(Util.hexToUbytes(test_inputs[i])); char[] mac = h.hexFinish(); assert(mac == test_results[i], h.name~": ("~mac~") != ("~test_results[i]~")"); } } } }