Major version increment. (#104)

* Major version increment.

* Removes deprecated members,
* Makes implementation classes private (they're not needed
  by end-users which just need a single instance).
* Makes all the hash object constants.
diff --git a/.travis.yml b/.travis.yml
index f72e622..8febc61 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,11 +16,11 @@
     - stage: test
       name: "Vm Tests"
       os: linux
-      script: pub run --enable-experiment=non-nullable test -p vm
+      script: pub run test -p vm
     - stage: test
       name: "Web Tests"
       os: linux
-      script: pub run --enable-experiment=non-nullable test -p chrome
+      script: pub run test -p chrome
 
 stages:
   - analyze_and_format
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7c508f2..25b209e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,18 +1,12 @@
 
-## 2.2.0-nullsafety-dev
+## 3.0.0-nullsafety.0
 
-Pre-release for the null safety migration of this package.
-
-Note that 2.2.0 may not be the final stable null safety release version, we
-reserve the right to release it as a 3.0.0 breaking change.
-
-This release will be pinned to only allow pre-release sdk versions starting from
-2.10.0-2.0.dev, which is the first version where this package will appear in the
-null safety allow list.
+Null safety migration of this package.
 
 * Adds SHA-2 512/224 and SHA-2 512/256 from FIPS 180-4
 
-* Deprecates `newInstance` instance members on some classes and updates documentation.
+* Removes `newInstance` instance members on some classes
+  and updates documentation.
 
 ## 2.1.5
 
@@ -34,7 +28,7 @@
     publish`).
 
 ## 2.1.1
-  * Added a workaround for a bug in DDC (used in build_web_compilers 1.x). 
+  * Added a workaround for a bug in DDC (used in build_web_compilers 1.x).
   This bug is not present in DDK (used in build_web_compilers 2.x).
 
 ## 2.1.0
@@ -123,7 +117,7 @@
 * `Hash.add`, `Hash.close`, and `Hash.newInstance` are deprecated.
   `Hash.convert` should be used for hashing single values, and
   `Hash.startChunkedConversion` should be used for hashing streamed values.
-  
+
 * `SHA1` and `SHA256` are deprecated. Use the top-level `sha1` and `sha256`
   fields instead.
 
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 20b4e83..e085b9c 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,11 +1,4 @@
-include: package:pedantic/analysis_options.yaml
-analyzer:
-  strong-mode:
-    implicit-casts: false
-
-  enable-experiment:
-  - non-nullable
-
+include: package:pedantic/analysis_options.1.9.0.yaml
 linter:
   rules:
     - avoid_empty_else
diff --git a/lib/src/digest.dart b/lib/src/digest.dart
index 1bb46a3..c6b7291 100644
--- a/lib/src/digest.dart
+++ b/lib/src/digest.dart
@@ -2,8 +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.
 
+import 'dart:typed_data';
+
 import 'package:collection/collection.dart';
-import 'package:convert/convert.dart';
 
 /// A message digest as computed by a `Hash` or `HMAC` function.
 class Digest {
@@ -39,5 +40,16 @@
 
   /// The message digest as a string of hexadecimal digits.
   @override
-  String toString() => hex.encode(bytes);
+  String toString() => _hexEncode(bytes);
+}
+
+String _hexEncode(List<int> bytes) {
+  const hexDigits = '0123456789abcdef';
+  var charCodes = Uint8List(bytes.length * 2);
+  for (var i = 0, j = 0; i < bytes.length; i++) {
+    var byte = bytes[i];
+    charCodes[j++] = hexDigits.codeUnitAt((byte >> 4) & 0xF);
+    charCodes[j++] = hexDigits.codeUnitAt(byte & 0xF);
+  }
+  return String.fromCharCodes(charCodes);
 }
diff --git a/lib/src/digest_sink.dart b/lib/src/digest_sink.dart
index 008c8b9..9ba4df9 100644
--- a/lib/src/digest_sink.dart
+++ b/lib/src/digest_sink.dart
@@ -18,13 +18,12 @@
   /// Unlike most sinks, this may only be called once.
   @override
   void add(Digest value) {
-    assert(_value == null);
+    if (_value != null) throw StateError('add may only be called once.');
     _value = value;
   }
 
   @override
   void close() {
-    // Ensure late final field was assigned before closing.
-    assert(_value != null);
+    if (_value == null) throw StateError('add must be called once.');
   }
 }
diff --git a/lib/src/hash.dart b/lib/src/hash.dart
index 62299d5..cf78a9a 100644
--- a/lib/src/hash.dart
+++ b/lib/src/hash.dart
@@ -15,8 +15,8 @@
 abstract class Hash extends Converter<List<int>, Digest> {
   /// 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.
+  /// This is exposed for use by the `Hmac` class,
+  /// which needs to know the block size for the [Hash] it uses.
   int get blockSize;
 
   const Hash();
diff --git a/lib/src/md5.dart b/lib/src/md5.dart
index fa7d8b3..c4f7ff4 100644
--- a/lib/src/md5.dart
+++ b/lib/src/md5.dart
@@ -10,15 +10,13 @@
 import 'hash_sink.dart';
 import 'utils.dart';
 
-/// An instance of [MD5].
-///
-/// This instance provides convenient access to the [MD5][rfc] hash function.
+/// 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.
-final md5 = MD5._();
+const Hash md5 = _MD5._();
 
 /// An implementation of the [MD5][rfc] hash function.
 ///
@@ -28,11 +26,11 @@
 /// for backwards compatibility.
 ///
 /// Use the [md5] object to perform MD5 hashing.
-class MD5 extends Hash {
+class _MD5 extends Hash {
   @override
   final int blockSize = 16 * bytesPerWord;
 
-  MD5._();
+  const _MD5._();
 
   @override
   ByteConversionSink startChunkedConversion(Sink<Digest> sink) =>
diff --git a/lib/src/sha1.dart b/lib/src/sha1.dart
index ed7615b..933d276 100644
--- a/lib/src/sha1.dart
+++ b/lib/src/sha1.dart
@@ -10,21 +10,19 @@
 import 'hash_sink.dart';
 import 'utils.dart';
 
-/// An instance of [Sha1].
-///
-/// This instance provides convenient access to the [SHA-1][rfc] hash function.
+/// An implemention of the [SHA-1][rfc] hash function.
 ///
 /// [rfc]: http://tools.ietf.org/html/rfc3174
-final sha1 = Sha1._();
+const Hash sha1 = _Sha1._();
 
 /// An implementation of the [SHA-1][rfc] hash function.
 ///
 /// [rfc]: http://tools.ietf.org/html/rfc3174
-class Sha1 extends Hash {
+class _Sha1 extends Hash {
   @override
   final int blockSize = 16 * bytesPerWord;
 
-  Sha1._();
+  const _Sha1._();
 
   @override
   ByteConversionSink startChunkedConversion(Sink<Digest> sink) =>
diff --git a/lib/src/sha256.dart b/lib/src/sha256.dart
index 27a8440..66e7c4d 100644
--- a/lib/src/sha256.dart
+++ b/lib/src/sha256.dart
@@ -10,33 +10,26 @@
 import 'hash_sink.dart';
 import 'utils.dart';
 
-/// An instance of [Sha256].
-///
-/// This instance provides convenient access to the [Sha256][rfc] hash function.
+/// An implementation of the [SHA-256][rfc] hash function.
 ///
 /// [rfc]: http://tools.ietf.org/html/rfc6234
-final sha256 = Sha256._();
+const Hash sha256 = _Sha256._();
 
-/// An instance of [Sha224].
-///
-/// This instance provides convenient access to the [Sha224][rfc] hash function.
+/// An implementation of the [SHA-224][rfc] hash function.
 ///
 /// [rfc]: http://tools.ietf.org/html/rfc6234
-final sha224 = Sha224._();
+const Hash sha224 = _Sha224._();
 
 /// An implementation of the [SHA-256][rfc] hash function.
 ///
 /// [rfc]: http://tools.ietf.org/html/rfc6234
 ///
 /// Use the [sha256] object to perform SHA-256 hashing.
-class Sha256 extends Hash {
+class _Sha256 extends Hash {
   @override
   final int blockSize = 16 * bytesPerWord;
 
-  Sha256._();
-
-  @deprecated
-  Sha256 newInstance() => Sha256._();
+  const _Sha256._();
 
   @override
   ByteConversionSink startChunkedConversion(Sink<Digest> sink) =>
@@ -49,14 +42,11 @@
 ///
 ///
 /// Use the [sha224] object to perform SHA-224 hashing.
-class Sha224 extends Hash {
+class _Sha224 extends Hash {
   @override
   final int blockSize = 16 * bytesPerWord;
 
-  Sha224._();
-
-  @deprecated
-  Sha224 newInstance() => Sha224._();
+  const _Sha224._();
 
   @override
   ByteConversionSink startChunkedConversion(Sink<Digest> sink) =>
diff --git a/lib/src/sha512.dart b/lib/src/sha512.dart
index fcb34fd..925ad84 100644
--- a/lib/src/sha512.dart
+++ b/lib/src/sha512.dart
@@ -10,47 +10,36 @@
 import 'sha512_fastsinks.dart' if (dart.library.js) 'sha512_slowsinks.dart';
 import 'utils.dart';
 
-/// A reusable instance of [Sha384].
-///
-/// This instance provides convenient and canonical access to the
-/// [Sha384][rfc] hash functionality.
+/// An implementation of the [SHA-384][rfc] hash function.
 ///
 /// [rfc]: http://tools.ietf.org/html/rfc6234
-const sha384 = Sha384._();
+const Hash sha384 = _Sha384._();
 
-/// A reusable instance of [Sha512].
-///
-/// This instance provides convenient and canonical access to the
-/// [Sha512][rfc] hash functionality.
+/// An implementation of the [SHA-512][rfc] hash function.
 ///
 /// [rfc]: http://tools.ietf.org/html/rfc6234
-const sha512 = Sha512._();
+const Hash sha512 = _Sha512._();
 
-/// A reusable, canonical instance of the [Sha512/224][FIPS] [Hash]
-/// functionality.
+/// An implementatino of the [SHA-512/224][FIPS] hash function.
 ///
 /// [FIPS]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
-const sha512224 = _Sha512224();
+const Hash sha512224 = _Sha512224();
 
-/// A reusable, canonical instance of the [Sha512/256][FIPS] [Hash]
-/// functionality.
+/// An implementatino of the [SHA-512/256][FIPS] hash function.
 ///
 /// [FIPS]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
-const sha512256 = _Sha512256();
+const Hash sha512256 = _Sha512256();
 
 /// An implementation of the [SHA-384][rfc] hash function.
 ///
 /// [rfc]: http://tools.ietf.org/html/rfc6234
 ///
 /// Use the [sha384] object to perform SHA-384 hashing
-class Sha384 extends Hash {
+class _Sha384 extends Hash {
   @override
   final int blockSize = 32 * bytesPerWord;
 
-  const Sha384._();
-
-  @deprecated
-  Sha384 newInstance() => Sha384._();
+  const _Sha384._();
 
   @override
   ByteConversionSink startChunkedConversion(Sink<Digest> sink) =>
@@ -62,14 +51,11 @@
 /// [rfc]: http://tools.ietf.org/html/rfc6234
 ///
 /// Use the [sha512] object to perform SHA-512 hashing
-class Sha512 extends Hash {
+class _Sha512 extends Hash {
   @override
   final int blockSize = 32 * bytesPerWord;
 
-  const Sha512._();
-
-  @deprecated
-  Sha512 newInstance() => Sha512._();
+  const _Sha512._();
 
   @override
   ByteConversionSink startChunkedConversion(Sink<Digest> sink) =>
diff --git a/pubspec.yaml b/pubspec.yaml
index a9d0b0e..4e0ab56 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: crypto
-version: 2.2.0-nullsafety.0
+version: 3.0.0-nullsafety.0
 description: Implementations of SHA, MD5, and HMAC cryptographic functions
 homepage: https://www.github.com/dart-lang/crypto
 
@@ -8,7 +8,6 @@
 
 dependencies:
   collection: ^1.15.0-nullsafety
-  convert: ^3.0.0-nullsafety
   typed_data: ^1.3.0-nullsafety
 
 dev_dependencies:
@@ -16,5 +15,9 @@
   test: ^1.16.0-nullsafety
 
 dependency_overrides:
-  convert:
-    git: git://github.com/dart-lang/convert.git
+  analyzer: ^0.41.0
+  test: ^1.16.0-nullsafety.12
+  test_api: ^0.2.19-nullsafety.6
+  test_core: ^0.3.12-nullsafety.11
+  web_socket_channel:
+    git: git://github.com/dart-lang/web_socket_channel.git