comparison dcrypt/crypto/macs/HMAC.d @ 15:0de48552be35

Added LimitReachedError and PBKDF2. Fixed some errors with the previous commit in PRNGFromHash, etc. Re-implemented HMAC. Changed the name() format of HMAC and PBKDF2.
author Thomas Dixon <reikon@reikon.us>
date Wed, 19 Nov 2008 19:30:52 -0500
parents 5ce3012f1def
children 4589f8c5eb3c
comparison
equal deleted inserted replaced
14:5ce3012f1def 15:0de48552be35
24 * References: http://www.faqs.org/rfcs/rfc2104.html 24 * References: http://www.faqs.org/rfcs/rfc2104.html
25 */ 25 */
26 class HMAC : MAC { 26 class HMAC : MAC {
27 private { 27 private {
28 ubyte[] ipad, opad, key; 28 ubyte[] ipad, opad, key;
29 Hash inner, outer; 29 Hash hash;
30 bool initialized; 30 bool initialized;
31 } 31 }
32 32
33 this (Hash hash, void[] key=null) { 33 this (Hash hash, void[] key=null) {
34 hash.reset(); 34 this.hash = hash.copy();
35 35 this.hash.reset();
36 inner = hash;
37 outer = hash.copy();
38 36
39 ipad = new ubyte[blockSize]; 37 ipad = new ubyte[blockSize];
40 opad = new ubyte[blockSize]; 38 opad = new ubyte[blockSize];
41
42 reset();
43 39
44 if (key) 40 if (key)
45 init(new SymmetricKey(key)); // I'm lazy. 41 init(new SymmetricKey(key)); // I'm lazy.
46 } 42 }
47 43
49 SymmetricKey keyParams = cast(SymmetricKey)params; 45 SymmetricKey keyParams = cast(SymmetricKey)params;
50 if (!keyParams) 46 if (!keyParams)
51 throw new InvalidParameterError( 47 throw new InvalidParameterError(
52 name()~": Invalid parameter passed to init"); 48 name()~": Invalid parameter passed to init");
53 49
50 hash.reset();
51
54 if (keyParams.key.length > blockSize) { 52 if (keyParams.key.length > blockSize) {
55 inner.update(keyParams.key); 53 hash.update(keyParams.key);
56 key = inner.digest(); 54 key = hash.digest();
57 } else 55 } else
58 key = keyParams.key; 56 key = keyParams.key;
57
58 ipad[] = 0x36;
59 opad[] = 0x5c;
59 60
60 foreach (uint i, ubyte j; key) { 61 foreach (uint i, ubyte j; key) {
61 ipad[i] ^= j; 62 ipad[i] ^= j;
62 opad[i] ^= j; 63 opad[i] ^= j;
63 } 64 }
64 65
65 inner.update(ipad); 66 reset();
66 outer.update(opad);
67 67
68 initialized = true; 68 initialized = true;
69 } 69 }
70 70
71 void update(void[] input_) { 71 void update(void[] input_) {
72 if (!initialized) 72 if (!initialized)
73 throw new NotInitializedError( 73 throw new NotInitializedError(
74 name()~": MAC not initialized."); 74 name()~": MAC not initialized.");
75 inner.update(input_); 75 hash.update(input_);
76 } 76 }
77 77
78 char[] name() { 78 char[] name() {
79 return inner.name~"/HMAC"; 79 return "HMAC-"~hash.name;
80 } 80 }
81 81
82 void reset() { 82 void reset() {
83 ipad[] = 0x36; 83 hash.reset();
84 opad[] = 0x5c; 84 hash.update(ipad);
85
86 inner.reset();
87 outer.reset();
88 } 85 }
89 86
90 uint blockSize() { 87 uint blockSize() {
91 return inner.blockSize; 88 return hash.blockSize;
92 } 89 }
93 90
94 uint macSize() { 91 uint macSize() {
95 return inner.digestSize; 92 return hash.digestSize;
96 } 93 }
97 94
98 ubyte[] digest() { 95 ubyte[] digest() {
99 outer.update(inner.digest()); 96 ubyte[] t = hash.digest();
100 ubyte[] r = outer.digest(); 97 hash.update(opad);
98 hash.update(t);
99 ubyte[] r = hash.digest();
101 reset(); 100 reset();
102 return r; 101 return r;
103 } 102 }
104 103
105 char[] hexDigest() { 104 char[] hexDigest() {
106 return Util.ubytesToHex(finish()); 105 return Util.ubytesToHex(digest());
107 } 106 }
108 107
109 HMAC copy() { 108 HMAC copy() {
110 // Ghetto... oh so ghetto :\ 109 // Ghetto... oh so ghetto :\
111 HMAC h = new HMAC(inner.copy()); 110 HMAC h = new HMAC(hash.copy());
112 h.inner = inner.copy(); 111 h.hash = hash.copy();
113 h.outer = outer.copy();
114 h.initialized = true; 112 h.initialized = true;
115 return h; 113 return h;
116 } 114 }
117 115
118 version (UnitTest) { 116 version (UnitTest) {