Mercurial > projects > dcrypt
comparison dcrypt/crypto/macs/HMAC.d @ 4:3de3a2de13a0
Added MAC base class and HMAC. Added StreamCipherWrapper as part of the work on the high-level cipher API. Running on fumes, so hopefully there isn't too much stupid mixed into the code.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Thu, 14 Aug 2008 01:45:24 -0400 |
parents | |
children | 5cb17e09d685 |
comparison
equal
deleted
inserted
replaced
3:a5789a7b3b3b | 4:3de3a2de13a0 |
---|---|
1 /** | |
2 * This file is part of the dcrypt project. | |
3 * | |
4 * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved. | |
5 * License: MIT | |
6 * Authors: Thomas Dixon | |
7 */ | |
8 | |
9 module dcrypt.crypto.macs.HMAC; | |
10 | |
11 import dcrypt.crypto.MAC; | |
12 import dcrypt.crypto.Hash; | |
13 import dcrypt.crypto.params.SymmetricKey; | |
14 import dcrypt.crypto.errors.NotInitializedError; | |
15 | |
16 version (UnitTest) { | |
17 import dcrypt.crypto.hashes.SHA1; | |
18 } | |
19 | |
20 /** Conforms: RFC2104 */ | |
21 class HMAC : MAC { | |
22 private { | |
23 ubyte[] ipad, opad, key; | |
24 Hash inner, outer; | |
25 bool initialized; | |
26 } | |
27 | |
28 this (Hash hash, void[] key=null) { | |
29 hash.reset(); | |
30 | |
31 inner = hash; | |
32 outer = hash.copy(); | |
33 | |
34 ipad = new ubyte[blockSize]; | |
35 opad = new ubyte[blockSize]; | |
36 | |
37 reset(); | |
38 | |
39 if (key) | |
40 init(new SymmetricKey(key)); // I'm lazy. | |
41 } | |
42 | |
43 void init(CipherParameters params) { | |
44 SymmetricKey keyParams = cast(SymmetricKey)params; | |
45 if (!keyParams) | |
46 throw new InvalidParameterError( | |
47 name()~": Invalid parameter passed to init"); | |
48 | |
49 if (keyParams.key.length > blockSize) { | |
50 inner.update(keyParams.key); | |
51 key = inner.digest(); | |
52 } else | |
53 key = keyParams.key; | |
54 | |
55 foreach (uint i, ubyte j; key) { | |
56 ipad[i] ^= j; | |
57 opad[i] ^= j; | |
58 } | |
59 | |
60 inner.update(ipad); | |
61 outer.update(opad); | |
62 | |
63 initialized = true; | |
64 } | |
65 | |
66 void update(void[] input_) { | |
67 if (!initialized) | |
68 throw new NotInitializedError( | |
69 name()~": MAC not initialized."); | |
70 inner.update(input_); | |
71 } | |
72 | |
73 char[] name() { | |
74 return inner.name~"/HMAC"; | |
75 } | |
76 | |
77 void reset() { | |
78 ipad[] = 0x36; | |
79 opad[] = 0x5c; | |
80 | |
81 inner.reset(); | |
82 outer.reset(); | |
83 } | |
84 | |
85 uint blockSize() { | |
86 return inner.blockSize; | |
87 } | |
88 | |
89 uint macSize() { | |
90 return inner.digestSize; | |
91 } | |
92 | |
93 ubyte[] finish() { | |
94 outer.update(inner.digest()); | |
95 ubyte[] r = outer.digest(); | |
96 reset(); | |
97 return r; | |
98 } | |
99 | |
100 char[] hexFinish() { | |
101 return Util.ubytesToHex(finish()); | |
102 } | |
103 | |
104 HMAC copy() { | |
105 // Ghetto... oh so ghetto :\ | |
106 HMAC h = new HMAC(inner.copy()); | |
107 h.inner = inner.copy(); | |
108 h.outer = outer.copy(); | |
109 h.initialized = true; | |
110 return h; | |
111 } | |
112 | |
113 version (UnitTest) { | |
114 unittest { | |
115 static char[][] test_keys = [ | |
116 "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", | |
117 "4a656665", // Jefe? | |
118 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", | |
119 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"~ | |
120 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"~ | |
121 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"~ | |
122 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" | |
123 ]; | |
124 | |
125 static char[][] test_inputs = [ | |
126 "4869205468657265", | |
127 "7768617420646f2079612077616e7420666f72206e6f7468696e673f", | |
128 "dd", | |
129 "54657374205573696e67204c6172676572205468616e20426c6f63"~ | |
130 "6b2d53697a65204b6579202d2048617368204b6579204669727374" | |
131 ]; | |
132 | |
133 static const int[] test_repeat = [ | |
134 1, 1, 50, 1 | |
135 ]; | |
136 | |
137 static const char[][] test_results = [ | |
138 "b617318655057264e28bc0b6fb378c8ef146be00", | |
139 "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", | |
140 "125d7342b9ac11cd91a39af48aa17b4f63f175d3", | |
141 "aa4ae5e15272d00e95705637ce8a3b55ed402112" | |
142 ]; | |
143 | |
144 HMAC h = new HMAC(new SHA1()); | |
145 foreach (uint i, char[] k; test_keys) { | |
146 h.init(new SymmetricKey(Util.hexToUbytes(k))); | |
147 for (int j = 0; j < test_repeat[i]; j++) | |
148 h.update(Util.hexToUbytes(test_inputs[i])); | |
149 char[] mac = h.hexFinish(); | |
150 assert(mac == test_results[i], | |
151 h.name~": ("~mac~") != ("~test_results[i]~")"); | |
152 } | |
153 } | |
154 } | |
155 } |