OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 part of dart.crypto; | |
6 | |
7 class _HMAC implements HMAC { | |
8 bool _isClosed = false; | |
9 | |
10 _HMAC(Hash this._hash, List<int> this._key) : _message = []; | |
11 | |
12 add(List<int> data) { | |
13 if (_isClosed) throw new StateError("HMAC is closed"); | |
14 _message.addAll(data); | |
15 } | |
16 | |
17 List<int> get digest { | |
18 var blockSize = _hash.blockSize; | |
19 | |
20 // Hash the key if it is longer than the block size of the hash. | |
21 if (_key.length > blockSize) { | |
22 _hash = _hash.newInstance(); | |
23 _hash.add(_key); | |
24 _key = _hash.close(); | |
25 } | |
26 | |
27 // Zero-pad the key until its size is equal to the block size of the hash. | |
28 if (_key.length < blockSize) { | |
29 var newKey = new List(blockSize); | |
30 newKey.setRange(0, _key.length, _key); | |
31 for (var i = _key.length; i < blockSize; i++) { | |
32 newKey[i] = 0; | |
33 } | |
34 _key = newKey; | |
35 } | |
36 | |
37 // Compute inner padding. | |
38 var padding = new List(blockSize); | |
39 for (var i = 0; i < blockSize; i++) { | |
40 padding[i] = 0x36 ^ _key[i]; | |
41 } | |
42 | |
43 // Inner hash computation. | |
44 _hash = _hash.newInstance(); | |
45 _hash.add(padding); | |
46 _hash.add(_message); | |
47 var innerHash = _hash.close(); | |
48 | |
49 // Compute outer padding. | |
50 for (var i = 0; i < blockSize; i++) { | |
51 padding[i] = 0x5c ^ _key[i]; | |
52 } | |
53 | |
54 // Outer hash computation which is the result. | |
55 _hash = _hash.newInstance(); | |
56 _hash.add(padding); | |
57 _hash.add(innerHash); | |
58 return _hash.close(); | |
59 } | |
60 | |
61 List<int> close() { | |
62 _isClosed = true; | |
63 return digest; | |
64 } | |
65 | |
66 bool verify(List<int> digest) { | |
67 var computedDigest = this.digest; | |
68 if (digest.length != computedDigest.length) { | |
69 throw new ArgumentError( | |
70 'Invalid digest size: ${digest.length} in HMAC.verify. ' | |
71 'Expected: ${_hash.blockSize}.'); | |
72 } | |
73 int result = 0; | |
74 for (var i = 0; i < digest.length; i++) { | |
75 result |= digest[i] ^ computedDigest[i]; | |
76 } | |
77 return result == 0; | |
78 } | |
79 | |
80 // HMAC internal state. | |
81 Hash _hash; | |
82 List<int> _key; | |
83 List<int> _message; | |
84 } | |
OLD | NEW |