Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: lib/src/hmac.dart

Issue 1355223002: Change Hash subclasses to be Converters. (Closed) Base URL: git@github.com:dart-lang/crypto.git@master
Patch Set: Code review changes Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/src/hash_sink.dart ('k') | lib/src/md5.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library crypto.hmac; 5 library crypto.hmac;
6 6
7 import 'dart:typed_data'; 7 import 'dart:typed_data';
8 8
9 import 'package:typed_data/typed_data.dart'; 9 import 'package:typed_data/typed_data.dart';
10 10
11 import 'digest_sink.dart';
11 import 'hash.dart'; 12 import 'hash.dart';
12 13
13 /// An implementation of [keyed-hash method authentication codes][rfc]. 14 /// An implementation of [keyed-hash method authentication codes][rfc].
14 /// 15 ///
15 /// [rfc]: https://tools.ietf.org/html/rfc2104 16 /// [rfc]: https://tools.ietf.org/html/rfc2104
16 /// 17 ///
17 /// HMAC allows messages to be cryptographically authenticated using any 18 /// HMAC allows messages to be cryptographically authenticated using any
18 /// iterated cryptographic hash function. 19 /// iterated cryptographic hash function.
19 /// 20 ///
20 /// The message's data is added using [add]. Once it's been fully added, the 21 /// The message's data is added using [add]. Once it's been fully added, the
21 /// [digest] and [close] methods can be used to extract the message 22 /// [digest] and [close] methods can be used to extract the message
22 /// authentication digest. 23 /// authentication digest.
23 /// 24 ///
24 /// If an expected authentication digest is available, the [verify] method may 25 /// If an expected authentication digest is available, the [verify] method may
25 /// also be used to ensure that the message actually corresponds to that digest. 26 /// also be used to ensure that the message actually corresponds to that digest.
26 // TODO(floitsch): make HMAC implement Sink, EventSink or similar. 27 // TODO(floitsch): make HMAC implement Sink, EventSink or similar.
27 class HMAC { 28 class HMAC {
28 /// The bytes from the message so far. 29 /// The bytes from the message so far.
29 final _message = new Uint8Buffer(); 30 final _message = new Uint8Buffer();
30 31
31 /// The hash function used to compute the authentication digest. 32 /// The hash function used to compute the authentication digest.
32 Hash _hash; 33 final Hash _hash;
33 34
34 /// The secret key shared by the sender and the receiver. 35 /// The secret key shared by the sender and the receiver.
35 final Uint8List _key; 36 final Uint8List _key;
36 37
37 /// Whether [close] has been called. 38 /// Whether [close] has been called.
38 bool _isClosed = false; 39 bool _isClosed = false;
39 40
40 /// Create an [HMAC] object from a [Hash] and a binary key. 41 /// Create an [HMAC] object from a [Hash] and a binary key.
41 /// 42 ///
42 /// The key should be a secret shared between the sender and receiver of the 43 /// The key should be a secret shared between the sender and receiver of the
43 /// message. 44 /// message.
44 HMAC(Hash hash, List<int> key) 45 HMAC(Hash hash, List<int> key)
45 : _hash = hash, 46 : _hash = hash,
46 _key = new Uint8List(hash.blockSize) { 47 _key = new Uint8List(hash.blockSize) {
47 // Hash the key if it's longer than the block size of the hash. 48 // Hash the key if it's longer than the block size of the hash.
48 if (key.length > _hash.blockSize) { 49 if (key.length > _hash.blockSize) key = _hash.convert(key).bytes;
49 _hash = _hash.newInstance();
50 _hash.add(key);
51 key = _hash.close();
52 }
53 50
54 // If [key] is shorter than the block size, the rest of [_key] will be 51 // If [key] is shorter than the block size, the rest of [_key] will be
55 // 0-padded. 52 // 0-padded.
56 _key.setRange(0, key.length, key); 53 _key.setRange(0, key.length, key);
57 } 54 }
58 55
59 /// Adds a list of bytes to the message. 56 /// Adds a list of bytes to the message.
60 /// 57 ///
61 /// If [this] has already been closed, throws a [StateError]. 58 /// If [this] has already been closed, throws a [StateError].
62 void add(List<int> data) { 59 void add(List<int> data) {
63 if (_isClosed) throw new StateError("HMAC is closed"); 60 if (_isClosed) throw new StateError("HMAC is closed");
64 _message.addAll(data); 61 _message.addAll(data);
65 } 62 }
66 63
67 /// Returns the digest of the message so far, as a list of bytes. 64 /// Returns the digest of the message so far, as a list of bytes.
68 List<int> get digest { 65 List<int> get digest {
69 // Compute inner padding. 66 // Compute inner padding.
70 var padding = new Uint8List(_key.length); 67 var padding = new Uint8List(_key.length);
71 for (var i = 0; i < padding.length; i++) { 68 for (var i = 0; i < padding.length; i++) {
72 padding[i] = 0x36 ^ _key[i]; 69 padding[i] = 0x36 ^ _key[i];
73 } 70 }
74 71
75 // Inner hash computation. 72 // Inner hash computation.
76 _hash = _hash.newInstance(); 73 var innerDigest = _hashWithPadding(padding, _message);
77 _hash.add(padding);
78 _hash.add(_message);
79 var innerDigest = _hash.close();
80 74
81 // Compute outer padding. 75 // Compute outer padding.
82 for (var i = 0; i < padding.length; i++) { 76 for (var i = 0; i < padding.length; i++) {
83 padding[i] = 0x5c ^ _key[i]; 77 padding[i] = 0x5c ^ _key[i];
84 } 78 }
85 79
86 // Outer hash computation which is the result. 80 // Outer hash computation which is the result.
87 _hash = _hash.newInstance(); 81 return _hashWithPadding(padding, innerDigest);
88 _hash.add(padding); 82 }
89 _hash.add(innerDigest); 83
90 return _hash.close(); 84 /// Returns the digest of [padding] followed by [data].
85 List<int> _hashWithPadding(List<int> padding, List<int> data) {
86 var innerSink = new DigestSink();
87 _hash.startChunkedConversion(innerSink)
88 ..add(padding)
89 ..add(data)
90 ..close();
91 return innerSink.value.bytes;
91 } 92 }
92 93
93 /// Closes [this] and returns the digest of the message as a list of bytes. 94 /// Closes [this] and returns the digest of the message as a list of bytes.
94 /// 95 ///
95 /// Once closed, [add] may no longer be called. 96 /// Once closed, [add] may no longer be called.
96 List<int> close() { 97 List<int> close() {
97 _isClosed = true; 98 _isClosed = true;
98 return digest; 99 return digest;
99 } 100 }
100 101
(...skipping 13 matching lines...) Expand all
114 'Expected: ${_hash.blockSize}.'); 115 'Expected: ${_hash.blockSize}.');
115 } 116 }
116 117
117 var result = 0; 118 var result = 0;
118 for (var i = 0; i < digest.length; i++) { 119 for (var i = 0; i < digest.length; i++) {
119 result |= digest[i] ^ computedDigest[i]; 120 result |= digest[i] ^ computedDigest[i];
120 } 121 }
121 return result == 0; 122 return result == 0;
122 } 123 }
123 } 124 }
OLDNEW
« no previous file with comments | « lib/src/hash_sink.dart ('k') | lib/src/md5.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698