Stop using parts.

R=rnystrom@google.com

Review URL: https://codereview.chromium.org//1350933002 .
diff --git a/lib/crypto.dart b/lib/crypto.dart
index 5e85a0a..29fd62a 100644
--- a/lib/crypto.dart
+++ b/lib/crypto.dart
@@ -8,101 +8,9 @@
  */
 library crypto;
 
-import 'dart:math';
-import 'dart:typed_data';
-import 'dart:convert';
-
-part 'src/crypto_utils.dart';
-part 'src/hash_utils.dart';
-part 'src/hmac.dart';
-part 'src/md5.dart';
-part 'src/sha1.dart';
-part 'src/sha256.dart';
-part 'src/base64.dart';
-
-/**
- * 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.
- */
-// TODO(floitsch): make Hash implement Sink, EventSink or similar.
-abstract class Hash {
-  /**
-   * Add a list of bytes to the hash computation.
-   */
-  void add(List<int> data);
-
-  /**
-   * 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.
-   */
-  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.
-   */
-  int get blockSize;
-}
-
-/**
- * Utility methods for working with message digests.
- */
-class CryptoUtils {
-  /**
-   * Convert a list of bytes (for example a message digest) into a hex
-   * string.
-   */
-  static String bytesToHex(List<int> bytes) {
-    return _CryptoUtils.bytesToHex(bytes);
-  }
-
-  /**
-   * 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)
-   *
-   */
-  static String bytesToBase64(List<int> bytes,
-      {bool urlSafe: false, bool addLineSeparator: false}) {
-    return _CryptoUtils.bytesToBase64(bytes, urlSafe, 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)
-   */
-  static List<int> base64StringToBytes(String input) {
-    return _CryptoUtils.base64StringToBytes(input);
-  }
-}
+export 'src/base64.dart';
+export 'src/crypto_utils.dart';
+export 'src/hmac.dart';
+export 'src/md5.dart';
+export 'src/sha1.dart';
+export 'src/sha256.dart';
diff --git a/lib/src/base64.dart b/lib/src/base64.dart
index 1360638..ad0d8bc 100644
--- a/lib/src/base64.dart
+++ b/lib/src/base64.dart
@@ -2,7 +2,10 @@
 // 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.
 
-part of crypto;
+library crypto.base64;
+
+import 'dart:convert';
+import 'dart:typed_data';
 
 const Base64Codec BASE64 = const Base64Codec();
 
diff --git a/lib/src/crypto_utils.dart b/lib/src/crypto_utils.dart
index 42871db..8498716 100644
--- a/lib/src/crypto_utils.dart
+++ b/lib/src/crypto_utils.dart
@@ -2,9 +2,18 @@
 // 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.
 
-part of crypto;
+library crypto.crypto_utils;
 
-abstract class _CryptoUtils {
+import 'base64.dart';
+
+/**
+ * Utility methods for working with message digests.
+ */
+abstract class CryptoUtils {
+  /**
+   * Convert a list of bytes (for example a message digest) into a hex
+   * string.
+   */
   static String bytesToHex(List<int> bytes) {
     var result = new StringBuffer();
     for (var part in bytes) {
@@ -13,12 +22,37 @@
     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)
+   *
+   */
   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)
+   */
   static List<int> base64StringToBytes(String input) {
     return BASE64.decode(input);
   }
diff --git a/lib/src/hash.dart b/lib/src/hash.dart
new file mode 100644
index 0000000..03d4b1c
--- /dev/null
+++ b/lib/src/hash.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2015, 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.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.
+ */
+// TODO(floitsch): make Hash implement Sink, EventSink or similar.
+abstract class Hash {
+  /**
+   * Add a list of bytes to the hash computation.
+   */
+  void add(List<int> data);
+
+  /**
+   * 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.
+   */
+  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.
+   */
+  int get blockSize;
+}
diff --git a/lib/src/hash_utils.dart b/lib/src/hash_base.dart
similarity index 64%
rename from lib/src/hash_utils.dart
rename to lib/src/hash_base.dart
index 5fd8b07..c325fe0 100644
--- a/lib/src/hash_utils.dart
+++ b/lib/src/hash_base.dart
@@ -2,40 +2,31 @@
 // 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.
 
-part of crypto;
+library crypto.hash_base;
 
-// Constants.
-const _MASK_8 = 0xff;
-const _MASK_32 = 0xffffffff;
-const _BITS_PER_BYTE = 8;
-const _BYTES_PER_WORD = 4;
+import 'dart:math' as math;
+import 'dart:typed_data';
 
-// Helper functions used by more than one hasher.
-
-// Rotate left limiting to unsigned 32-bit values.
-int _rotl32(int val, int shift) {
-  var mod_shift = shift & 31;
-  return ((val << mod_shift) & _MASK_32) |
-      ((val & _MASK_32) >> (32 - mod_shift));
-}
+import 'hash.dart';
+import 'utils.dart';
 
 // Base class encapsulating common behavior for cryptographic hash
 // functions.
-abstract class _HashBase implements Hash {
+abstract class HashBase implements Hash {
   final int _chunkSizeInWords;
   final int _digestSizeInWords;
   final bool _bigEndianWords;
   final Uint32List _currentChunk;
-  final Uint32List _h;
+  final Uint32List h;
   int _lengthInBytes = 0;
   List<int> _pendingData;
   bool _digestCalled = false;
 
-  _HashBase(
+  HashBase(
       int chunkSizeInWords, int digestSizeInWords, bool this._bigEndianWords)
       : _pendingData = [],
         _currentChunk = new Uint32List(chunkSizeInWords),
-        _h = new Uint32List(digestSizeInWords),
+        h = new Uint32List(digestSizeInWords),
         _chunkSizeInWords = chunkSizeInWords,
         _digestSizeInWords = digestSizeInWords;
 
@@ -64,28 +55,24 @@
 
   // Returns the block size of the hash in bytes.
   int get blockSize {
-    return _chunkSizeInWords * _BYTES_PER_WORD;
+    return _chunkSizeInWords * BYTES_PER_WORD;
   }
 
   // One round of the hash computation.
-  void _updateHash(Uint32List m);
-
-  // Helper methods.
-  int _add32(x, y) => (x + y) & _MASK_32;
-  int _roundUp(val, n) => (val + n - 1) & -n;
+  void updateHash(Uint32List m);
 
   // Compute the final result as a list of bytes from the hash words.
   List<int> _resultAsBytes() {
     var result = [];
-    for (var i = 0; i < _h.length; i++) {
-      result.addAll(_wordToBytes(_h[i]));
+    for (var i = 0; i < h.length; i++) {
+      result.addAll(_wordToBytes(h[i]));
     }
     return result;
   }
 
   // Converts a list of bytes to a chunk of 32-bit words.
   void _bytesToChunk(List<int> data, int dataIndex) {
-    assert((data.length - dataIndex) >= (_chunkSizeInWords * _BYTES_PER_WORD));
+    assert((data.length - dataIndex) >= (_chunkSizeInWords * BYTES_PER_WORD));
 
     for (var wordIndex = 0; wordIndex < _chunkSizeInWords; wordIndex++) {
       var w3 = _bigEndianWords ? data[dataIndex] : data[dataIndex + 3];
@@ -94,20 +81,20 @@
       var w0 = _bigEndianWords ? data[dataIndex + 3] : data[dataIndex];
       dataIndex += 4;
       var word = (w3 & 0xff) << 24;
-      word |= (w2 & _MASK_8) << 16;
-      word |= (w1 & _MASK_8) << 8;
-      word |= (w0 & _MASK_8);
+      word |= (w2 & MASK_8) << 16;
+      word |= (w1 & MASK_8) << 8;
+      word |= (w0 & MASK_8);
       _currentChunk[wordIndex] = word;
     }
   }
 
   // Convert 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;
-    bytes[1] = (word >> (_bigEndianWords ? 16 : 8)) & _MASK_8;
-    bytes[2] = (word >> (_bigEndianWords ? 8 : 16)) & _MASK_8;
-    bytes[3] = (word >> (_bigEndianWords ? 0 : 24)) & _MASK_8;
+    List bytes = new List<int>(BYTES_PER_WORD);
+    bytes[0] = (word >> (_bigEndianWords ? 24 : 0)) & MASK_8;
+    bytes[1] = (word >> (_bigEndianWords ? 16 : 8)) & MASK_8;
+    bytes[2] = (word >> (_bigEndianWords ? 8 : 16)) & MASK_8;
+    bytes[3] = (word >> (_bigEndianWords ? 0 : 24)) & MASK_8;
     return bytes;
   }
 
@@ -115,12 +102,12 @@
   // chunk.
   void _iterate() {
     var len = _pendingData.length;
-    var chunkSizeInBytes = _chunkSizeInWords * _BYTES_PER_WORD;
+    var chunkSizeInBytes = _chunkSizeInWords * BYTES_PER_WORD;
     if (len >= chunkSizeInBytes) {
       var index = 0;
       for (; (len - index) >= chunkSizeInBytes; index += chunkSizeInBytes) {
         _bytesToChunk(_pendingData, index);
-        _updateHash(_currentChunk);
+        updateHash(_currentChunk);
       }
       _pendingData = _pendingData.sublist(index, len);
     }
@@ -131,19 +118,19 @@
   void _finalizeData() {
     _pendingData.add(0x80);
     var contentsLength = _lengthInBytes + 9;
-    var chunkSizeInBytes = _chunkSizeInWords * _BYTES_PER_WORD;
-    var finalizedLength = _roundUp(contentsLength, chunkSizeInBytes);
+    var chunkSizeInBytes = _chunkSizeInWords * BYTES_PER_WORD;
+    var finalizedLength = roundUp(contentsLength, chunkSizeInBytes);
     var zeroPadding = finalizedLength - contentsLength;
     for (var i = 0; i < zeroPadding; i++) {
       _pendingData.add(0);
     }
-    var lengthInBits = _lengthInBytes * _BITS_PER_BYTE;
-    assert(lengthInBits < pow(2, 32));
+    var lengthInBits = _lengthInBytes * BITS_PER_BYTE;
+    assert(lengthInBits < math.pow(2, 32));
     if (_bigEndianWords) {
       _pendingData.addAll(_wordToBytes(0));
-      _pendingData.addAll(_wordToBytes(lengthInBits & _MASK_32));
+      _pendingData.addAll(_wordToBytes(lengthInBits & MASK_32));
     } else {
-      _pendingData.addAll(_wordToBytes(lengthInBits & _MASK_32));
+      _pendingData.addAll(_wordToBytes(lengthInBits & MASK_32));
       _pendingData.addAll(_wordToBytes(0));
     }
   }
diff --git a/lib/src/hmac.dart b/lib/src/hmac.dart
index 4cdf81f..2e9e0ef 100644
--- a/lib/src/hmac.dart
+++ b/lib/src/hmac.dart
@@ -2,7 +2,9 @@
 // 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.
 
-part of crypto;
+library crypto.hmac;
+
+import 'hash.dart';
 
 /**
  * Hash-based Message Authentication Code support.
diff --git a/lib/src/md5.dart b/lib/src/md5.dart
index 08bc012..077b218 100644
--- a/lib/src/md5.dart
+++ b/lib/src/md5.dart
@@ -2,7 +2,13 @@
 // 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.
 
-part of crypto;
+library crypto.md5;
+
+import 'dart:typed_data';
+
+import 'hash.dart';
+import 'hash_base.dart';
+import 'utils.dart';
 
 /**
  * MD5 hash function implementation.
@@ -10,17 +16,23 @@
  * WARNING: MD5 has known collisions and should only be used when
  * required for backwards compatibility.
  */
-class MD5 extends _HashBase {
-  MD5() : super(16, 4, false) {
-    _h[0] = 0x67452301;
-    _h[1] = 0xefcdab89;
-    _h[2] = 0x98badcfe;
-    _h[3] = 0x10325476;
+abstract class MD5 implements Hash {
+  factory MD5() = _MD5;
+
+  MD5 newInstance();
+}
+
+class _MD5 extends HashBase implements MD5 {
+  _MD5() : super(16, 4, false) {
+    h[0] = 0x67452301;
+    h[1] = 0xefcdab89;
+    h[2] = 0x98badcfe;
+    h[3] = 0x10325476;
   }
 
   // Returns a new instance of this Hash.
   MD5 newInstance() {
-    return new MD5();
+    return new _MD5();
   }
 
   static const _k = const [
@@ -46,43 +58,43 @@
 
   // Compute one iteration of the MD5 algorithm with a chunk of
   // 16 32-bit pieces.
-  void _updateHash(Uint32List m) {
+  void updateHash(Uint32List m) {
     assert(m.length == 16);
 
-    var a = _h[0];
-    var b = _h[1];
-    var c = _h[2];
-    var d = _h[3];
+    var a = h[0];
+    var b = h[1];
+    var c = h[2];
+    var d = h[3];
 
     var t0;
     var t1;
 
     for (var i = 0; i < 64; i++) {
       if (i < 16) {
-        t0 = (b & c) | ((~b & _MASK_32) & d);
+        t0 = (b & c) | ((~b & MASK_32) & d);
         t1 = i;
       } else if (i < 32) {
-        t0 = (d & b) | ((~d & _MASK_32) & c);
+        t0 = (d & b) | ((~d & MASK_32) & c);
         t1 = ((5 * i) + 1) % 16;
       } else if (i < 48) {
         t0 = b ^ c ^ d;
         t1 = ((3 * i) + 5) % 16;
       } else {
-        t0 = c ^ (b | (~d & _MASK_32));
+        t0 = c ^ (b | (~d & MASK_32));
         t1 = (7 * i) % 16;
       }
 
       var temp = d;
       d = c;
       c = b;
-      b = _add32(
-          b, _rotl32(_add32(_add32(a, t0), _add32(_k[i], m[t1])), _r[i]));
+      b = add32(
+          b, rotl32(add32(add32(a, t0), add32(_k[i], m[t1])), _r[i]));
       a = temp;
     }
 
-    _h[0] = _add32(a, _h[0]);
-    _h[1] = _add32(b, _h[1]);
-    _h[2] = _add32(c, _h[2]);
-    _h[3] = _add32(d, _h[3]);
+    h[0] = add32(a, h[0]);
+    h[1] = add32(b, h[1]);
+    h[2] = add32(c, h[2]);
+    h[3] = add32(d, h[3]);
   }
 }
diff --git a/lib/src/sha1.dart b/lib/src/sha1.dart
index 3946484..d059226 100644
--- a/lib/src/sha1.dart
+++ b/lib/src/sha1.dart
@@ -2,70 +2,82 @@
 // 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.
 
-part of crypto;
+library crypto.sha1;
+
+import 'dart:typed_data';
+
+import 'hash.dart';
+import 'hash_base.dart';
+import 'utils.dart';
 
 /**
  * SHA1 hash function implementation.
  */
-class SHA1 extends _HashBase {
+abstract class SHA1 implements Hash {
+  factory SHA1() = _SHA1;
+
+  SHA1 newInstance();
+}
+
+class _SHA1 extends HashBase implements SHA1 {
   final Uint32List _w;
 
   // Construct a SHA1 hasher object.
-  SHA1()
+  _SHA1()
       : _w = new Uint32List(80),
         super(16, 5, true) {
-    _h[0] = 0x67452301;
-    _h[1] = 0xEFCDAB89;
-    _h[2] = 0x98BADCFE;
-    _h[3] = 0x10325476;
-    _h[4] = 0xC3D2E1F0;
+    h[0] = 0x67452301;
+    h[1] = 0xEFCDAB89;
+    h[2] = 0x98BADCFE;
+    h[3] = 0x10325476;
+    h[4] = 0xC3D2E1F0;
   }
 
   // Returns a new instance of this Hash.
   SHA1 newInstance() {
-    return new SHA1();
+    return new _SHA1();
   }
 
   // Compute one iteration of the SHA1 algorithm with a chunk of
   // 16 32-bit pieces.
-  void _updateHash(Uint32List m) {
+  void updateHash(Uint32List m) {
     assert(m.length == 16);
 
-    var a = _h[0];
-    var b = _h[1];
-    var c = _h[2];
-    var d = _h[3];
-    var e = _h[4];
+    var a = h[0];
+    var b = h[1];
+    var c = h[2];
+    var d = h[3];
+    var e = h[4];
 
     for (var i = 0; i < 80; i++) {
       if (i < 16) {
         _w[i] = m[i];
       } else {
         var n = _w[i - 3] ^ _w[i - 8] ^ _w[i - 14] ^ _w[i - 16];
-        _w[i] = _rotl32(n, 1);
+        _w[i] = rotl32(n, 1);
       }
-      var t = _add32(_add32(_rotl32(a, 5), e), _w[i]);
+      var t = add32(add32(rotl32(a, 5), e), _w[i]);
       if (i < 20) {
-        t = _add32(_add32(t, (b & c) | (~b & d)), 0x5A827999);
+        t = add32(add32(t, (b & c) | (~b & d)), 0x5A827999);
       } else if (i < 40) {
-        t = _add32(_add32(t, (b ^ c ^ d)), 0x6ED9EBA1);
+        t = add32(add32(t, (b ^ c ^ d)), 0x6ED9EBA1);
       } else if (i < 60) {
-        t = _add32(_add32(t, (b & c) | (b & d) | (c & d)), 0x8F1BBCDC);
+        t = add32(add32(t, (b & c) | (b & d) | (c & d)), 0x8F1BBCDC);
       } else {
-        t = _add32(_add32(t, b ^ c ^ d), 0xCA62C1D6);
+        t = add32(add32(t, b ^ c ^ d), 0xCA62C1D6);
       }
 
       e = d;
       d = c;
-      c = _rotl32(b, 30);
+      c = rotl32(b, 30);
       b = a;
-      a = t & _MASK_32;
+      a = t & MASK_32;
     }
 
-    _h[0] = _add32(a, _h[0]);
-    _h[1] = _add32(b, _h[1]);
-    _h[2] = _add32(c, _h[2]);
-    _h[3] = _add32(d, _h[3]);
-    _h[4] = _add32(e, _h[4]);
+    h[0] = add32(a, h[0]);
+    h[1] = add32(b, h[1]);
+    h[2] = add32(c, h[2]);
+    h[3] = add32(d, h[3]);
+    h[4] = add32(e, h[4]);
   }
 }
diff --git a/lib/src/sha256.dart b/lib/src/sha256.dart
index e2dc37e..158f3f9 100644
--- a/lib/src/sha256.dart
+++ b/lib/src/sha256.dart
@@ -2,33 +2,45 @@
 // 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.
 
-part of crypto;
+library crypto.sha256;
+
+import 'dart:typed_data';
+
+import 'hash.dart';
+import 'hash_base.dart';
+import 'utils.dart';
 
 /**
  * SHA256 hash function implementation.
  */
-class SHA256 extends _HashBase {
+abstract class SHA256 implements Hash {
+  factory SHA256() = _SHA256;
+
+  SHA256 newInstance();
+}
+
+class _SHA256 extends HashBase implements SHA256 {
   final Uint32List _w;
 
   // Construct a SHA256 hasher object.
-  SHA256()
+  _SHA256()
       : _w = new Uint32List(64),
         super(16, 8, true) {
     // Initial value of the hash parts. First 32 bits of the fractional parts
     // of the square roots of the first 8 prime numbers.
-    _h[0] = 0x6a09e667;
-    _h[1] = 0xbb67ae85;
-    _h[2] = 0x3c6ef372;
-    _h[3] = 0xa54ff53a;
-    _h[4] = 0x510e527f;
-    _h[5] = 0x9b05688c;
-    _h[6] = 0x1f83d9ab;
-    _h[7] = 0x5be0cd19;
+    h[0] = 0x6a09e667;
+    h[1] = 0xbb67ae85;
+    h[2] = 0x3c6ef372;
+    h[3] = 0xa54ff53a;
+    h[4] = 0x510e527f;
+    h[5] = 0x9b05688c;
+    h[6] = 0x1f83d9ab;
+    h[7] = 0x5be0cd19;
   }
 
   // Returns a new instance of this Hash.
   SHA256 newInstance() {
-    return new SHA256();
+    return new _SHA256();
   }
 
   // Table of round constants. First 32 bits of the fractional
@@ -50,8 +62,8 @@
   ];
 
   // Helper functions as defined in 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);
+  _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);
   _bsig0(x) => _rotr32(2, x) ^ _rotr32(13, x) ^ _rotr32(22, x);
   _bsig1(x) => _rotr32(6, x) ^ _rotr32(11, x) ^ _rotr32(25, x);
@@ -60,7 +72,7 @@
 
   // Compute one iteration of the SHA256 algorithm with a chunk of
   // 16 32-bit pieces.
-  void _updateHash(Uint32List M) {
+  void updateHash(Uint32List M) {
     assert(M.length == 16);
 
     // Prepare message schedule.
@@ -69,42 +81,42 @@
       _w[i] = M[i];
     }
     for (; i < 64; i++) {
-      _w[i] = _add32(_add32(_ssig1(_w[i - 2]), _w[i - 7]),
-          _add32(_ssig0(_w[i - 15]), _w[i - 16]));
+      _w[i] = add32(add32(_ssig1(_w[i - 2]), _w[i - 7]),
+          add32(_ssig0(_w[i - 15]), _w[i - 16]));
     }
 
     // Shuffle around the bits.
-    var a = _h[0];
-    var b = _h[1];
-    var c = _h[2];
-    var d = _h[3];
-    var e = _h[4];
-    var f = _h[5];
-    var g = _h[6];
-    var h = _h[7];
+    var a = h[0];
+    var b = h[1];
+    var c = h[2];
+    var d = h[3];
+    var e = h[4];
+    var f = h[5];
+    var g = h[6];
+    var j = h[7];
 
     for (var t = 0; t < 64; t++) {
-      var t1 = _add32(
-          _add32(h, _bsig1(e)), _add32(_ch(e, f, g), _add32(_K[t], _w[t])));
-      var t2 = _add32(_bsig0(a), _maj(a, b, c));
-      h = g;
+      var t1 = add32(
+          add32(j, _bsig1(e)), add32(_ch(e, f, g), add32(_K[t], _w[t])));
+      var t2 = add32(_bsig0(a), _maj(a, b, c));
+      j = g;
       g = f;
       f = e;
-      e = _add32(d, t1);
+      e = add32(d, t1);
       d = c;
       c = b;
       b = a;
-      a = _add32(t1, t2);
+      a = add32(t1, t2);
     }
 
     // Update hash values after iteration.
-    _h[0] = _add32(a, _h[0]);
-    _h[1] = _add32(b, _h[1]);
-    _h[2] = _add32(c, _h[2]);
-    _h[3] = _add32(d, _h[3]);
-    _h[4] = _add32(e, _h[4]);
-    _h[5] = _add32(f, _h[5]);
-    _h[6] = _add32(g, _h[6]);
-    _h[7] = _add32(h, _h[7]);
+    h[0] = add32(a, h[0]);
+    h[1] = add32(b, h[1]);
+    h[2] = add32(c, h[2]);
+    h[3] = add32(d, h[3]);
+    h[4] = add32(e, h[4]);
+    h[5] = add32(f, h[5]);
+    h[6] = add32(g, h[6]);
+    h[7] = add32(j, h[7]);
   }
 }
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
new file mode 100644
index 0000000..3f8a5c9
--- /dev/null
+++ b/lib/src/utils.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2015, 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.utils;
+
+// Constants.
+const MASK_8 = 0xff;
+const MASK_32 = 0xffffffff;
+const BITS_PER_BYTE = 8;
+const BYTES_PER_WORD = 4;
+
+// Helper methods.
+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.
+int rotl32(int val, int shift) {
+  var mod_shift = shift & 31;
+  return ((val << mod_shift) & MASK_32) |
+      ((val & MASK_32) >> (32 - mod_shift));
+}