| Index: packages/crypto/lib/src/sha1.dart
|
| diff --git a/packages/crypto/lib/src/sha1.dart b/packages/crypto/lib/src/sha1.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..dd40410a10199cdf0d70f08adef9b3b6eb083b52
|
| --- /dev/null
|
| +++ b/packages/crypto/lib/src/sha1.dart
|
| @@ -0,0 +1,104 @@
|
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +import 'dart:convert';
|
| +import 'dart:typed_data';
|
| +
|
| +import 'digest.dart';
|
| +import 'hash.dart';
|
| +import 'hash_sink.dart';
|
| +import 'utils.dart';
|
| +
|
| +/// An instance of [Sha1].
|
| +///
|
| +/// This instance provides convenient access to the [SHA-1][rfc] hash function.
|
| +///
|
| +/// [rfc]: http://tools.ietf.org/html/rfc3174
|
| +final sha1 = new Sha1._();
|
| +
|
| +/// An implementation of the [SHA-1][rfc] hash function.
|
| +///
|
| +/// [rfc]: http://tools.ietf.org/html/rfc3174
|
| +class Sha1 extends Hash {
|
| + @override
|
| + final int blockSize = 16 * bytesPerWord;
|
| +
|
| + Sha1._();
|
| +
|
| + @override
|
| + ByteConversionSink startChunkedConversion(Sink<Digest> sink) =>
|
| + new ByteConversionSink.from(new _Sha1Sink(sink));
|
| +}
|
| +
|
| +/// The concrete implementation of [Sha1].
|
| +///
|
| +/// This is separate so that it can extend [HashSink] without leaking additional
|
| +/// public memebers.
|
| +class _Sha1Sink extends HashSink {
|
| + @override
|
| + final digest = new Uint32List(5);
|
| +
|
| + /// The sixteen words from the original chunk, extended to 80 words.
|
| + ///
|
| + /// This is an instance variable to avoid re-allocating, but its data isn't
|
| + /// used across invocations of [updateHash].
|
| + final Uint32List _extended;
|
| +
|
| + _Sha1Sink(Sink<Digest> sink)
|
| + : _extended = new Uint32List(80),
|
| + super(sink, 16) {
|
| + digest[0] = 0x67452301;
|
| + digest[1] = 0xEFCDAB89;
|
| + digest[2] = 0x98BADCFE;
|
| + digest[3] = 0x10325476;
|
| + digest[4] = 0xC3D2E1F0;
|
| + }
|
| +
|
| + @override
|
| + void updateHash(Uint32List chunk) {
|
| + assert(chunk.length == 16);
|
| +
|
| + var a = digest[0];
|
| + var b = digest[1];
|
| + var c = digest[2];
|
| + var d = digest[3];
|
| + var e = digest[4];
|
| +
|
| + for (var i = 0; i < 80; i++) {
|
| + if (i < 16) {
|
| + _extended[i] = chunk[i];
|
| + } else {
|
| + _extended[i] = rotl32(
|
| + _extended[i - 3] ^
|
| + _extended[i - 8] ^
|
| + _extended[i - 14] ^
|
| + _extended[i - 16],
|
| + 1);
|
| + }
|
| +
|
| + var newA = add32(add32(rotl32(a, 5), e), _extended[i]);
|
| + if (i < 20) {
|
| + newA = add32(add32(newA, (b & c) | (~b & d)), 0x5A827999);
|
| + } else if (i < 40) {
|
| + newA = add32(add32(newA, (b ^ c ^ d)), 0x6ED9EBA1);
|
| + } else if (i < 60) {
|
| + newA = add32(add32(newA, (b & c) | (b & d) | (c & d)), 0x8F1BBCDC);
|
| + } else {
|
| + newA = add32(add32(newA, b ^ c ^ d), 0xCA62C1D6);
|
| + }
|
| +
|
| + e = d;
|
| + d = c;
|
| + c = rotl32(b, 30);
|
| + b = a;
|
| + a = newA & mask32;
|
| + }
|
| +
|
| + digest[0] = add32(a, digest[0]);
|
| + digest[1] = add32(b, digest[1]);
|
| + digest[2] = add32(c, digest[2]);
|
| + digest[3] = add32(d, digest[3]);
|
| + digest[4] = add32(e, digest[4]);
|
| + }
|
| +}
|
|
|