OLD | NEW |
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.hash_base; | 5 library crypto.hash_base; |
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.dart'; |
11 import 'hash.dart'; | 12 import 'hash.dart'; |
12 import 'utils.dart'; | 13 import 'utils.dart'; |
13 | 14 |
14 /// A base class for [Hash] implementations. | 15 /// A base class for [Sink] implementations for hash algorithms. |
15 /// | 16 /// |
16 /// Subclasses should override [updateHash] and [digest]. | 17 /// Subclasses should override [updateHash] and [digest]. |
17 abstract class HashBase implements Hash { | 18 abstract class HashSink implements Sink<List<int>> { |
| 19 /// The inner sink that this should forward to. |
| 20 final Sink<Digest> _sink; |
| 21 |
18 /// Whether the hash function operates on big-endian words. | 22 /// Whether the hash function operates on big-endian words. |
19 final Endianness _endian; | 23 final Endianness _endian; |
20 | 24 |
21 /// The words in the current chunk. | 25 /// The words in the current chunk. |
22 /// | 26 /// |
23 /// This is an instance variable to avoid re-allocating, but its data isn't | 27 /// This is an instance variable to avoid re-allocating, but its data isn't |
24 /// used across invocations of [_iterate]. | 28 /// used across invocations of [_iterate]. |
25 final Uint32List _currentChunk; | 29 final Uint32List _currentChunk; |
26 | 30 |
27 /// The length of the input data so far, in bytes. | 31 /// The length of the input data so far, in bytes. |
28 int _lengthInBytes = 0; | 32 int _lengthInBytes = 0; |
29 | 33 |
30 /// Data that has yet to be processed by the hash function. | 34 /// Data that has yet to be processed by the hash function. |
31 final _pendingData = new Uint8Buffer(); | 35 final _pendingData = new Uint8Buffer(); |
32 | 36 |
33 /// Whether [close] has been called. | 37 /// Whether [close] has been called. |
34 bool _isClosed = false; | 38 bool _isClosed = false; |
35 | 39 |
36 /// The words in the current digest. | 40 /// The words in the current digest. |
37 /// | 41 /// |
38 /// This should be updated each time [updateHash] is called. | 42 /// This should be updated each time [updateHash] is called. |
39 Uint32List get digest; | 43 Uint32List get digest; |
40 | 44 |
41 int get blockSize => _currentChunk.lengthInBytes; | |
42 | |
43 /// Creates a new hash. | 45 /// Creates a new hash. |
44 /// | 46 /// |
45 /// [chunkSizeInWords] represents the size of the input chunks processed by | 47 /// [chunkSizeInWords] represents the size of the input chunks processed by |
46 /// the algorithm, in terms of 32-bit words. | 48 /// the algorithm, in terms of 32-bit words. |
47 HashBase(int chunkSizeInWords, {Endianness endian: Endianness.BIG_ENDIAN}) | 49 HashSink(this._sink, int chunkSizeInWords, |
| 50 {Endianness endian: Endianness.BIG_ENDIAN}) |
48 : _endian = endian, | 51 : _endian = endian, |
49 _currentChunk = new Uint32List(chunkSizeInWords); | 52 _currentChunk = new Uint32List(chunkSizeInWords); |
50 | 53 |
51 /// Runs a single iteration of the hash computation, updating [digest] with | 54 /// Runs a single iteration of the hash computation, updating [digest] with |
52 /// the result. | 55 /// the result. |
53 /// | 56 /// |
54 /// [m] is the current chunk, whose size is given by the `chunkSizeInWords` | 57 /// [m] is the current chunk, whose size is given by the `chunkSizeInWords` |
55 /// parameter passed to the constructor. | 58 /// parameter passed to the constructor. |
56 void updateHash(Uint32List chunk); | 59 void updateHash(Uint32List chunk); |
57 | 60 |
58 void add(List<int> data) { | 61 void add(List<int> data) { |
59 if (_isClosed) throw new StateError('Hash.add() called after close().'); | 62 if (_isClosed) throw new StateError('Hash.add() called after close().'); |
60 _lengthInBytes += data.length; | 63 _lengthInBytes += data.length; |
61 _pendingData.addAll(data); | 64 _pendingData.addAll(data); |
62 _iterate(); | 65 _iterate(); |
63 } | 66 } |
64 | 67 |
65 List<int> close() { | 68 void close() { |
66 if (_isClosed) return _byteDigest(); | 69 if (_isClosed) return; |
67 _isClosed = true; | 70 _isClosed = true; |
68 | 71 |
69 _finalizeData(); | 72 _finalizeData(); |
70 _iterate(); | 73 _iterate(); |
71 assert(_pendingData.isEmpty); | 74 assert(_pendingData.isEmpty); |
72 return _byteDigest(); | 75 _sink.add(new Digest(_byteDigest())); |
73 } | 76 } |
74 | 77 |
75 Uint8List _byteDigest() { | 78 Uint8List _byteDigest() { |
76 if (_endian == Endianness.HOST_ENDIAN) return digest.buffer.asUint8List(); | 79 if (_endian == Endianness.HOST_ENDIAN) return digest.buffer.asUint8List(); |
77 | 80 |
78 var byteDigest = new Uint8List(digest.lengthInBytes); | 81 var byteDigest = new Uint8List(digest.lengthInBytes); |
79 var byteData = byteDigest.buffer.asByteData(); | 82 var byteData = byteDigest.buffer.asByteData(); |
80 for (var i = 0; i < digest.length; i++) { | 83 for (var i = 0; i < digest.length; i++) { |
81 byteData.setUint32(i * bytesPerWord, digest[i]); | 84 byteData.setUint32(i * bytesPerWord, digest[i]); |
82 } | 85 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 // hash. | 131 // hash. |
129 var offset = _pendingData.length; | 132 var offset = _pendingData.length; |
130 _pendingData.addAll(new Uint8List(8)); | 133 _pendingData.addAll(new Uint8List(8)); |
131 _pendingData.buffer.asByteData().setUint64(offset, lengthInBits, _endian); | 134 _pendingData.buffer.asByteData().setUint64(offset, lengthInBits, _endian); |
132 } | 135 } |
133 | 136 |
134 /// Rounds [val] up to the next multiple of [n], as long as [n] is a power of | 137 /// Rounds [val] up to the next multiple of [n], as long as [n] is a power of |
135 /// two. | 138 /// two. |
136 int _roundUp(int val, int n) => (val + n - 1) & -n; | 139 int _roundUp(int val, int n) => (val + n - 1) & -n; |
137 } | 140 } |
OLD | NEW |