Update documentation comments.
R=rnystrom@google.com
Review URL: https://codereview.chromium.org//1348983002 .
diff --git a/lib/crypto.dart b/lib/crypto.dart
index 29fd62a..e6ffa55 100644
--- a/lib/crypto.dart
+++ b/lib/crypto.dart
@@ -2,10 +2,6 @@
// 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.
-/**
- * Cryptographic algorithms, with support for hash functions such as
- * SHA-1, SHA-256, HMAC, and MD5.
- */
library crypto;
export 'src/base64.dart';
diff --git a/lib/src/base64.dart b/lib/src/base64.dart
index ad0d8bc..b3896b6 100644
--- a/lib/src/base64.dart
+++ b/lib/src/base64.dart
@@ -7,8 +7,15 @@
import 'dart:convert';
import 'dart:typed_data';
+/// An instance of the default implementation of [Base64Codec].
+///
+/// This provides convenient access to most common Base64 use-cases.
const Base64Codec BASE64 = const Base64Codec();
+/// A mapping from ASCII character codes to their corresponding Base64 values.
+///
+/// Characters with a value of -2 are invalid. Characters with a value of -1
+/// should be ignored. The padding character, "=", is represented as 0.
const List<int> _decodeTable = const [
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -2, -2, -1, -2, -2,
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
@@ -28,47 +35,64 @@
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
];
+/// A String representing a mapping from numbers between 0 and 63, inclusive, to
+/// their corresponding encoded character.
+///
+/// This is the table for URL-safe encodings.
const String _encodeTableUrlSafe =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+/// A String representing a mapping from numbers between 0 and 63, inclusive, to
+/// their corresponding encoded character.
+///
+/// This is the table for URL-unsafe encodings.
const String _encodeTable =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+/// The line length for Base64 strings with line separators.
const int _LINE_LENGTH = 76;
+
+/// A carriage return.
const int _CR = 13; // '\r'
+
+/// A line feed.
const int _LF = 10; // '\n'
+
+/// The byte sequence representing non-URL-encoded padding.
const List<int> _PAD_BYTES = const [61]; // '='
+
+/// The byte sequence representing URL-encoded padding.
const List<int> _ENCODED_PAD_BYTES = const [37, 51, 68]; // '%3D'
+
+/// The string representing non-URL-encoded padding.
const String _PAD = "=";
+
+/// The string representing URL-encoded padding.
const String _ENCODED_PAD = "%3D";
+/// A codec that converts between binary data and [Base64][rfc]-encoded strings.
+///
+/// [rfc]: https://tools.ietf.org/html/rfc4648
class Base64Codec extends Codec<List<int>, String> {
final bool _urlSafe;
final bool _addLineSeparator;
final bool _encodePaddingCharacter;
- /**
- * Instantiates a new [Base64Codec].
- *
- * The optional [urlSafe] argument specifies if [encoder] and [encode]
- * should generate a string, that is safe to use in an URL.
- *
- * If [urlSafe] is `true` (and not overriden at the method invocation)
- * the [encoder] and [encode] use '-' instead of '+' and '_' instead of '/'.
- *
- * The default value of [urlSafe] is `false`.
- *
- * The optional [addLineSeparator] argument specifies if the [encoder] and
- * [encode] should add line separators.
- *
- * If `addLineSeparator` is `true` [encode] adds an
- * optional line separator (CR + LF) for each 76 char output.
- *
- * The default value of [addLineSeparator] if `false`.
- *
- * If [encodePaddingCharacter] is `true` `encode` converts `=` to `%3D`.
- * The default value of [encodePaddingCharacter] is `false`.
- */
+ /// Creates a new [Base64Codec].
+ ///
+ /// The default [BASE64] codec will be good enough for most cases. A new codec
+ /// only needs to be instantiated when you want to do multiple conversions
+ /// with the same configuration.
+ ///
+ /// If [urlSafe] is `true`, a URL-safe alphabet will be used when encoding.
+ /// Specifically, the characters `-` and `_` will be used instead of `+` and
+ /// `/`.
+ ///
+ /// If [addLineSeparator] is `true`, `\r\n` line separators will be added
+ /// every 76 characters when encoding.
+ ///
+ /// If [encodePaddingCharacter] is `true`, the padding character `=` will be
+ /// written as `%3D` when encoding.
const Base64Codec(
{bool urlSafe: false,
bool addLineSeparator: false,
@@ -79,6 +103,20 @@
String get name => "base64";
+ /// Encodes [bytes] into a Base64 string.
+ ///
+ /// If [urlSafe] is `true`, a URL-safe alphabet will be used when encoding.
+ /// Specifically, the characters `-` and `_` will be used instead of `+` and
+ /// `/`.
+ ///
+ /// If [addLineSeparator] is `true`, `\r\n` line separators will be added
+ /// every 76 characters when encoding.
+ ///
+ /// If [encodePaddingCharacter] is `true`, the padding character `=` will be
+ /// written as `%3D` when encoding.
+ ///
+ /// Any flags passed to this method take precedence over the flags passed to
+ /// the codec itself.
String encode(List<int> bytes,
{bool urlSafe, bool addLineSeparator, bool encodePaddingCharacter}) {
if (urlSafe == null) urlSafe = _urlSafe;
@@ -100,38 +138,36 @@
Base64Decoder get decoder => new Base64Decoder();
}
-/**
- * This class encodes byte strings (lists of unsigned
- * 8-bit integers) to strings according to Base64.
- */
+/// An encoder that converts sequences of bytes to strings using [Base64][rfc].
+///
+/// [rfc]: https://tools.ietf.org/html/rfc4648
class Base64Encoder extends Converter<List<int>, String> {
+ /// Whether this encoder generates URL-safe strings.
final bool _urlSafe;
+
+ /// Whether this encoder adds line breaks to the output.
final bool _addLineSeparator;
+
+ /// Whether this encoder URL-encodes trailing padding characters.
final bool _encodePaddingCharacter;
+
+ /// The sequence of bytes to use as a padding character.
final List<int> _pad;
- /**
- * Instantiates a new [Base64Encoder].
- *
- * The optional [urlSafe] argument specifies if [convert]
- * should generate a string, that is safe to use in an URL.
- *
- * If it is `true` the [convert] use
- * '-' instead of '+' and '_' instead of '/'.
- *
- * The default value of [urlSafe] is `false`.
- *
- * The optional [addLineSeparator] argument specifies if [convert]
- * should add line separators.
- *
- * If it is `true` [convert] adds an optional line separator(CR + LF)
- * for each 76 char output.
- *
- * The default value of [addLineSeparator] if `false`.
- *
- * If [encodePaddingCharacter] is `true` `encode` converts `=` to `%3D`.
- * The default value of [encodePaddingCharacter] is `false`.
- */
+ /// Creates a new [Base64Encoder].
+ ///
+ /// The default [BASE64.encoder] will be good enough for most cases. A new
+ /// codec only needs to be instantiated when you want to do multiple
+ /// conversions with the same configuration.
+ ///
+ /// If [urlSafe] is `true`, a URL-safe alphabet will be used. Specifically,
+ /// the characters `-` and `_` will be used instead of `+` and `/`.
+ ///
+ /// If [addLineSeparator] is `true`, `\r\n` line separators will be added
+ /// every 76 characters.
+ ///
+ /// If [encodePaddingCharacter] is `true`, the padding character `=` will be
+ /// written as `%3D`.
const Base64Encoder(
{bool urlSafe: false,
bool addLineSeparator: false,
@@ -141,12 +177,10 @@
_encodePaddingCharacter = encodePaddingCharacter,
_pad = encodePaddingCharacter == true ? _ENCODED_PAD_BYTES : _PAD_BYTES;
- /**
- * Converts [bytes] to its Base64 representation as a string.
- *
- * if [start] and [end] are provided, only the sublist
- * `bytes.sublist(start, end)` is converted.
- */
+ /// Converts [bytes] to Base64.
+ ///
+ /// If [start] and [end] are provided, only the sublist `bytes.sublist(start,
+ /// end)` is converted.
String convert(List<int> bytes, [int start = 0, int end]) {
int bytes_length = bytes.length;
RangeError.checkValidRange(start, end, bytes_length);
@@ -224,10 +258,21 @@
}
}
+/// A [ChunkedConversionSink] for encoding chunks of data to Base64.
class _Base64EncoderSink extends ChunkedConversionSink<List<int>> {
+ /// The encoder used to encode each chunk.
final Base64Encoder _encoder;
+
+ /// The underlying sink to which to emit the encoded strings.
final ChunkedConversionSink<String> _outSink;
+
+ /// The buffer of as-yet-unconverted bytes.
+ ///
+ /// This is used to ensure that we don't generate interstitial padding
+ /// characters.
final List<int> _buffer = new List<int>();
+
+ /// The length of [_buffer]; that is, the number of unconverted bytes.
int _bufferCount = 0;
_Base64EncoderSink(this._outSink, urlSafe, addLineSeparator)
@@ -260,14 +305,10 @@
}
}
-/**
- * This class decodes strings to lists of bytes(lists of
- * unsigned 8-bit integers) according to Base64.
- */
+/// An encoder that converts [Base64][rfc] strings to sequences of bytes.
+///
+/// [rfc]: https://tools.ietf.org/html/rfc4648
class Base64Decoder extends Converter<String, List<int>> {
- /**
- * Instantiates a new [Base64Decoder]
- */
const Base64Decoder();
List<int> convert(String input) {
@@ -357,9 +398,18 @@
}
}
+/// A [ChunkedConversionSink] for decoding chunks of Base64 strings to data.
class _Base64DecoderSink extends ChunkedConversionSink<String> {
+ /// The encoder used to decode each chunk.
final Base64Decoder _decoder = new Base64Decoder();
+
+ /// The underlying sink to which to emit the decoded strings.
final ChunkedConversionSink<List<int>> _outSink;
+
+ /// The as-yet-unconverted text.
+ ///
+ /// This is used to handle a chunk stopping partway in the middle of a
+ /// URL-encoded `=` character.
String _unconverted = "";
_Base64DecoderSink(this._outSink);
diff --git a/lib/src/crypto_utils.dart b/lib/src/crypto_utils.dart
index 99613ef..821fd2b 100644
--- a/lib/src/crypto_utils.dart
+++ b/lib/src/crypto_utils.dart
@@ -6,14 +6,10 @@
import 'base64.dart';
-/**
- * Utility methods for working with message digests.
- */
+/// Utility methods for working with message digests.
abstract class CryptoUtils {
- /**
- * Convert a list of bytes (for example a message digest) into a hex
- * string.
- */
+ /// Convert a list of bytes (for example a message digest) into a hexadecimal
+ /// string.
static String bytesToHex(List<int> bytes) {
var result = new StringBuffer();
for (var part in bytes) {
@@ -22,37 +18,32 @@
return result.toString();
}
- /**
- * Converts a list of bytes into a Base 64 encoded string.
- *
- * The list can be any list of integers in the range 0..255,
- * for example a message digest.
- *
- * If [addLineSeparator] is true, the resulting string will be
- * broken into lines of 76 characters, separated by "\r\n".
- *
- * If [urlSafe] is true, the result is URL and filename safe.
- *
- * Based on [RFC 4648](http://tools.ietf.org/html/rfc4648)
- *
- */
+ /// Converts a list of bytes into a [Base64-encoded][rfc] string.
+ ///
+ /// [rfc]: https://tools.ietf.org/html/rfc4648
+ ///
+ /// The list can be any list of integers from 0 to 255 inclusive, for example
+ /// a message digest.
+ ///
+ /// If [addLineSeparator] is true, the resulting string will be
+ /// broken into lines of 76 characters, separated by "\r\n".
+ ///
+ /// If [urlSafe] is true, the resulting string will be URL- and filename-
+ /// safe.
static String bytesToBase64(List<int> bytes,
{bool urlSafe: false, bool addLineSeparator: false}) {
return BASE64.encode(bytes,
urlSafe: urlSafe, addLineSeparator: addLineSeparator);
}
- /**
- * Converts a Base 64 encoded String into list of bytes.
- *
- * Decoder ignores "\r\n" sequences from input.
- *
- * Accepts both URL safe and unsafe Base 64 encoded strings.
- *
- * Throws a FormatException exception if input contains invalid characters.
- *
- * Based on [RFC 4648](http://tools.ietf.org/html/rfc4648)
- */
+ /// Converts a [Base64-encoded][rfc] String into list of bytes.
+ ///
+ /// [rfc]: https://tools.ietf.org/html/rfc4648
+ ///
+ /// This ignores "\r\n" sequences in [input]. It accepts both URL-safe and
+ /// -unsafe Base 64 encoded strings.
+ ///
+ /// Throws a [FormatException] if [input] contains invalid characters.
static List<int> base64StringToBytes(String input) {
return BASE64.decode(input);
}
diff --git a/lib/src/hash.dart b/lib/src/hash.dart
index 03d4b1c..bb228fa 100644
--- a/lib/src/hash.dart
+++ b/lib/src/hash.dart
@@ -4,42 +4,30 @@
library crypto.hash;
-/**
- * Interface for cryptographic hash functions.
- *
- * The [add] method is used to add data to the hash. The [close] method
- * is used to extract the message digest.
- *
- * Once the [close] method has been called no more data can be added using the
- * [add] method. If [add] is called after the first call to [close] a
- * HashException is thrown.
- *
- * If multiple instances of a given Hash is needed the [newInstance]
- * method can provide a new instance.
- */
+/// An interface for cryptographic hash functions.
+///
+/// The [add] method adds data to the hash. The [close] method extracts the
+/// message digest.
+///
+/// If multiple instances of a given Hash is needed, the [newInstance] method
+/// can provide a new instance.
// TODO(floitsch): make Hash implement Sink, EventSink or similar.
abstract class Hash {
- /**
- * Add a list of bytes to the hash computation.
- */
+ /// Add a list of bytes to the hash computation.
+ ///
+ /// If [this] has already been closed, throws a [StateError].
void add(List<int> data);
- /**
- * Finish the hash computation and extract the message digest as
- * a list of bytes.
- */
+ /// Finish the hash computation and extract the message digest as a list of
+ /// bytes.
List<int> close();
- /**
- * Returns a new instance of this hash function.
- */
+ /// Returns a new instance of this hash function.
Hash newInstance();
- /**
- * Internal block size of the hash in bytes.
- *
- * This is exposed for use by the HMAC class which needs to know the
- * block size for the [Hash] it is using.
- */
+ /// The internal block size of the hash in bytes.
+ ///
+ /// This is exposed for use by the [HMAC] class, which needs to know the block
+ /// size for the [Hash] it uses.
int get blockSize;
}
diff --git a/lib/src/hash_base.dart b/lib/src/hash_base.dart
index 796fd14..b77b26d 100644
--- a/lib/src/hash_base.dart
+++ b/lib/src/hash_base.dart
@@ -10,18 +10,44 @@
import 'hash.dart';
import 'utils.dart';
-// Base class encapsulating common behavior for cryptographic hash
-// functions.
+/// A base class for [Hash] implementations.
+///
+/// Subclasses should override [updateHash], and define it to update [h] with
+/// the results of the hash function.
abstract class HashBase implements Hash {
+ /// The size (in 32-bit words) of the chunks of input data that the hash
+ /// function consumes at once.
final int _chunkSizeInWords;
+
+ /// The size (in 32-bit words) of the digest that the hash function emits.
final int _digestSizeInWords;
+
+ /// Whether the hash function operates on big-endian words.
final bool _bigEndianWords;
+
+ /// The words in the current chunk.
final Uint32List _currentChunk;
+
+ /// The words in the current digest.
+ ///
+ /// The size of this buffer is given by the `digestSizeInWords` constructor
+ /// parameter.
final Uint32List h;
+
+ /// The length of the input data so far, in bytes.
int _lengthInBytes = 0;
+
+ /// Data that has yet to be processed by the hash function.
List<int> _pendingData;
+
+ /// Whether [close] has been called.
bool _digestCalled = false;
+ /// Creates a new hash.
+ ///
+ /// [chunkSizeInWords] represents the size of the input chunks processed by
+ /// the algorithm. [digestSizeInWords] represents the size of the algorithm's
+ /// output digest. Both are in terms of 32-bit words.
HashBase(
int chunkSizeInWords, int digestSizeInWords, bool this._bigEndianWords)
: _pendingData = [],
@@ -30,7 +56,6 @@
_chunkSizeInWords = chunkSizeInWords,
_digestSizeInWords = digestSizeInWords;
- // Update the hasher with more data.
void add(List<int> data) {
if (_digestCalled) {
throw new StateError(
@@ -41,7 +66,6 @@
_iterate();
}
- // Finish the hash computation and return the digest string.
List<int> close() {
if (_digestCalled) {
return _resultAsBytes();
@@ -53,15 +77,19 @@
return _resultAsBytes();
}
- // Returns the block size of the hash in bytes.
int get blockSize {
return _chunkSizeInWords * BYTES_PER_WORD;
}
- // One round of the hash computation.
+ /// Runs a single iteration of the hash computation, updating [h] with the
+ /// result.
+ ///
+ /// [m] is the current chunk, whose size is given by the `chunkSizeInWords`
+ /// parameter passed to the constructor.
void updateHash(Uint32List m);
- // Compute the final result as a list of bytes from the hash words.
+ /// Computes the final result of the hash as a list of bytes from the hash
+ /// words.
List<int> _resultAsBytes() {
var result = [];
for (var i = 0; i < h.length; i++) {
@@ -70,7 +98,9 @@
return result;
}
- // Converts a list of bytes to a chunk of 32-bit words.
+ /// Converts a list of bytes to a chunk of 32-bit words.
+ ///
+ /// Stores the result in [_currentChunk].
void _bytesToChunk(List<int> data, int dataIndex) {
assert((data.length - dataIndex) >= (_chunkSizeInWords * BYTES_PER_WORD));
@@ -88,7 +118,7 @@
}
}
- // Convert a 32-bit word to four bytes.
+ /// Converts a 32-bit word to four bytes.
List<int> _wordToBytes(int word) {
List bytes = new List<int>(BYTES_PER_WORD);
bytes[0] = (word >> (_bigEndianWords ? 24 : 0)) & MASK_8;
@@ -98,8 +128,8 @@
return bytes;
}
- // Iterate through data updating the hash computation for each
- // chunk.
+ /// Iterates through [_pendingData], updating the hash computation for each
+ /// chunk.
void _iterate() {
var len = _pendingData.length;
var chunkSizeInBytes = _chunkSizeInWords * BYTES_PER_WORD;
@@ -113,13 +143,15 @@
}
}
- // Finalize the data. Add a 1 bit to the end of the message. Expand with
- // 0 bits and add the length of the message.
+ /// Finalizes [_pendingData].
+ ///
+ /// This adds a 1 bit to the end of the message, and expands it with 0 bits to
+ /// pad it out.
void _finalizeData() {
_pendingData.add(0x80);
var contentsLength = _lengthInBytes + 9;
var chunkSizeInBytes = _chunkSizeInWords * BYTES_PER_WORD;
- var finalizedLength = roundUp(contentsLength, chunkSizeInBytes);
+ var finalizedLength = _roundUp(contentsLength, chunkSizeInBytes);
var zeroPadding = finalizedLength - contentsLength;
for (var i = 0; i < zeroPadding; i++) {
_pendingData.add(0);
@@ -138,4 +170,7 @@
_pendingData.addAll(_wordToBytes((lengthInBits >> 32) & MASK_32));
}
}
+
+ /// Rounds [val] to the nearest multiple of [n].
+ int _roundUp(val, n) => (val + n - 1) & -n;
}
diff --git a/lib/src/hmac.dart b/lib/src/hmac.dart
index 2e9e0ef..668f40f 100644
--- a/lib/src/hmac.dart
+++ b/lib/src/hmac.dart
@@ -6,35 +6,48 @@
import 'hash.dart';
-/**
- * Hash-based Message Authentication Code support.
- *
- * The [add] method is used to add data to the message. The [digest] and
- * [close] methods are used to extract the message authentication code.
- */
-// TODO(floitsch): make Hash implement Sink, EventSink or similar.
+/// An implementation of [keyed-hash method authentication codes][rfc].
+///
+/// [rfc]: https://tools.ietf.org/html/rfc2104
+///
+/// HMAC allows messages to be cryptographically authenticated using any
+/// iterated cryptographic hash function.
+///
+/// The message's data is added using [add]. Once it's been fully added, the
+/// [digest] and [close] methods can be used to extract the message
+/// authentication digest.
+///
+/// If an expected authentication digest is available, the [verify] method may
+/// also be used to ensure that the message actually corresponds to that digest.
+// TODO(floitsch): make HMAC implement Sink, EventSink or similar.
class HMAC {
+ /// The bytes from the message so far.
final List<int> _message;
+
+ /// The hash function used to compute the authentication digest.
Hash _hash;
+
+ /// The secret key shared by the sender and the receiver.
List<int> _key;
+
+ /// Whether this is closed.
bool _isClosed = false;
- /**
- * Create an [HMAC] object from a [Hash] and a key.
- */
+ /// Create an [HMAC] object from a [Hash] and a binary key.
+ ///
+ /// The key should be a secret shared between the sender and receiver of the
+ /// message.
HMAC(Hash this._hash, List<int> this._key) : _message = [];
- /**
- * Add a list of bytes to the message.
- */
+ /// Adds a list of bytes to the message.
+ ///
+ /// If [this] has already been closed, throws a [StateError].
void add(List<int> data) {
if (_isClosed) throw new StateError("HMAC is closed");
_message.addAll(data);
}
- /**
- * Extract the message digest as a list of bytes without closing [this].
- */
+ /// Returns the digest of the message so far, as a list of bytes.
List<int> get digest {
var blockSize = _hash.blockSize;
@@ -79,25 +92,22 @@
return _hash.close();
}
- /**
- * Perform the actual computation and extract the message digest
- * as a list of bytes.
- */
+ /// Closes [this] and returns the digest of the message as a list of bytes.
+ ///
+ /// Once closed, [add] may no longer be called.
List<int> close() {
_isClosed = true;
return digest;
}
- /**
- * Verify that the HMAC computed for the data so far matches the
- * given message digest.
- *
- * This method should be used instead of memcmp-style comparisons
- * to avoid leaking information via timing.
- *
- * Throws an exception if the given digest does not have the same
- * size as the digest computed by this HMAC instance.
- */
+ /// Returns whether the digest computed for the data so far matches the given
+ /// [digest].
+ ///
+ /// This method should be used instead of iterative comparisons to avoid
+ /// leaking information via timing.
+ ///
+ /// Throws an [ArgumentError] if the given digest does not have the same size
+ /// as the digest computed by [this].
bool verify(List<int> digest) {
var computedDigest = this.digest;
if (digest.length != computedDigest.length) {
diff --git a/lib/src/md5.dart b/lib/src/md5.dart
index 077b218..e1caf88 100644
--- a/lib/src/md5.dart
+++ b/lib/src/md5.dart
@@ -10,18 +10,22 @@
import 'hash_base.dart';
import 'utils.dart';
-/**
- * MD5 hash function implementation.
- *
- * WARNING: MD5 has known collisions and should only be used when
- * required for backwards compatibility.
- */
+/// An implementation of the [MD5][rfc] hash function.
+///
+/// [rfc]: https://tools.ietf.org/html/rfc1321
+///
+/// **Warning**: MD5 has known collisions and should only be used when required
+/// for backwards compatibility.
abstract class MD5 implements Hash {
factory MD5() = _MD5;
MD5 newInstance();
}
+/// The concrete implementation of [MD5].
+///
+/// This is separate so that it can extend [HashBase] without leaking additional
+/// public memebers.
class _MD5 extends HashBase implements MD5 {
_MD5() : super(16, 4, false) {
h[0] = 0x67452301;
@@ -30,11 +34,12 @@
h[3] = 0x10325476;
}
- // Returns a new instance of this Hash.
MD5 newInstance() {
return new _MD5();
}
+ /// Data from a non-linear mathematical function that functions as
+ /// reproducible noise.
static const _k = const [
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,
0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
@@ -49,6 +54,7 @@
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
];
+ /// Per-round shift amounts.
static const _r = const [
07, 12, 17, 22, 07, 12, 17, 22, 07, 12, 17, 22, 07, 12, 17, 22, 05, 09, 14,
20, 05, 09, 14, 20, 05, 09, 14, 20, 05, 09, 14, 20, 04, 11, 16, 23, 04, 11,
@@ -56,8 +62,6 @@
10, 15, 21, 06, 10, 15, 21
];
- // Compute one iteration of the MD5 algorithm with a chunk of
- // 16 32-bit pieces.
void updateHash(Uint32List m) {
assert(m.length == 16);
diff --git a/lib/src/sha1.dart b/lib/src/sha1.dart
index d059226..7041a6f 100644
--- a/lib/src/sha1.dart
+++ b/lib/src/sha1.dart
@@ -10,19 +10,26 @@
import 'hash_base.dart';
import 'utils.dart';
-/**
- * SHA1 hash function implementation.
- */
+/// An implementation of the [SHA-1][rfc] hash function.
+///
+/// [rfc]: http://tools.ietf.org/html/rfc3174
abstract class SHA1 implements Hash {
factory SHA1() = _SHA1;
SHA1 newInstance();
}
+/// The concrete implementation of [SHA1].
+///
+/// This is separate so that it can extend [HashBase] without leaking additional
+/// public memebers.
class _SHA1 extends HashBase implements SHA1 {
+ /// 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 _w;
- // Construct a SHA1 hasher object.
_SHA1()
: _w = new Uint32List(80),
super(16, 5, true) {
@@ -33,13 +40,10 @@
h[4] = 0xC3D2E1F0;
}
- // Returns a new instance of this Hash.
SHA1 newInstance() {
return new _SHA1();
}
- // Compute one iteration of the SHA1 algorithm with a chunk of
- // 16 32-bit pieces.
void updateHash(Uint32List m) {
assert(m.length == 16);
diff --git a/lib/src/sha256.dart b/lib/src/sha256.dart
index 158f3f9..f66976d 100644
--- a/lib/src/sha256.dart
+++ b/lib/src/sha256.dart
@@ -10,19 +10,26 @@
import 'hash_base.dart';
import 'utils.dart';
-/**
- * SHA256 hash function implementation.
- */
+/// An implementation of the [SHA-256][rfc] hash function.
+///
+/// [rfc]: http://tools.ietf.org/html/rfc6234
abstract class SHA256 implements Hash {
factory SHA256() = _SHA256;
SHA256 newInstance();
}
+/// The concrete implementation of [SHA256].
+///
+/// This is separate so that it can extend [HashBase] without leaking additional
+/// public memebers.
class _SHA256 extends HashBase implements SHA256 {
+ /// The sixteen words from the original chunk, extended to 64 words.
+ ///
+ /// This is an instance variable to avoid re-allocating, but its data isn't
+ /// used across invocations of [updateHash].
final Uint32List _w;
- // Construct a SHA256 hasher object.
_SHA256()
: _w = new Uint32List(64),
super(16, 8, true) {
@@ -38,13 +45,11 @@
h[7] = 0x5be0cd19;
}
- // Returns a new instance of this Hash.
SHA256 newInstance() {
return new _SHA256();
}
- // Table of round constants. First 32 bits of the fractional
- // parts of the cube roots of the first 64 prime numbers.
+ /// Data from a non-linear function that functions as reproducible noise.
static const List<int> _K = const [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
@@ -61,7 +66,9 @@
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];
- // Helper functions as defined in http://tools.ietf.org/html/rfc6234
+ // The following helper functions are taken directly from
+ // http://tools.ietf.org/html/rfc6234.
+
_rotr32(n, x) => (x >> n) | ((x << (32 - n)) & MASK_32);
_ch(x, y, z) => (x & y) ^ ((~x & MASK_32) & z);
_maj(x, y, z) => (x & y) ^ (x & z) ^ (y & z);
@@ -70,8 +77,6 @@
_ssig0(x) => _rotr32(7, x) ^ _rotr32(18, x) ^ (x >> 3);
_ssig1(x) => _rotr32(17, x) ^ _rotr32(19, x) ^ (x >> 10);
- // Compute one iteration of the SHA256 algorithm with a chunk of
- // 16 32-bit pieces.
void updateHash(Uint32List M) {
assert(M.length == 16);
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 3f8a5c9..f2f265d 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -4,20 +4,23 @@
library crypto.utils;
-// Constants.
+/// A bitmask that limits an integer to 8 bits.
const MASK_8 = 0xff;
+
+/// A bitmask that limits an integer to 32 bits.
const MASK_32 = 0xffffffff;
+
+/// The number of bits in a byte.
const BITS_PER_BYTE = 8;
+
+/// The number of bytes in a 32-bit word.
const BYTES_PER_WORD = 4;
-// Helper methods.
+/// Adds [x] and [y] with 32-bit overflow semantics.
int add32(x, y) => (x + y) & MASK_32;
-int roundUp(val, n) => (val + n - 1) & -n;
-
-// Helper functions used by more than one hasher.
-
-// Rotate left limiting to unsigned 32-bit values.
+/// Bitwise rotates [val] to the left by [shift], obeying 32-bit overflow
+/// semantics.
int rotl32(int val, int shift) {
var mod_shift = shift & 31;
return ((val << mod_shift) & MASK_32) |