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

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

Issue 1349373002: Improve the style of code in lib/. (Closed) Base URL: git@github.com:dart-lang/crypto.git@master
Patch Set: Code review changes Created 5 years, 3 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_base.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';
8
9 import 'package:typed_data/typed_data.dart';
10
7 import 'hash.dart'; 11 import 'hash.dart';
8 12
9 /// An implementation of [keyed-hash method authentication codes][rfc]. 13 /// An implementation of [keyed-hash method authentication codes][rfc].
10 /// 14 ///
11 /// [rfc]: https://tools.ietf.org/html/rfc2104 15 /// [rfc]: https://tools.ietf.org/html/rfc2104
12 /// 16 ///
13 /// HMAC allows messages to be cryptographically authenticated using any 17 /// HMAC allows messages to be cryptographically authenticated using any
14 /// iterated cryptographic hash function. 18 /// iterated cryptographic hash function.
15 /// 19 ///
16 /// The message's data is added using [add]. Once it's been fully added, the 20 /// The message's data is added using [add]. Once it's been fully added, the
17 /// [digest] and [close] methods can be used to extract the message 21 /// [digest] and [close] methods can be used to extract the message
18 /// authentication digest. 22 /// authentication digest.
19 /// 23 ///
20 /// If an expected authentication digest is available, the [verify] method may 24 /// If an expected authentication digest is available, the [verify] method may
21 /// also be used to ensure that the message actually corresponds to that digest. 25 /// also be used to ensure that the message actually corresponds to that digest.
22 // TODO(floitsch): make HMAC implement Sink, EventSink or similar. 26 // TODO(floitsch): make HMAC implement Sink, EventSink or similar.
23 class HMAC { 27 class HMAC {
24 /// The bytes from the message so far. 28 /// The bytes from the message so far.
25 final List<int> _message; 29 final _message = new Uint8Buffer();
26 30
27 /// The hash function used to compute the authentication digest. 31 /// The hash function used to compute the authentication digest.
28 Hash _hash; 32 Hash _hash;
29 33
30 /// The secret key shared by the sender and the receiver. 34 /// The secret key shared by the sender and the receiver.
31 List<int> _key; 35 final Uint8List _key;
32 36
33 /// Whether this is closed. 37 /// Whether [close] has been called.
34 bool _isClosed = false; 38 bool _isClosed = false;
35 39
36 /// Create an [HMAC] object from a [Hash] and a binary key. 40 /// Create an [HMAC] object from a [Hash] and a binary key.
37 /// 41 ///
38 /// The key should be a secret shared between the sender and receiver of the 42 /// The key should be a secret shared between the sender and receiver of the
39 /// message. 43 /// message.
40 HMAC(Hash this._hash, List<int> this._key) : _message = []; 44 HMAC(Hash hash, List<int> key)
45 : _hash = hash,
46 _key = new Uint8List(hash.blockSize) {
47 // Hash the key if it's longer than the block size of the hash.
48 if (key.length > _hash.blockSize) {
49 _hash = _hash.newInstance();
50 _hash.add(key);
51 key = _hash.close();
52 }
53
54 // If [key] is shorter than the block size, the rest of [_key] will be
55 // 0-padded.
56 _key.setRange(0, key.length, key);
57 }
41 58
42 /// Adds a list of bytes to the message. 59 /// Adds a list of bytes to the message.
43 /// 60 ///
44 /// If [this] has already been closed, throws a [StateError]. 61 /// If [this] has already been closed, throws a [StateError].
45 void add(List<int> data) { 62 void add(List<int> data) {
46 if (_isClosed) throw new StateError("HMAC is closed"); 63 if (_isClosed) throw new StateError("HMAC is closed");
47 _message.addAll(data); 64 _message.addAll(data);
48 } 65 }
49 66
50 /// Returns the digest of the message so far, as a list of bytes. 67 /// Returns the digest of the message so far, as a list of bytes.
51 List<int> get digest { 68 List<int> get digest {
52 var blockSize = _hash.blockSize;
53
54 // Hash the key if it is longer than the block size of the hash.
55 if (_key.length > blockSize) {
56 _hash = _hash.newInstance();
57 _hash.add(_key);
58 _key = _hash.close();
59 }
60
61 // Zero-pad the key until its size is equal to the block size of the hash.
62 if (_key.length < blockSize) {
63 var newKey = new List(blockSize);
64 newKey.setRange(0, _key.length, _key);
65 for (var i = _key.length; i < blockSize; i++) {
66 newKey[i] = 0;
67 }
68 _key = newKey;
69 }
70
71 // Compute inner padding. 69 // Compute inner padding.
72 var padding = new List(blockSize); 70 var padding = new Uint8List(_key.length);
73 for (var i = 0; i < blockSize; i++) { 71 for (var i = 0; i < padding.length; i++) {
74 padding[i] = 0x36 ^ _key[i]; 72 padding[i] = 0x36 ^ _key[i];
75 } 73 }
76 74
77 // Inner hash computation. 75 // Inner hash computation.
78 _hash = _hash.newInstance(); 76 _hash = _hash.newInstance();
79 _hash.add(padding); 77 _hash.add(padding);
80 _hash.add(_message); 78 _hash.add(_message);
81 var innerHash = _hash.close(); 79 var innerDigest = _hash.close();
82 80
83 // Compute outer padding. 81 // Compute outer padding.
84 for (var i = 0; i < blockSize; i++) { 82 for (var i = 0; i < padding.length; i++) {
85 padding[i] = 0x5c ^ _key[i]; 83 padding[i] = 0x5c ^ _key[i];
86 } 84 }
87 85
88 // Outer hash computation which is the result. 86 // Outer hash computation which is the result.
89 _hash = _hash.newInstance(); 87 _hash = _hash.newInstance();
90 _hash.add(padding); 88 _hash.add(padding);
91 _hash.add(innerHash); 89 _hash.add(innerDigest);
92 return _hash.close(); 90 return _hash.close();
93 } 91 }
94 92
95 /// Closes [this] and returns the digest of the message as a list of bytes. 93 /// Closes [this] and returns the digest of the message as a list of bytes.
96 /// 94 ///
97 /// Once closed, [add] may no longer be called. 95 /// Once closed, [add] may no longer be called.
98 List<int> close() { 96 List<int> close() {
99 _isClosed = true; 97 _isClosed = true;
100 return digest; 98 return digest;
101 } 99 }
102 100
103 /// Returns whether the digest computed for the data so far matches the given 101 /// Returns whether the digest computed for the data so far matches the given
104 /// [digest]. 102 /// [digest].
105 /// 103 ///
106 /// This method should be used instead of iterative comparisons to avoid 104 /// This method should be used instead of iterative comparisons to avoid
107 /// leaking information via timing. 105 /// leaking information via timing.
108 /// 106 ///
109 /// Throws an [ArgumentError] if the given digest does not have the same size 107 /// Throws an [ArgumentError] if the given digest does not have the same size
110 /// as the digest computed by [this]. 108 /// as the digest computed by [this].
111 bool verify(List<int> digest) { 109 bool verify(List<int> digest) {
112 var computedDigest = this.digest; 110 var computedDigest = this.digest;
113 if (digest.length != computedDigest.length) { 111 if (digest.length != computedDigest.length) {
114 throw new ArgumentError( 112 throw new ArgumentError(
115 'Invalid digest size: ${digest.length} in HMAC.verify. ' 113 'Invalid digest size: ${digest.length} in HMAC.verify. '
116 'Expected: ${_hash.blockSize}.'); 114 'Expected: ${_hash.blockSize}.');
117 } 115 }
118 int result = 0; 116
117 var result = 0;
119 for (var i = 0; i < digest.length; i++) { 118 for (var i = 0; i < digest.length; i++) {
120 result |= digest[i] ^ computedDigest[i]; 119 result |= digest[i] ^ computedDigest[i];
121 } 120 }
122 return result == 0; 121 return result == 0;
123 } 122 }
124 } 123 }
OLDNEW
« no previous file with comments | « lib/src/hash_base.dart ('k') | lib/src/md5.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698