blob: 300147f7abc82c37aa433064a89407c0fac74c73 [file] [log] [blame]
// 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.
library crypto.sha1;
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 [SHA1][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
///
/// Note that it's almost always easier to use [sha1] rather than creating a new
/// instance.
class SHA1 extends Hash {
final int blockSize = 16 * bytesPerWord;
@Deprecated("Use the sha1 field instead.")
SHA1();
SHA1 newInstance() => new SHA1();
ByteConversionSink startChunkedConversion(Sink<Digest> sink) =>
new ByteConversionSink.from(new _SHA1Sink(sink));
}
/// The concrete implementation of [SHA1].
///
/// This is separate so that it can extend [HashBase] without leaking additional
/// public memebers.
class _SHA1Sink extends HashSink {
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;
}
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]);
}
}