diff --git a/lib/cryptography_utils.dart b/lib/cryptography_utils.dart index 405058bd..eea2d787 100644 --- a/lib/cryptography_utils.dart +++ b/lib/cryptography_utils.dart @@ -6,6 +6,9 @@ export 'src/hash/hmac.dart'; export 'src/hash/keccak/keccak.dart'; export 'src/hash/pbkdf2.dart'; export 'src/hash/ripemd160.dart'; +export 'src/hash/sha/hash/digest.dart'; +export 'src/hash/sha/sha256/sha256.dart'; +export 'src/hash/sha/sha512/sha512.dart'; export 'src/signer/export.dart'; export 'src/slip/slip.dart'; export 'src/transactions/export.dart'; diff --git a/lib/src/bip/bip32/address_encoders/bitcoin/bitcoin_p2pkh_address_encoder.dart b/lib/src/bip/bip32/address_encoders/bitcoin/bitcoin_p2pkh_address_encoder.dart index cae6d51e..568f874f 100644 --- a/lib/src/bip/bip32/address_encoders/bitcoin/bitcoin_p2pkh_address_encoder.dart +++ b/lib/src/bip/bip32/address_encoders/bitcoin/bitcoin_p2pkh_address_encoder.dart @@ -1,7 +1,6 @@ import 'dart:typed_data'; import 'package:codec_utils/codec_utils.dart'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; /// The [BitcoinP2PKHAddressEncoder] class is designed for encoding P2PKH (Pay-to-PubKey-Hash) addresses in accordance with Bitcoin. @@ -9,6 +8,7 @@ import 'package:cryptography_utils/cryptography_utils.dart'; /// Through these methods, it produces addresses prefixed with '1 and encoded with Base58Check'. class BitcoinP2PKHAddressEncoder extends ABlockchainAddressEncoder { static const List _networkVersionBytes = [0x00]; + final PublicKeyMode publicKeyMode; BitcoinP2PKHAddressEncoder({ @@ -25,7 +25,7 @@ class BitcoinP2PKHAddressEncoder extends ABlockchainAddressEncoder[..._networkVersionBytes, ...publicKeyHash])); diff --git a/lib/src/bip/bip32/address_encoders/bitcoin/bitcoin_p2sh_address_encoder.dart b/lib/src/bip/bip32/address_encoders/bitcoin/bitcoin_p2sh_address_encoder.dart index f07f916d..04635789 100644 --- a/lib/src/bip/bip32/address_encoders/bitcoin/bitcoin_p2sh_address_encoder.dart +++ b/lib/src/bip/bip32/address_encoders/bitcoin/bitcoin_p2sh_address_encoder.dart @@ -1,7 +1,6 @@ import 'dart:typed_data'; import 'package:codec_utils/codec_utils.dart'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; /// The [BitcoinP2SHAddressEncoder] class is designed for encoding P2SH (Pay-to-Script-Hash) addresses in accordance with Bitcoin. @@ -26,11 +25,11 @@ class BitcoinP2SHAddressEncoder extends ABlockchainAddressEncoder _addScriptSignature(Secp256k1PublicKey publicKey) { - Uint8List publicKeyFingerprint = Uint8List.fromList(sha256.convert(publicKey.compressed).bytes); + Uint8List publicKeyFingerprint = Sha256().convert(publicKey.compressed).byteList; Uint8List publicKeyHash = Ripemd160().process(publicKeyFingerprint); Uint8List signatureBytes = Uint8List.fromList([..._scriptBytes, ...publicKeyHash]); - Uint8List signatureFingerprint = Uint8List.fromList(sha256.convert(signatureBytes).bytes); + Uint8List signatureFingerprint = Sha256().convert(signatureBytes).byteList; Uint8List signatureHash = Ripemd160().process(signatureFingerprint); return signatureHash; diff --git a/lib/src/bip/bip32/address_encoders/bitcoin/bitcoin_p2wpkh_address_encoder.dart b/lib/src/bip/bip32/address_encoders/bitcoin/bitcoin_p2wpkh_address_encoder.dart index 672d5a1c..4258bb05 100644 --- a/lib/src/bip/bip32/address_encoders/bitcoin/bitcoin_p2wpkh_address_encoder.dart +++ b/lib/src/bip/bip32/address_encoders/bitcoin/bitcoin_p2wpkh_address_encoder.dart @@ -1,7 +1,6 @@ import 'dart:typed_data'; import 'package:codec_utils/codec_utils.dart'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; /// The [BitcoinP2WPKHAddressEncoder] class is designed for encoding P2WPKH (Pay-to-Witness-Public-Key-Hash) addresses in accordance with Bitcoin. @@ -24,7 +23,7 @@ class BitcoinP2WPKHAddressEncoder extends ABlockchainAddressEncoder @override String encodePublicKey(Secp256k1PublicKey publicKey) { - Uint8List publicKeyFingerprint = Uint8List.fromList(sha256.convert(publicKey.compressed).bytes); + Uint8List publicKeyFingerprint = Sha256().convert(publicKey.compressed).byteList; Uint8List publicKeyHash = Ripemd160().process(publicKeyFingerprint); return Bech32Codec.encode(Bech32Pair(hrp: hrp, data: publicKeyHash)); diff --git a/lib/src/bip/bip32/derivators/legacy_derivators/secp256k1_derivator.dart b/lib/src/bip/bip32/derivators/legacy_derivators/secp256k1_derivator.dart index 0aa5c62a..633c0753 100644 --- a/lib/src/bip/bip32/derivators/legacy_derivators/secp256k1_derivator.dart +++ b/lib/src/bip/bip32/derivators/legacy_derivators/secp256k1_derivator.dart @@ -31,7 +31,6 @@ import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; import 'package:cryptography_utils/src/bip/bip32/derivators/derivator_type.dart'; import 'package:cryptography_utils/src/utils/big_int_utils.dart'; @@ -60,7 +59,7 @@ class Secp256k1Derivator extends ALegacyDerivator { Future deriveMasterKey(Mnemonic mnemonic) async { LegacyMnemonicSeedGenerator seedGenerator = LegacyMnemonicSeedGenerator(); Uint8List seed = await seedGenerator.generateSeed(mnemonic); - Uint8List hmacHash = HMAC(hash: sha512, key: Bip32HMACKeys.hmacKeySecp256k1Bytes).process(seed); + Uint8List hmacHash = HMAC(hash: Sha512(), key: Bip32HMACKeys.hmacKeySecp256k1Bytes).process(seed); Uint8List privateKey = hmacHash.sublist(0, 32); Uint8List chainCode = hmacHash.sublist(32); @@ -99,7 +98,7 @@ class Secp256k1Derivator extends ALegacyDerivator { } List data = [...parentSecp256k1PublicKey.compressed, ...legacyDerivationPathElement.toBytes()]; - Uint8List hmacHash = HMAC(hash: sha512, key: parentBip32KeyMetadata.chainCode!).process(data); + Uint8List hmacHash = HMAC(hash: Sha512(), key: parentBip32KeyMetadata.chainCode!).process(data); Uint8List scalarBytes = hmacHash.sublist(0, 32); Uint8List chainCodeBytes = hmacHash.sublist(32); @@ -125,8 +124,9 @@ class Secp256k1Derivator extends ALegacyDerivator { throw ArgumentError('Cannot derive hardened key without chain code'); } - Uint8List data = Uint8List.fromList([..._hardenedPrivateKeyPrefix, ...parentSecp256k1PrivateKey.bytes, ...legacyDerivationPathElement.toBytes()]); - Uint8List hmacHash = HMAC(hash: sha512, key: parentBip32KeyMetadata.chainCode!).process(data); + Uint8List data = + Uint8List.fromList([..._hardenedPrivateKeyPrefix, ...parentSecp256k1PrivateKey.bytes, ...legacyDerivationPathElement.toBytes()]); + Uint8List hmacHash = HMAC(hash: Sha512(), key: parentBip32KeyMetadata.chainCode!).process(data); Uint8List scalarBytes = hmacHash.sublist(0, 32); Uint8List chainCodeBytes = hmacHash.sublist(32); @@ -156,7 +156,7 @@ class Secp256k1Derivator extends ALegacyDerivator { } Uint8List data = Uint8List.fromList([...parentSecp256k1PrivateKey.publicKey.compressed, ...legacyDerivationPathElement.toBytes()]); - Uint8List hmacHash = HMAC(hash: sha512, key: parentBip32KeyMetadata.chainCode!).process(data); + Uint8List hmacHash = HMAC(hash: Sha512(), key: parentBip32KeyMetadata.chainCode!).process(data); Uint8List scalarBytes = hmacHash.sublist(0, 32); Uint8List chainCodeBytes = hmacHash.sublist(32); diff --git a/lib/src/bip/bip32/keys/a_bip32_public_key.dart b/lib/src/bip/bip32/keys/a_bip32_public_key.dart index 4dd9733b..a2a56b81 100644 --- a/lib/src/bip/bip32/keys/a_bip32_public_key.dart +++ b/lib/src/bip/bip32/keys/a_bip32_public_key.dart @@ -1,7 +1,6 @@ import 'dart:typed_data'; import 'package:codec_utils/codec_utils.dart'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; import 'package:cryptography_utils/src/utils/big_int_utils.dart'; import 'package:equatable/equatable.dart'; @@ -32,7 +31,7 @@ abstract class ABip32PublicKey extends Equatable { }); static BigInt calcFingerprint(Uint8List publicKeyBytes) { - Uint8List sha256Fingerprint = Uint8List.fromList(sha256.convert(publicKeyBytes).bytes); + Uint8List sha256Fingerprint = Sha256().convert(publicKeyBytes).byteList; Uint8List ripemd160Fingerprint = Uint8List.fromList(Ripemd160().process(sha256Fingerprint)); return BigIntUtils.decode(ripemd160Fingerprint.sublist(0, 4)); } diff --git a/lib/src/bip/bip39/mnemonic.dart b/lib/src/bip/bip39/mnemonic.dart index f27101a4..99fe3057 100644 --- a/lib/src/bip/bip39/mnemonic.dart +++ b/lib/src/bip/bip39/mnemonic.dart @@ -1,10 +1,8 @@ import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; import 'package:cryptography_utils/src/utils/binary_utils.dart'; import 'package:cryptography_utils/src/utils/secure_random.dart'; - import 'package:equatable/equatable.dart'; /// The [Mnemonic] class is designed for handling mnemonic phrases, which are human-readable sequences of words used to generate and recover cryptographic keys. @@ -77,7 +75,7 @@ class Mnemonic extends Equatable { static String _calculateChecksum(Uint8List entropy) { int entropyBitsLength = entropy.length * 8; int checksumSize = entropyBitsLength ~/ 32; - List hash = sha256.convert(entropy).bytes; + List hash = Sha256().convert(entropy).byteList; return BinaryUtils.bytesToBinary(hash).substring(0, checksumSize); } diff --git a/lib/src/cdsa/ecdsa/signer/ecdsa_signer.dart b/lib/src/cdsa/ecdsa/signer/ecdsa_signer.dart index cff026da..d53b3822 100644 --- a/lib/src/cdsa/ecdsa/signer/ecdsa_signer.dart +++ b/lib/src/cdsa/ecdsa/signer/ecdsa_signer.dart @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; +import 'package:cryptography_utils/src/hash/sha/hash/a_hash.dart'; import 'package:cryptography_utils/src/utils/big_int_utils.dart'; /// This class implements the functionality necessary to generate and verify digital signatures using @@ -29,7 +29,7 @@ import 'package:cryptography_utils/src/utils/big_int_utils.dart'; /// which can then be verified by others with the signer's public key. class ECDSASigner { /// The hash function used for generating the message digest. - final Hash hashFunction; + final AHash hashFunction; /// The ECDSA private key used for signing the message. final ECPrivateKey ecPrivateKey; diff --git a/lib/src/cdsa/ecdsa/signer/ecdsa_verifier.dart b/lib/src/cdsa/ecdsa/signer/ecdsa_verifier.dart index 3e54f42c..fd2bcb94 100644 --- a/lib/src/cdsa/ecdsa/signer/ecdsa_verifier.dart +++ b/lib/src/cdsa/ecdsa/signer/ecdsa_verifier.dart @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; +import 'package:cryptography_utils/src/hash/sha/hash/a_hash.dart'; import 'package:cryptography_utils/src/utils/big_int_utils.dart'; import 'package:cryptography_utils/src/utils/ec_point_utils.dart'; @@ -31,7 +31,7 @@ import 'package:cryptography_utils/src/utils/ec_point_utils.dart'; /// of the corresponding private key and that the data has not been altered since it was signed. class ECDSAVerifier { /// The hash function used for generating the message digest. - final Hash hashFunction; + final AHash hashFunction; /// The ECDSA public key which will be used to verification. final ECPublicKey ecPublicKey; diff --git a/lib/src/cdsa/ecdsa/signer/rfc6979.dart b/lib/src/cdsa/ecdsa/signer/rfc6979.dart index f585f39c..c564af9d 100644 --- a/lib/src/cdsa/ecdsa/signer/rfc6979.dart +++ b/lib/src/cdsa/ecdsa/signer/rfc6979.dart @@ -20,15 +20,15 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; +import 'package:cryptography_utils/src/hash/sha/hash/a_hash.dart'; import 'package:cryptography_utils/src/utils/big_int_utils.dart'; import 'package:cryptography_utils/src/utils/bytes_utils.dart'; /// The `RFC6979` class implements the deterministic generation of the ephemeral key 'k' for ECDSA signatures as outlined in RFC 6979. /// https://www.rfc-editor.org/rfc/rfc6979.html#section-3.2 class RFC6979 { - late final Hash _hashFunction; + late final AHash _hashFunction; late final int _hLen; late final List _m; @@ -49,7 +49,7 @@ class RFC6979 { required BigInt d, /// RFC6979 H parameter - required Hash hashFunction, + required AHash hashFunction, }) { _m = m; _n = n; diff --git a/lib/src/hash/hmac.dart b/lib/src/hash/hmac.dart index 44e6eaa4..48727231 100644 --- a/lib/src/hash/hmac.dart +++ b/lib/src/hash/hmac.dart @@ -1,11 +1,11 @@ import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; +import 'package:cryptography_utils/src/hash/sha/hash/a_hash.dart'; /// Hash-based Message Authentication Code. /// It computes a MAC using a given hash function with a secret key and input data. class HMAC { - final Hash hash; + final AHash hash; late final List key; final List _chunks = []; @@ -50,8 +50,8 @@ class HMAC { Uint8List get digest { Uint8List message = _chunks.fold(Uint8List(0), (Uint8List previous, Uint8List chunk) => Uint8List.fromList(previous + chunk)); - List innerHash = hash.convert(iKeyPad + message).bytes; - List finalHash = hash.convert(oKeyPad + innerHash).bytes; + List innerHash = hash.convert(iKeyPad + message).byteList; + List finalHash = hash.convert(oKeyPad + innerHash).byteList; return Uint8List.fromList(finalHash); } @@ -60,7 +60,7 @@ class HMAC { Uint8List _normalizeKey(List key) { Uint8List normalizedKey = Uint8List.fromList(key); if (normalizedKey.length > digestSize) { - normalizedKey = Uint8List.fromList(hash.convert(key).bytes); + normalizedKey = Uint8List.fromList(hash.convert(key).byteList); } if (normalizedKey.length < digestSize) { List padding = List.filled(digestSize - normalizedKey.length, 0); diff --git a/lib/src/hash/pbkdf2.dart b/lib/src/hash/pbkdf2.dart index 7bcf73fe..e49795a3 100644 --- a/lib/src/hash/pbkdf2.dart +++ b/lib/src/hash/pbkdf2.dart @@ -31,8 +31,8 @@ import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; +import 'package:cryptography_utils/src/hash/sha/hash/a_hash.dart'; /// The [PBKDF2] class utilizes the PBKDF2 (Password-Based Key Derivation Function 2) hashing algorithm /// to generate secure cryptographic keys from passwords. It is frequently applied for hashing passwords @@ -40,13 +40,13 @@ import 'package:cryptography_utils/cryptography_utils.dart'; class PBKDF2 { final int iterations; final int outputLength; - final Hash hash; + final AHash hash; PBKDF2({ this.iterations = 2048, this.outputLength = 64, - this.hash = sha512, - }); + AHash? hash, + }) : hash = hash ?? Sha512(); /// Derives a cryptographic key from the provided password and salt using the PBKDF2 algorithm. Uint8List process(Uint8List password, Uint8List salt) { diff --git a/lib/src/hash/sha/hash/a_hash.dart b/lib/src/hash/sha/hash/a_hash.dart new file mode 100644 index 00000000..14f2f9b3 --- /dev/null +++ b/lib/src/hash/sha/hash/a_hash.dart @@ -0,0 +1,50 @@ +//This class was primarily influenced by: +// Copyright 2015, the Dart project authors. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import 'dart:convert'; + +import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; +import 'package:cryptography_utils/src/hash/sha/hash/digest_sink.dart'; + +/// [AHash] serves as an abstraction for cryptographic hash functions, managing the conversion of byte input into a digest. It ensures a modular and structured approach to hashing, defining a standard interface for processing data in both single-pass and chunked modes. +abstract class AHash extends Converter, Digest> { + @override + Digest convert(List input) { + DigestSink digestSink = DigestSink(); + startChunkedConversion(digestSink) + ..add(input) + ..close(); + return digestSink.valueDigest; + } + + @override + ByteConversionSink startChunkedConversion(Sink sink); + + int get blockSize; +} diff --git a/lib/src/hash/sha/hash/a_hash_sink.dart b/lib/src/hash/sha/hash/a_hash_sink.dart new file mode 100644 index 00000000..051fa58b --- /dev/null +++ b/lib/src/hash/sha/hash/a_hash_sink.dart @@ -0,0 +1,140 @@ +//This class was primarily influenced by: +// Copyright 2015, the Dart project authors. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import 'dart:typed_data'; + +import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; +import 'package:typed_data/typed_data.dart'; + +/// [AHashSink] is a base class for processing streaming hash input efficiently. It handles incoming data in chunks, manages buffering, and ensures correct endian formatting. +abstract class AHashSink implements Sink> { + static const int bitsPerByte = 8; + static const int bytesPerWord = 4; + static const int mask32 = 0xFFFFFFFF; + + final Sink _sink; + final Endian _endian; + final Uint32List _currentUint8List; + final int _signatureBytes; + final Uint8Buffer _pendingUint8Buffer = Uint8Buffer(); + + int _lengthInBytes = 0; + bool _closedBool = false; + + AHashSink(this._sink, int chunkSize, {Endian endian = Endian.big, int signaturesBytes = 8}) + : _endian = endian, + _signatureBytes = signaturesBytes, + _currentUint8List = Uint32List(chunkSize); + + @override + void add(List dataList) { + if (_closedBool) { + return; + } + _lengthInBytes += dataList.length; + _pendingUint8Buffer.addAll(dataList); + _applyIterate(); + } + + @override + void close() { + if (_closedBool) { + return; + } + _closedBool = true; + _finalizeData(); + _applyIterate(); + _sink + ..add(Digest(_applyByteDigest())) + ..close(); + } + + Uint32List get digestUint32List; + + void updateHash(Uint32List inputUint32List); + + void _applyIterate() { + ByteData pendingByteData = _pendingUint8Buffer.buffer.asByteData(); + int pendingData = _pendingUint8Buffer.length ~/ _currentUint8List.lengthInBytes; + + for (int i = 0; i < pendingData; i++) { + for (int j = 0; j < _currentUint8List.length; j++) { + _currentUint8List[j] = pendingByteData.getUint32(i * _currentUint8List.lengthInBytes + j * bytesPerWord, _endian); + } + updateHash(_currentUint8List); + } + + _pendingUint8Buffer.removeRange(0, pendingData * _currentUint8List.lengthInBytes); + } + + Uint8List _applyByteDigest() { + if (_endian == Endian.host) { + return digestUint32List.buffer.asUint8List(); + } + Uint32List cacheUint32List = digestUint32List; + Uint8List digestUint8List = Uint8List(cacheUint32List.lengthInBytes); + ByteData currentByteData = digestUint8List.buffer.asByteData(); + for (int i = 0; i < cacheUint32List.length; i++) { + currentByteData.setUint32(i * bytesPerWord, cacheUint32List[i]); + } + return digestUint8List; + } + + void _finalizeData() { + _pendingUint8Buffer.add(0x80); + int contentsLength = _lengthInBytes + 1 + _signatureBytes; + int finalizedLength = _applyRoundUp(contentsLength, _currentUint8List.lengthInBytes); + + for (int i = 0; i < finalizedLength - contentsLength; i++) { + _pendingUint8Buffer.add(0); + } + + int lengthInBits = _lengthInBytes * bitsPerByte; + int offsetOutput = _pendingUint8Buffer.length + (_signatureBytes - 8); + + _pendingUint8Buffer.addAll(Uint8List(_signatureBytes)); + + ByteData currentByteData = _pendingUint8Buffer.buffer.asByteData(); + int highBits = lengthInBits ~/ 0x100000000; + int lowBits = lengthInBits & mask32; + + if (_endian == Endian.big) { + currentByteData + ..setUint32(offsetOutput, highBits, _endian) + ..setUint32(offsetOutput + bytesPerWord, lowBits, _endian); + } else { + currentByteData + ..setUint32(offsetOutput, lowBits, _endian) + ..setUint32(offsetOutput + bytesPerWord, highBits, _endian); + } + } + + int _applyRoundUp(int value, int multiple) { + return (value + multiple - 1) & -multiple; + } +} diff --git a/lib/src/hash/sha/hash/digest.dart b/lib/src/hash/sha/hash/digest.dart new file mode 100644 index 00000000..9b0844f0 --- /dev/null +++ b/lib/src/hash/sha/hash/digest.dart @@ -0,0 +1,41 @@ +//This class was primarily influenced by: +// Copyright 2015, the Dart project authors. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import 'dart:typed_data'; + +import 'package:equatable/equatable.dart'; + +/// [Digest] representing the final output of a hashing algorithm, encapsulating the computed hash value as a list of bytes. +class Digest extends Equatable { + final Uint8List byteList; + + const Digest(this.byteList); + + @override + List get props => [byteList]; +} diff --git a/lib/src/hash/sha/hash/digest_sink.dart b/lib/src/hash/sha/hash/digest_sink.dart new file mode 100644 index 00000000..707f0b4c --- /dev/null +++ b/lib/src/hash/sha/hash/digest_sink.dart @@ -0,0 +1,48 @@ +//This class was primarily influenced by: +// Copyright 2015, the Dart project authors. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; + +/// [DigestSink] acts as a simple sink for capturing a digestValue. It ensures that only the first received digest is stored, preventing overwrites. +class DigestSink implements Sink { + Digest? _valueDigest; + + @override + void add(Digest valueDigest) { + if (_valueDigest != null) { + return; + } + _valueDigest = valueDigest; + } + + @override + void close() {} + + Digest get valueDigest => _valueDigest!; +} diff --git a/lib/src/hash/sha/sha256/a_sha_32bit_sink.dart b/lib/src/hash/sha/sha256/a_sha_32bit_sink.dart new file mode 100644 index 00000000..9c5dbd02 --- /dev/null +++ b/lib/src/hash/sha/sha256/a_sha_32bit_sink.dart @@ -0,0 +1,138 @@ +//This class was primarily influenced by: +// Copyright 2015, the Dart project authors. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import 'dart:typed_data'; + +import 'package:cryptography_utils/src/hash/sha/hash/a_hash_sink.dart'; +import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; + +/// [ASha32BitSink] provides hashing logic for SHA256. It processes input data in 512-bit chunks, expanding them into a 64-entry message schedule using bitwise operations. The class applies transformations, including bit rotations, modular additions, and logical operations. +abstract class ASha32BitSink extends AHashSink { + static const List _roundConstantsList = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, // + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + ]; + + final Uint32List _extendedUint32List = Uint32List(64); + final Uint32List _digestUint32List; + + ASha32BitSink(Sink sink, this._digestUint32List) : super(sink, 16); + + @override + Uint32List get digestUint32List => _digestUint32List; + + @override + void updateHash(Uint32List inputUint32List) { + for (int i = 0; i < 16; i++) { + _extendedUint32List[i] = inputUint32List[i]; + } + for (int i = 16; i < 64; i++) { + _extendedUint32List[i] = _applyAdd32(_applyAdd32(_applySmallSigma1(_extendedUint32List[i - 2]), _extendedUint32List[i - 7]), + _applyAdd32(_applySmallSigma0(_extendedUint32List[i - 15]), _extendedUint32List[i - 16])); + } + + int aHash = _digestUint32List[0]; + int bHash = _digestUint32List[1]; + int cHash = _digestUint32List[2]; + int dHash = _digestUint32List[3]; + int eHash = _digestUint32List[4]; + int fHash = _digestUint32List[5]; + int gHash = _digestUint32List[6]; + int hHash = _digestUint32List[7]; + + for (int i = 0; i < 64; i++) { + int tmp1 = _applyAdd32(_applyAdd32(hHash, _applyBigSigma1(eHash)), + _applyAdd32(_applyChoiceBits(eHash, fHash, gHash), _applyAdd32(_roundConstantsList[i], _extendedUint32List[i]))); + + int tmp2 = _applyAdd32(_applyBigSigma0(aHash), _applyMajorityBits(aHash, bHash, cHash)); + + hHash = gHash; + gHash = fHash; + fHash = eHash; + eHash = _applyAdd32(dHash, tmp1); + dHash = cHash; + cHash = bHash; + bHash = aHash; + aHash = _applyAdd32(tmp1, tmp2); + } + _digestUint32List[0] = _applyAdd32(aHash, _digestUint32List[0]); + _digestUint32List[1] = _applyAdd32(bHash, _digestUint32List[1]); + _digestUint32List[2] = _applyAdd32(cHash, _digestUint32List[2]); + _digestUint32List[3] = _applyAdd32(dHash, _digestUint32List[3]); + _digestUint32List[4] = _applyAdd32(eHash, _digestUint32List[4]); + _digestUint32List[5] = _applyAdd32(fHash, _digestUint32List[5]); + _digestUint32List[6] = _applyAdd32(gHash, _digestUint32List[6]); + _digestUint32List[7] = _applyAdd32(hHash, _digestUint32List[7]); + } + + int _applyChoiceBits(int xHash, int yHash, int zHash) { + return (xHash & yHash) ^ ((~xHash & AHashSink.mask32) & zHash); + } + + int _applyMajorityBits(int xHash, int yHash, int zHash) { + return (xHash & yHash) ^ (xHash & zHash) ^ (yHash & zHash); + } + + int _applyBigSigma0(int bits) { + return _rotationRight32(2, bits) ^ _rotationRight32(13, bits) ^ _rotationRight32(22, bits); + } + + int _applyBigSigma1(int bits) { + return _rotationRight32(6, bits) ^ _rotationRight32(11, bits) ^ _rotationRight32(25, bits); + } + + int _applySmallSigma0(int bits) { + return _rotationRight32(7, bits) ^ _rotationRight32(18, bits) ^ (bits >> 3); + } + + int _applySmallSigma1(int bits) { + return _rotationRight32(17, bits) ^ _rotationRight32(19, bits) ^ (bits >> 10); + } + + int _applyAdd32(int hash, int operand) { + return (hash + operand) & AHashSink.mask32; + } + + int _rotationRight32(int bits, int value) { + return (value >> bits) | ((value << (32 - bits)) & AHashSink.mask32); + } +} diff --git a/lib/src/hash/sha/sha256/sha256.dart b/lib/src/hash/sha/sha256/sha256.dart new file mode 100644 index 00000000..1006e333 --- /dev/null +++ b/lib/src/hash/sha/sha256/sha256.dart @@ -0,0 +1,49 @@ +//This class was primarily influenced by: +// Copyright 2015, the Dart project authors. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import 'dart:convert'; + +import 'package:cryptography_utils/src/hash/sha/hash/a_hash.dart'; +import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; +import 'package:cryptography_utils/src/hash/sha/sha256/sha256_sink.dart'; + +/// [Sha256] is a singleton implementation of the SHA-256 hashing algorithm - defines the block size. +class Sha256 extends AHash { + static const int _bytesPerWord = 4; + static final Sha256 _sha256 = Sha256._(); + + factory Sha256() => _sha256; + + Sha256._(); + + @override + int get blockSize => 16 * _bytesPerWord; + + @override + ByteConversionSink startChunkedConversion(Sink sink) => ByteConversionSink.from(Sha256Sink(sink)); +} diff --git a/lib/src/hash/sha/sha256/sha256_sink.dart b/lib/src/hash/sha/sha256/sha256_sink.dart new file mode 100644 index 00000000..b8568f67 --- /dev/null +++ b/lib/src/hash/sha/sha256/sha256_sink.dart @@ -0,0 +1,50 @@ +//This class was primarily influenced by: +// Copyright 2015, the Dart project authors. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import 'dart:typed_data'; + +import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; +import 'package:cryptography_utils/src/hash/sha/sha256/a_sha_32bit_sink.dart'; + +/// [Sha256Sink] initializes the hash state. This class processes input and applies SHA-256 transformations to compute the final digest. +class Sha256Sink extends ASha32BitSink { + Sha256Sink(Sink sink) + : super( + sink, + Uint32List.fromList([ + 0x6a09e667, + 0xbb67ae85, + 0x3c6ef372, + 0xa54ff53a, + 0x510e527f, + 0x9b05688c, + 0x1f83d9ab, + 0x5be0cd19, + ]), + ); +} diff --git a/lib/src/hash/sha/sha512/a_sha_64bit_sink.dart b/lib/src/hash/sha/sha512/a_sha_64bit_sink.dart new file mode 100644 index 00000000..db114f87 --- /dev/null +++ b/lib/src/hash/sha/sha512/a_sha_64bit_sink.dart @@ -0,0 +1,292 @@ +//This class was primarily influenced by: +// Copyright 2015, the Dart project authors. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import 'dart:typed_data'; + +import 'package:cryptography_utils/src/hash/sha/hash/a_hash_sink.dart'; +import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; + +///[ASha64BitSink] is an abstract class responsible for managing the internal state of the SHA-64 bit algorithm, using a 1600-bit state and multiple intermediate variables. It processes data through a series of transformations, including rotations, shifts, and bitwise operations, to generate the hash output. +abstract class ASha64BitSink extends AHashSink { + static const int _hashVarAIndex = _sigmaIndex4 + 2; + static const int _hashVarBIndex = _hashVarAIndex + 2; + static const int _hashVarCIndex = _hashVarBIndex + 2; + static const int _hashVarDIndex = _hashVarCIndex + 2; + static const int _hashVarEIndex = _hashVarDIndex + 2; + static const int _hashVarFIndex = _hashVarEIndex + 2; + static const int _hashVarGIndex = _hashVarFIndex + 2; + static const int _hashVarHIndex = _hashVarGIndex + 2; + static const int _rotateRightIndex1 = 0; + static const int _rotateRightIndex2 = _rotateRightIndex1 + 2; + static const int _sigmaIndex1 = _rotateRightIndex2 + 2; + static const int _sigmaIndex2 = _sigmaIndex1 + 2; + static const int _sigmaIndex3 = _sigmaIndex2 + 2; + static const int _sigmaIndex4 = _sigmaIndex3 + 2; + static const int _tmp1Index = _hashVarHIndex + 2; + static const int _tmp2Index = _tmp1Index + 2; + static const int _tmp3Index = _tmp2Index + 2; + static const int _tmp4Index = _tmp3Index + 2; + static const int _tmp5Index = _tmp4Index + 2; + static const int digestBytes = 16; + + final Uint32List _digestUint32List; + final Uint32List _extendedUint32List = Uint32List(160); + final Uint32List _numUint32List = Uint32List(12 + 16 + 10); + final Uint32List _roundConstUint32List = Uint32List.fromList([ + 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, // + 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, + 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, + 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, + 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, + 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, + 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, + 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, + 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, + 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, + 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, + 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, + 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, + 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, + 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, + 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, + 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, + 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, + 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, + 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, + 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, + 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, + 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, + 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, + 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, + 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, + 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, + 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, + 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, + 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, + 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, + 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, + 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, + 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, + 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, + 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, + 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, + 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, + 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, + 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817, + ]); + + ASha64BitSink(Sink sink, this._digestUint32List) : super(sink, 32, signaturesBytes: 16); + + @override + Uint32List get digestUint32List { + return Uint32List.view(_digestUint32List.buffer, 0, digestBytes); + } + + @override + void updateHash(Uint32List inputUint32List) { + for (int i = 0; i < 32; i++) { + _extendedUint32List[i] = inputUint32List[i]; + } + + for (int i = 32; i < 160; i += 2) { + _applySmallSigma1(_extendedUint32List, i - 2 * 2, _numUint32List, _tmp1Index); + _applyAdd(_numUint32List, _tmp1Index, _extendedUint32List, i - 7 * 2, _numUint32List, _tmp2Index); + + _applySmallSigma0(_extendedUint32List, i - 15 * 2, _numUint32List, _tmp1Index); + + _applyAdd(_numUint32List, _tmp1Index, _extendedUint32List, i - 16 * 2, _numUint32List, _tmp3Index); + _applyAdd(_numUint32List, _tmp2Index, _numUint32List, _tmp3Index, _extendedUint32List, i); + } + + _numUint32List.setRange(_hashVarAIndex, _hashVarHIndex + 2, _digestUint32List); + + for (int i = 0; i < 160; i += 2) { + _applyBigSigma1(_numUint32List, _hashVarEIndex, _numUint32List, _tmp1Index); + _applyAdd(_numUint32List, _hashVarHIndex, _numUint32List, _tmp1Index, _numUint32List, _tmp2Index); + + _applyChoiceBits(_numUint32List, _hashVarEIndex, _numUint32List, _hashVarFIndex, _numUint32List, _hashVarGIndex, _numUint32List, _tmp3Index); + + _applyAdd(_numUint32List, _tmp2Index, _numUint32List, _tmp3Index, _numUint32List, _tmp4Index); + _applyAdd(_roundConstUint32List, i, _extendedUint32List, i, _numUint32List, _tmp5Index); + _applyAdd(_numUint32List, _tmp4Index, _numUint32List, _tmp5Index, _numUint32List, _tmp1Index); + + _applyBigSigma0(_numUint32List, _hashVarAIndex, _numUint32List, _tmp3Index); + + _applyMajorityBits(_numUint32List, _hashVarAIndex, _numUint32List, _hashVarBIndex, _numUint32List, _hashVarCIndex, _numUint32List, _tmp4Index); + _applyAdd(_numUint32List, _tmp3Index, _numUint32List, _tmp4Index, _numUint32List, _tmp2Index); + + _numUint32List[_hashVarHIndex] = _numUint32List[_hashVarGIndex]; + _numUint32List[_hashVarHIndex + 1] = _numUint32List[_hashVarGIndex + 1]; + _numUint32List[_hashVarGIndex] = _numUint32List[_hashVarFIndex]; + _numUint32List[_hashVarGIndex + 1] = _numUint32List[_hashVarFIndex + 1]; + _numUint32List[_hashVarFIndex] = _numUint32List[_hashVarEIndex]; + _numUint32List[_hashVarFIndex + 1] = _numUint32List[_hashVarEIndex + 1]; + + _applyAdd(_numUint32List, _hashVarDIndex, _numUint32List, _tmp1Index, _numUint32List, _hashVarEIndex); + + _numUint32List[_hashVarDIndex] = _numUint32List[_hashVarCIndex]; + _numUint32List[_hashVarDIndex + 1] = _numUint32List[_hashVarCIndex + 1]; + _numUint32List[_hashVarCIndex] = _numUint32List[_hashVarBIndex]; + _numUint32List[_hashVarCIndex + 1] = _numUint32List[_hashVarBIndex + 1]; + _numUint32List[_hashVarBIndex] = _numUint32List[_hashVarAIndex]; + _numUint32List[_hashVarBIndex + 1] = _numUint32List[_hashVarAIndex + 1]; + + _applyAdd(_numUint32List, _tmp1Index, _numUint32List, _tmp2Index, _numUint32List, _hashVarAIndex); + } + + _applyAddWithCarry(_digestUint32List, 0, _numUint32List, _hashVarAIndex); + _applyAddWithCarry(_digestUint32List, 2, _numUint32List, _hashVarBIndex); + _applyAddWithCarry(_digestUint32List, 4, _numUint32List, _hashVarCIndex); + _applyAddWithCarry(_digestUint32List, 6, _numUint32List, _hashVarDIndex); + _applyAddWithCarry(_digestUint32List, 8, _numUint32List, _hashVarEIndex); + _applyAddWithCarry(_digestUint32List, 10, _numUint32List, _hashVarFIndex); + _applyAddWithCarry(_digestUint32List, 12, _numUint32List, _hashVarGIndex); + _applyAddWithCarry(_digestUint32List, 14, _numUint32List, _hashVarHIndex); + } + + void _applyBigSigma0(Uint32List inputUint32List, int offsetInput, Uint32List outputUint32List, int offsetRightOutput) { + _rotateRight(28, inputUint32List, offsetInput, _numUint32List, _sigmaIndex1); + _rotateRight(34, inputUint32List, offsetInput, _numUint32List, _sigmaIndex2); + _rotateRight(39, inputUint32List, offsetInput, _numUint32List, _sigmaIndex3); + + _applyXor(_numUint32List, _sigmaIndex2, _numUint32List, _sigmaIndex3, _numUint32List, _sigmaIndex4); + _applyXor(_numUint32List, _sigmaIndex1, _numUint32List, _sigmaIndex4, outputUint32List, offsetRightOutput); + } + + void _applyBigSigma1(Uint32List inputUint32List, int offsetInput, Uint32List outputUint32List, int offsetRightOutput) { + _rotateRight(14, inputUint32List, offsetInput, _numUint32List, _sigmaIndex1); + _rotateRight(18, inputUint32List, offsetInput, _numUint32List, _sigmaIndex2); + _rotateRight(41, inputUint32List, offsetInput, _numUint32List, _sigmaIndex3); + + _applyXor(_numUint32List, _sigmaIndex2, _numUint32List, _sigmaIndex3, _numUint32List, _sigmaIndex4); + _applyXor(_numUint32List, _sigmaIndex1, _numUint32List, _sigmaIndex4, outputUint32List, offsetRightOutput); + } + + void _applySmallSigma0(Uint32List inputUint32List, int offsetInput, Uint32List outputUint32List, int offsetRightOutput) { + _rotateRight(1, inputUint32List, offsetInput, _numUint32List, _sigmaIndex1); + _rotateRight(8, inputUint32List, offsetInput, _numUint32List, _sigmaIndex2); + + _shiftRight(7, inputUint32List, offsetInput, _numUint32List, _sigmaIndex3); + + _applyXor(_numUint32List, _sigmaIndex2, _numUint32List, _sigmaIndex3, _numUint32List, _sigmaIndex4); + _applyXor(_numUint32List, _sigmaIndex1, _numUint32List, _sigmaIndex4, outputUint32List, offsetRightOutput); + } + + void _applySmallSigma1(Uint32List inputUint32List, int offsetInput, Uint32List outputUint32List, int offsetRightOutput) { + _rotateRight(19, inputUint32List, offsetInput, _numUint32List, _sigmaIndex1); + _rotateRight(61, inputUint32List, offsetInput, _numUint32List, _sigmaIndex2); + + _shiftRight(6, inputUint32List, offsetInput, _numUint32List, _sigmaIndex3); + + _applyXor(_numUint32List, _sigmaIndex2, _numUint32List, _sigmaIndex3, _numUint32List, _sigmaIndex4); + _applyXor(_numUint32List, _sigmaIndex1, _numUint32List, _sigmaIndex4, outputUint32List, offsetRightOutput); + } + + void _rotateRight(int bits, Uint32List inputUint32List, int offsetInput, Uint32List outputUint32List, int offsetRightOutput) { + _shiftRight(bits, inputUint32List, offsetInput, _numUint32List, _rotateRightIndex1); + _shiftLeft(64 - bits, inputUint32List, offsetInput, _numUint32List, _rotateRightIndex2); + + _applyOr(_numUint32List, _rotateRightIndex1, _numUint32List, _rotateRightIndex2, outputUint32List, offsetRightOutput); + } + + void _applyChoiceBits(Uint32List xInputUint32List, int xOffsetInput, Uint32List yInputUint32List, int yOffsetInput, Uint32List zInputUint32List, + int zOffsetInput, Uint32List outputUint32List, int offsetRightOutput) { + outputUint32List[0 + offsetRightOutput] = + (xInputUint32List[0 + xOffsetInput] & (yInputUint32List[0 + yOffsetInput] ^ zInputUint32List[0 + zOffsetInput])) ^ + zInputUint32List[0 + zOffsetInput]; + + outputUint32List[1 + offsetRightOutput] = + (xInputUint32List[1 + xOffsetInput] & (yInputUint32List[1 + yOffsetInput] ^ zInputUint32List[1 + zOffsetInput])) ^ + zInputUint32List[1 + zOffsetInput]; + } + + void _applyMajorityBits(Uint32List xInputUint32List, int xOffsetInput, Uint32List yInputUint32List, int yOffsetInput, Uint32List zInputUint32List, + int zOffsetInput, Uint32List outputUint32List, int offsetRightOutput) { + outputUint32List[0 + offsetRightOutput] = + (xInputUint32List[0 + xOffsetInput] & (yInputUint32List[0 + yOffsetInput] | zInputUint32List[0 + zOffsetInput])) | + (yInputUint32List[0 + yOffsetInput] & zInputUint32List[0 + zOffsetInput]); + + outputUint32List[1 + offsetRightOutput] = + (xInputUint32List[1 + xOffsetInput] & (yInputUint32List[1 + yOffsetInput] | zInputUint32List[1 + zOffsetInput])) | + (yInputUint32List[1 + yOffsetInput] & zInputUint32List[1 + zOffsetInput]); + } + + void _shiftRight(int bits, Uint32List inputUint32List, int offsetInput, Uint32List outputUint32List, int offsetRightOutput) { + outputUint32List[0 + offsetRightOutput] = ((bits < 32) && (bits >= 0)) ? (inputUint32List[0 + offsetInput] >> bits) : 0; + + outputUint32List[1 + offsetRightOutput] = (bits > 32) + ? (inputUint32List[0 + offsetInput] >> (bits - 32)) + : (bits == 32) + ? inputUint32List[0 + offsetInput] + : (bits >= 0) + ? ((inputUint32List[0 + offsetInput]) << (32 - bits)) | (inputUint32List[1 + offsetInput] >> bits) + : 0; + } + + void _shiftLeft(int bits, Uint32List inputUint32List, int offsetInput, Uint32List outputUint32List, int offsetRightOutput) { + outputUint32List[0 + offsetRightOutput] = (bits > 32) + ? (inputUint32List[1 + offsetInput] << (bits - 32)) + : (bits == 32) + ? inputUint32List[1 + offsetInput] + : (bits >= 0) + ? ((inputUint32List[0 + offsetInput]) << bits) | (inputUint32List[1 + offsetInput] >> (32 - bits)) + : 0; + + outputUint32List[1 + offsetRightOutput] = ((bits < 32) && (bits >= 0)) ? (inputUint32List[1 + offsetInput] << bits) : 0; + } + + void _applyOr(Uint32List inputOneUint32List, int offsetOneInput, Uint32List inputTwoUint32List, int offsetTwoInput, Uint32List outputUint32List, + int offsetRightOutput) { + outputUint32List[0 + offsetRightOutput] = inputOneUint32List[0 + offsetOneInput] | inputTwoUint32List[0 + offsetTwoInput]; + + outputUint32List[1 + offsetRightOutput] = inputOneUint32List[1 + offsetOneInput] | inputTwoUint32List[1 + offsetTwoInput]; + } + + void _applyXor(Uint32List inputOneUint32List, int offsetOneInput, Uint32List inputTwoUint32List, int offsetTwoInput, Uint32List outputUint32List, + int offsetRightOutput) { + outputUint32List[0 + offsetRightOutput] = inputOneUint32List[0 + offsetOneInput] ^ inputTwoUint32List[0 + offsetTwoInput]; + + outputUint32List[1 + offsetRightOutput] = inputOneUint32List[1 + offsetOneInput] ^ inputTwoUint32List[1 + offsetTwoInput]; + } + + void _applyAdd(Uint32List inputOneUint32List, int offsetOneInput, Uint32List inputTwoUint32List, int offsetTwoInput, Uint32List outputUint32List, + int offsetRightOutput) { + outputUint32List[1 + offsetRightOutput] = inputOneUint32List[1 + offsetOneInput] + inputTwoUint32List[1 + offsetTwoInput]; + + outputUint32List[0 + offsetRightOutput] = inputOneUint32List[0 + offsetOneInput] + + inputTwoUint32List[0 + offsetTwoInput] + + (outputUint32List[1 + offsetRightOutput] < inputOneUint32List[1 + offsetOneInput] ? 1 : 0); + } + + void _applyAddWithCarry(Uint32List inputOneUint32List, int offsetOneInput, Uint32List inputTwoUint32List, int offsetTwoInput) { + int addTmp = inputOneUint32List[1 + offsetOneInput]; + + inputOneUint32List[1 + offsetOneInput] += inputTwoUint32List[1 + offsetTwoInput]; + inputOneUint32List[0 + offsetOneInput] += inputTwoUint32List[0 + offsetTwoInput] + (inputOneUint32List[1 + offsetOneInput] < addTmp ? 1 : 0); + } +} diff --git a/lib/src/hash/sha/sha512/sha512.dart b/lib/src/hash/sha/sha512/sha512.dart new file mode 100644 index 00000000..2f5f3cf2 --- /dev/null +++ b/lib/src/hash/sha/sha512/sha512.dart @@ -0,0 +1,49 @@ +//This class was primarily influenced by: +// Copyright 2015, the Dart project authors. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import 'dart:convert'; + +import 'package:cryptography_utils/src/hash/sha/hash/a_hash.dart'; +import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; +import 'package:cryptography_utils/src/hash/sha/sha512/sha_512_sink.dart'; + +///[Sha512] configure the hash computation, defining a block size of 32 words (128 bytes), and provides a method for starting the chunked conversion process with a custom Sha512Sink. +class Sha512 extends AHash { + static const int _bytesPerWord = 4; + static final Sha512 _sha512 = Sha512._(); + + factory Sha512() => _sha512; + + Sha512._(); + + @override + int get blockSize => 32 * _bytesPerWord; + + @override + ByteConversionSink startChunkedConversion(Sink sink) => ByteConversionSink.from(Sha512Sink(sink)); +} diff --git a/lib/src/hash/sha/sha512/sha_512_sink.dart b/lib/src/hash/sha/sha512/sha_512_sink.dart new file mode 100644 index 00000000..c13def49 --- /dev/null +++ b/lib/src/hash/sha/sha512/sha_512_sink.dart @@ -0,0 +1,58 @@ +//This class was primarily influenced by: +// crypto - Copyright 2015, the Dart project authors. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google LLC nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import 'dart:typed_data'; + +import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; +import 'package:cryptography_utils/src/hash/sha/sha512/a_sha_64bit_sink.dart'; + +///[Sha512Sink] initializes the digest state with predefined constants and specifies that the digest length is 16 bytes. +class Sha512Sink extends ASha64BitSink { + Sha512Sink(Sink sink) + : super( + sink, + Uint32List.fromList([ + 0x6a09e667, + 0xf3bcc908, + 0xbb67ae85, + 0x84caa73b, + 0x3c6ef372, + 0xfe94f82b, + 0xa54ff53a, + 0x5f1d36f1, + 0x510e527f, + 0xade682d1, + 0x9b05688c, + 0x2b3e6c1f, + 0x1f83d9ab, + 0xfb41bd6b, + 0x5be0cd19, + 0x137e2179, + ]), + ); +} diff --git a/lib/src/signer/cosmos/cosmos_signer.dart b/lib/src/signer/cosmos/cosmos_signer.dart index 4dc4d758..55783893 100644 --- a/lib/src/signer/cosmos/cosmos_signer.dart +++ b/lib/src/signer/cosmos/cosmos_signer.dart @@ -21,7 +21,6 @@ import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; /// Provides functionality for creating Cosmos-compatible digital signatures using an ECDSA private key. @@ -34,11 +33,11 @@ class CosmosSigner { /// Signs given [CosmosSignDoc] using SIGN_MODE_DIRECT and returns the signature as an [CosmosSignature]. CosmosSignature signDirect(CosmosSignDoc signDoc) { - ECDSASigner ecdsaSigner = ECDSASigner(hashFunction: sha256, ecPrivateKey: _ecPrivateKey); + ECDSASigner ecdsaSigner = ECDSASigner(hashFunction: Sha256(), ecPrivateKey: _ecPrivateKey); CosmosVerifier cosmosVerifier = CosmosVerifier(_ecPrivateKey.ecPublicKey); Uint8List signBytes = signDoc.getDirectSignBytes(); - Uint8List hashedSignBytes = Uint8List.fromList(sha256.convert(signBytes).bytes); + Uint8List hashedSignBytes = Sha256().convert(signBytes).byteList; ECSignature ecSignature = ecdsaSigner.sign(hashedSignBytes); diff --git a/lib/src/signer/cosmos/cosmos_verifier.dart b/lib/src/signer/cosmos/cosmos_verifier.dart index 49da1bb3..17eeaaa2 100644 --- a/lib/src/signer/cosmos/cosmos_verifier.dart +++ b/lib/src/signer/cosmos/cosmos_verifier.dart @@ -1,6 +1,5 @@ import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; import 'package:cryptography_utils/src/cdsa/ecdsa/signer/ecdsa_verifier.dart'; @@ -17,11 +16,11 @@ class CosmosVerifier { /// Verifies a signature against a provided digest and the public key stored in this verifier. bool isSignatureValid(CosmosSignDoc signDoc, CosmosSignature cosmosSignature) { - ECDSAVerifier ecdsaVerifier = ECDSAVerifier(hashFunction: sha256, ecPublicKey: _ecPublicKey); + ECDSAVerifier ecdsaVerifier = ECDSAVerifier(hashFunction: Sha256(), ecPublicKey: _ecPublicKey); ECSignature ecSignature = ECSignature.fromBytes(cosmosSignature.bytes, ecCurve: _ecPublicKey.G.curve); Uint8List signBytes = signDoc.getDirectSignBytes(); - Uint8List hashedSignBytes = Uint8List.fromList(sha256.convert(signBytes).bytes); + Uint8List hashedSignBytes = Sha256().convert(signBytes).byteList; return ecdsaVerifier.isSignatureValid(hashedSignBytes, ecSignature); } diff --git a/lib/src/signer/ethereum/ethereum_signer.dart b/lib/src/signer/ethereum/ethereum_signer.dart index dc5d479e..c639d411 100644 --- a/lib/src/signer/ethereum/ethereum_signer.dart +++ b/lib/src/signer/ethereum/ethereum_signer.dart @@ -22,7 +22,6 @@ import 'dart:convert'; import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; import 'package:cryptography_utils/src/hash/keccak/keccak_bit_length.dart'; @@ -52,7 +51,7 @@ class EthereumSigner { /// Signs a digest and returns the signature as an [EthereumSignature]. This method can optionally hash the /// digest before signing, which is typically required when the input is not already a hash. EthereumSignature sign(Uint8List digest, {bool hashMessage = true}) { - ECDSASigner ecdsaSigner = ECDSASigner(hashFunction: sha256, ecPrivateKey: _ecPrivateKey); + ECDSASigner ecdsaSigner = ECDSASigner(hashFunction: Sha256(), ecPrivateKey: _ecPrivateKey); EthereumVerifier ethereumVerifier = EthereumVerifier(_ecPrivateKey.ecPublicKey); Uint8List hash = hashMessage ? Keccak(KeccakBitLength.keccak256).process(digest) : digest; diff --git a/lib/src/signer/ethereum/ethereum_verifier.dart b/lib/src/signer/ethereum/ethereum_verifier.dart index a8de8a62..a5c910eb 100644 --- a/lib/src/signer/ethereum/ethereum_verifier.dart +++ b/lib/src/signer/ethereum/ethereum_verifier.dart @@ -20,7 +20,6 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; import 'package:cryptography_utils/src/cdsa/ecdsa/signer/ecdsa_verifier.dart'; import 'package:cryptography_utils/src/hash/keccak/keccak_bit_length.dart'; @@ -43,7 +42,7 @@ class EthereumVerifier { Uint8List signatureBytes = ethereumSignature.bytes.sublist(0, EthereumSignature.ethSignatureLength); Uint8List hashDigest = hashMessage ? Keccak(KeccakBitLength.keccak256).process(digest) : digest; - ECDSAVerifier ecdsaVerifier = ECDSAVerifier(hashFunction: sha256, ecPublicKey: _ecPublicKey); + ECDSAVerifier ecdsaVerifier = ECDSAVerifier(hashFunction: Sha256(), ecPublicKey: _ecPublicKey); ECSignature ecSignature = ECSignature.fromBytes(signatureBytes, ecCurve: _ecPublicKey.G.curve); return ecdsaVerifier.isSignatureValid(hashDigest, ecSignature); } diff --git a/lib/src/transactions/cosmos/cosmos_tx.dart b/lib/src/transactions/cosmos/cosmos_tx.dart index ab3dda14..297893c2 100644 --- a/lib/src/transactions/cosmos/cosmos_tx.dart +++ b/lib/src/transactions/cosmos/cosmos_tx.dart @@ -1,7 +1,6 @@ import 'dart:typed_data'; import 'package:codec_utils/codec_utils.dart'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; /// [CosmosTx] is the standard type used for broadcasting transactions. @@ -53,7 +52,7 @@ class CosmosTx extends AProtobufObject { /// Returns the transaction hash. String getTransactionHash() { - return HexCodec.encode(sha256.convert(toProtoBytes()).bytes, includePrefixBool: true); + return HexCodec.encode(Sha256().convert(toProtoBytes()).byteList, includePrefixBool: true); } @override diff --git a/pubspec.yaml b/pubspec.yaml index 843a3211..91c7be80 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: cryptography_utils description: "Dart package containing utility methods for common cryptographic and blockchain-specific operations" publish_to: none -version: 0.0.20 +version: 0.0.21 environment: sdk: ">=3.2.6" @@ -11,10 +11,6 @@ dependencies: # https://pub.dev/packages/equatable equatable: 2.0.5 - # Implementations of SHA, MD5, and HMAC cryptographic functions. - # https://pub.dev/packages/crypto - crypto: 3.0.3 - # A Dart library implementing cryptographic algorithms and primitives, modeled on the BouncyCastle library. # https://pub.dev/packages/pointycastle pointycastle: 3.9.1 @@ -27,6 +23,10 @@ dependencies: # https://pub.dev/packages/decimal decimal: 2.3.3 + # Utility functions and classes related to the dart:typed_data library. + # https://pub.dev/packages/typed_data + typed_data: ^1.3.0 + # Dart package containing utility methods for data encoding and decoding. codec_utils: git: diff --git a/test/cdsa/ecdsa/signer/ecdsa_signer_test.dart b/test/cdsa/ecdsa/signer/ecdsa_signer_test.dart index ad163107..d5867ffe 100644 --- a/test/cdsa/ecdsa/signer/ecdsa_signer_test.dart +++ b/test/cdsa/ecdsa/signer/ecdsa_signer_test.dart @@ -1,6 +1,5 @@ import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; import 'package:test/test.dart'; @@ -16,7 +15,7 @@ void main() { // Act ECSignature actualECSignature = ECDSASigner( - hashFunction: sha256, + hashFunction: Sha256(), ecPrivateKey: actualECPrivateKey, ).sign(actualMessage); diff --git a/test/cdsa/ecdsa/signer/ecdsa_verifier_test.dart b/test/cdsa/ecdsa/signer/ecdsa_verifier_test.dart index 0f616282..9c42039d 100644 --- a/test/cdsa/ecdsa/signer/ecdsa_verifier_test.dart +++ b/test/cdsa/ecdsa/signer/ecdsa_verifier_test.dart @@ -1,6 +1,5 @@ import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; import 'package:cryptography_utils/src/cdsa/ecdsa/signer/ecdsa_verifier.dart'; import 'package:test/test.dart'; @@ -28,7 +27,7 @@ void main() { // Act bool actualSignatureValidBool = ECDSAVerifier( - hashFunction: sha256, + hashFunction: Sha256(), ecPublicKey: actualECPublicKey, ).isSignatureValid(actualMessage, actualECSignature); @@ -57,7 +56,7 @@ void main() { // Act bool actualSignatureValidBool = ECDSAVerifier( - hashFunction: sha256, + hashFunction: Sha256(), ecPublicKey: actualECPublicKey, ).isSignatureValid(actualMessage, actualECSignature); diff --git a/test/cdsa/ecdsa/signer/rfc6979_test.dart b/test/cdsa/ecdsa/signer/rfc6979_test.dart index 8b43d56b..6c38f102 100644 --- a/test/cdsa/ecdsa/signer/rfc6979_test.dart +++ b/test/cdsa/ecdsa/signer/rfc6979_test.dart @@ -1,4 +1,3 @@ -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; import 'package:test/test.dart'; @@ -10,7 +9,7 @@ void main() { m: 'Hello Word'.codeUnits, n: BigInt.parse('115792089237316195423570985008687907852837564279074904382605163141518161494337'), d: BigInt.parse('15864759622800253937020257025334897817812874204769186060960403729801414344643'), - hashFunction: sha256, + hashFunction: Sha256(), ); test('Should [return 1st k] for given message', () { diff --git a/test/hash/hmac_test.dart b/test/hash/hmac_test.dart index 5e54d0c1..0354da42 100644 --- a/test/hash/hmac_test.dart +++ b/test/hash/hmac_test.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'dart:typed_data'; -import 'package:crypto/crypto.dart'; import 'package:cryptography_utils/cryptography_utils.dart'; import 'package:test/test.dart'; @@ -13,7 +12,7 @@ void main() { Uint8List actualHMACKey = base64Decode('Qml0Y29pbiBzZWVk'); // Act - Uint8List actualHMACResult = HMAC(hash: sha256, key: actualHMACKey).process(actualDataToHash); + Uint8List actualHMACResult = HMAC(hash: Sha256(), key: actualHMACKey).process(actualDataToHash); // Assert Uint8List expectedHMACResult = base64Decode('v2mD8MCO7DhGtDEDnyf1bextorPfq2WWl4tMV9uGqEU='); @@ -27,7 +26,7 @@ void main() { Uint8List actualHMACKey = base64Decode('BucEJucuy4B7Xo9OvwvDO0Z3HokXk3DjIQC51BiJGdU='); // Act - Uint8List actualHMACResult = HMAC(hash: sha256, key: actualHMACKey).process(actualDataToHash); + Uint8List actualHMACResult = HMAC(hash: Sha256(), key: actualHMACKey).process(actualDataToHash); // Assert Uint8List expectedHMACResult = base64Decode('LmFRERNSnjn0Z1qgGrzq/iv9zSZA4kzJ/3U7CeZ5+wE='); @@ -42,7 +41,7 @@ void main() { 'ZXhjbHVkZSB3ZXN0IG5vYmxlIHB1cml0eSBiZXlvbmQgaWxsbmVzcyBzb3VwIHJlc2VtYmxlIGF0b20gb2J2aW91cyBtZXRob2QgZmVzdGl2YWwgbmFtZSBpZGVudGlmeSBlbGVwaGFudCBzYXRpc2Z5IHdlZGRpbmcgaG9uZXkgY2VydGFpbiB0b2UgZXJvZGU='); // Act - Uint8List actualHMACResult = HMAC(hash: sha256, key: actualHMACKey).process(actualDataToHash); + Uint8List actualHMACResult = HMAC(hash: Sha256(), key: actualHMACKey).process(actualDataToHash); // Assert Uint8List expectedHMACResult = base64Decode('LmFRERNSnjn0Z1qgGrzq/iv9zSZA4kzJ/3U7CeZ5+wE='); @@ -58,7 +57,7 @@ void main() { Uint8List actualHMACKey = base64Decode('Qml0Y29pbiBzZWVk'); // Act - Uint8List actualHMACResult = HMAC(hash: sha512, key: actualHMACKey).process(actualDataToHash); + Uint8List actualHMACResult = HMAC(hash: Sha512(), key: actualHMACKey).process(actualDataToHash); // Assert Uint8List expectedHMACResult = base64Decode('tNAYHKi1A1v+dYxeuRBssVzo0wD/BccFLM8Ek2MUKfghQaRFgE4jqQND6+UBYd2CADPxl03Yu1wIorDCokjZlA=='); @@ -72,7 +71,7 @@ void main() { Uint8List actualHMACKey = base64Decode('YLx7mbfIG2DJhqGhJdI0TgJGcDPyouYG/jURk8BZNr5N706v+vpVknd9X4as7jVrOkgBHFOkLmWuGSdWXTkqLw=='); // Act - Uint8List actualHMACResult = HMAC(hash: sha512, key: actualHMACKey).process(actualDataToHash); + Uint8List actualHMACResult = HMAC(hash: Sha512(), key: actualHMACKey).process(actualDataToHash); // Assert Uint8List expectedHMACResult = base64Decode('rJmboYqazBqeHW/vUXGSTcj7hE67pNaxyJoqS7/VnR0QIxDuK7+t2YWo/7X1SoAmXXoGxYQobJj8RWLZpb/LYg=='); @@ -87,7 +86,7 @@ void main() { 'ZXhjbHVkZSB3ZXN0IG5vYmxlIHB1cml0eSBiZXlvbmQgaWxsbmVzcyBzb3VwIHJlc2VtYmxlIGF0b20gb2J2aW91cyBtZXRob2QgZmVzdGl2YWwgbmFtZSBpZGVudGlmeSBlbGVwaGFudCBzYXRpc2Z5IHdlZGRpbmcgaG9uZXkgY2VydGFpbiB0b2UgZXJvZGU='); // Act - Uint8List actualHMACResult = HMAC(hash: sha512, key: actualHMACKey).process(actualDataToHash); + Uint8List actualHMACResult = HMAC(hash: Sha512(), key: actualHMACKey).process(actualDataToHash); // Assert Uint8List expectedHMACResult = base64Decode('rJmboYqazBqeHW/vUXGSTcj7hE67pNaxyJoqS7/VnR0QIxDuK7+t2YWo/7X1SoAmXXoGxYQobJj8RWLZpb/LYg=='); @@ -100,10 +99,15 @@ void main() { test('Should [return HMAC digest] constructed using SHA256 algorithm (key length < digest size)', () { // Arrange Uint8List actualHMACKey = base64Decode('Qml0Y29pbiBzZWVk'); - List actualDataChunks = [base64Decode('RE9HRQ=='), base64Decode('V0lMTA=='), base64Decode('UFVNUA=='), base64Decode('U09PTg==')]; + List actualDataChunks = [ + base64Decode('RE9HRQ=='), + base64Decode('V0lMTA=='), + base64Decode('UFVNUA=='), + base64Decode('U09PTg==') + ]; // Act - Uint8List actualHMACResult = HMAC(hash: sha256, key: actualHMACKey).processChunks(actualDataChunks); + Uint8List actualHMACResult = HMAC(hash: Sha256(), key: actualHMACKey).processChunks(actualDataChunks); // Assert Uint8List expectedHMACResult = base64Decode('7uihKHgHk+0F3U6SLKY0bkDMOXM8sypysER56JBcH5E='); @@ -114,10 +118,15 @@ void main() { test('Should [return HMAC digest] constructed using SHA256 algorithm (key length == digest size)', () { // Arrange Uint8List actualHMACKey = base64Decode('BucEJucuy4B7Xo9OvwvDO0Z3HokXk3DjIQC51BiJGdU='); - List actualDataChunks = [base64Decode('RE9HRQ=='), base64Decode('V0lMTA=='), base64Decode('UFVNUA=='), base64Decode('U09PTg==')]; + List actualDataChunks = [ + base64Decode('RE9HRQ=='), + base64Decode('V0lMTA=='), + base64Decode('UFVNUA=='), + base64Decode('U09PTg==') + ]; // Act - Uint8List actualHMACResult = HMAC(hash: sha256, key: actualHMACKey).processChunks(actualDataChunks); + Uint8List actualHMACResult = HMAC(hash: Sha256(), key: actualHMACKey).processChunks(actualDataChunks); // Assert Uint8List expectedHMACResult = base64Decode('XvKsFtyfohW5qhl46GezrMqKHGLP1i9LZ8HBRcmW5cA='); @@ -129,10 +138,15 @@ void main() { // Arrange Uint8List actualHMACKey = base64Decode( 'ZXhjbHVkZSB3ZXN0IG5vYmxlIHB1cml0eSBiZXlvbmQgaWxsbmVzcyBzb3VwIHJlc2VtYmxlIGF0b20gb2J2aW91cyBtZXRob2QgZmVzdGl2YWwgbmFtZSBpZGVudGlmeSBlbGVwaGFudCBzYXRpc2Z5IHdlZGRpbmcgaG9uZXkgY2VydGFpbiB0b2UgZXJvZGU='); - List actualDataChunks = [base64Decode('RE9HRQ=='), base64Decode('V0lMTA=='), base64Decode('UFVNUA=='), base64Decode('U09PTg==')]; + List actualDataChunks = [ + base64Decode('RE9HRQ=='), + base64Decode('V0lMTA=='), + base64Decode('UFVNUA=='), + base64Decode('U09PTg==') + ]; // Act - Uint8List actualHMACResult = HMAC(hash: sha256, key: actualHMACKey).processChunks(actualDataChunks); + Uint8List actualHMACResult = HMAC(hash: Sha256(), key: actualHMACKey).processChunks(actualDataChunks); // Assert Uint8List expectedHMACResult = base64Decode('XvKsFtyfohW5qhl46GezrMqKHGLP1i9LZ8HBRcmW5cA='); @@ -145,10 +159,15 @@ void main() { test('Should [return HMAC digest] constructed using SHA512 algorithm (key length < digest size)', () { // Arrange Uint8List actualHMACKey = base64Decode('Qml0Y29pbiBzZWVk'); - List actualDataChunks = [base64Decode('RE9HRQ=='), base64Decode('V0lMTA=='), base64Decode('UFVNUA=='), base64Decode('U09PTg==')]; + List actualDataChunks = [ + base64Decode('RE9HRQ=='), + base64Decode('V0lMTA=='), + base64Decode('UFVNUA=='), + base64Decode('U09PTg==') + ]; // Act - Uint8List actualHMACResult = HMAC(hash: sha512, key: actualHMACKey).processChunks(actualDataChunks); + Uint8List actualHMACResult = HMAC(hash: Sha512(), key: actualHMACKey).processChunks(actualDataChunks); // Assert Uint8List expectedHMACResult = base64Decode('eEpNI3pCXfnKPZ8jEXJTmKl1hJDoiEHl66YCHD9q4f7KULIwqrfw3FMraqHhfObTv692Kmans1yNHwkVG//v/g=='); @@ -159,10 +178,15 @@ void main() { test('Should [return HMAC digest] constructed using SHA512 algorithm (key length == digest size)', () { // Arrange Uint8List actualHMACKey = base64Decode('YLx7mbfIG2DJhqGhJdI0TgJGcDPyouYG/jURk8BZNr5N706v+vpVknd9X4as7jVrOkgBHFOkLmWuGSdWXTkqLw=='); - List actualDataChunks = [base64Decode('RE9HRQ=='), base64Decode('V0lMTA=='), base64Decode('UFVNUA=='), base64Decode('U09PTg==')]; + List actualDataChunks = [ + base64Decode('RE9HRQ=='), + base64Decode('V0lMTA=='), + base64Decode('UFVNUA=='), + base64Decode('U09PTg==') + ]; // Act - Uint8List actualHMACResult = HMAC(hash: sha512, key: actualHMACKey).processChunks(actualDataChunks); + Uint8List actualHMACResult = HMAC(hash: Sha512(), key: actualHMACKey).processChunks(actualDataChunks); // Assert Uint8List expectedHMACResult = base64Decode('30yTALZp0ra21ujiDOOFLf56WpOXeBrWL+Bg/LQLw7y1mgncKn9rRwX3whAiQ8miZWNNnVmM9vjMFE1OFmU/EA=='); @@ -174,10 +198,15 @@ void main() { // Arrange Uint8List actualHMACKey = base64Decode( 'ZXhjbHVkZSB3ZXN0IG5vYmxlIHB1cml0eSBiZXlvbmQgaWxsbmVzcyBzb3VwIHJlc2VtYmxlIGF0b20gb2J2aW91cyBtZXRob2QgZmVzdGl2YWwgbmFtZSBpZGVudGlmeSBlbGVwaGFudCBzYXRpc2Z5IHdlZGRpbmcgaG9uZXkgY2VydGFpbiB0b2UgZXJvZGU='); - List actualDataChunks = [base64Decode('RE9HRQ=='), base64Decode('V0lMTA=='), base64Decode('UFVNUA=='), base64Decode('U09PTg==')]; + List actualDataChunks = [ + base64Decode('RE9HRQ=='), + base64Decode('V0lMTA=='), + base64Decode('UFVNUA=='), + base64Decode('U09PTg==') + ]; // Act - Uint8List actualHMACResult = HMAC(hash: sha512, key: actualHMACKey).processChunks(actualDataChunks); + Uint8List actualHMACResult = HMAC(hash: Sha512(), key: actualHMACKey).processChunks(actualDataChunks); // Assert Uint8List expectedHMACResult = base64Decode('30yTALZp0ra21ujiDOOFLf56WpOXeBrWL+Bg/LQLw7y1mgncKn9rRwX3whAiQ8miZWNNnVmM9vjMFE1OFmU/EA=='); @@ -189,7 +218,7 @@ void main() { group('Tests of HMAC.update() method and HMAC.digest getter', () { group('Tests for SHA256 algorithm (key length < digest size)', () { Uint8List actualHMACKey = base64Decode('Qml0Y29pbiBzZWVk'); - HMAC actualHMAC = HMAC(hash: sha256, key: actualHMACKey); + HMAC actualHMAC = HMAC(hash: Sha256(), key: actualHMACKey); test('Should [return HMAC digest] constructed using SHA256 algorithm (empty chunks)', () { // Act @@ -232,7 +261,7 @@ void main() { group('Tests for SHA256 algorithm (key length == digest size)', () { Uint8List actualHMACKey = base64Decode('BucEJucuy4B7Xo9OvwvDO0Z3HokXk3DjIQC51BiJGdU='); - HMAC actualHMAC = HMAC(hash: sha256, key: actualHMACKey); + HMAC actualHMAC = HMAC(hash: Sha256(), key: actualHMACKey); test('Should [return HMAC digest] constructed using SHA256 algorithm (empty chunks)', () { // Act @@ -276,7 +305,7 @@ void main() { group('Tests for SHA256 algorithm (key length > digest size)', () { Uint8List actualHMACKey = base64Decode( 'ZXhjbHVkZSB3ZXN0IG5vYmxlIHB1cml0eSBiZXlvbmQgaWxsbmVzcyBzb3VwIHJlc2VtYmxlIGF0b20gb2J2aW91cyBtZXRob2QgZmVzdGl2YWwgbmFtZSBpZGVudGlmeSBlbGVwaGFudCBzYXRpc2Z5IHdlZGRpbmcgaG9uZXkgY2VydGFpbiB0b2UgZXJvZGU='); - HMAC actualHMAC = HMAC(hash: sha256, key: actualHMACKey); + HMAC actualHMAC = HMAC(hash: Sha256(), key: actualHMACKey); test('Should [return HMAC digest] constructed using SHA256 algorithm (empty chunks)', () { // Act @@ -321,7 +350,7 @@ void main() { group('Tests for SHA512 algorithm (key length < digest size)', () { Uint8List actualHMACKey = base64Decode('Qml0Y29pbiBzZWVk'); - HMAC actualHMAC = HMAC(hash: sha512, key: actualHMACKey); + HMAC actualHMAC = HMAC(hash: Sha512(), key: actualHMACKey); test('Should [return HMAC digest] constructed using SHA256 algorithm (empty chunks)', () { // Act @@ -364,7 +393,7 @@ void main() { group('Tests for SHA512 algorithm (key length == digest size)', () { Uint8List actualHMACKey = base64Decode('YLx7mbfIG2DJhqGhJdI0TgJGcDPyouYG/jURk8BZNr5N706v+vpVknd9X4as7jVrOkgBHFOkLmWuGSdWXTkqLw=='); - HMAC actualHMAC = HMAC(hash: sha512, key: actualHMACKey); + HMAC actualHMAC = HMAC(hash: Sha512(), key: actualHMACKey); test('Should [return HMAC digest] constructed using SHA256 algorithm (empty chunks)', () { // Act @@ -408,7 +437,7 @@ void main() { group('Tests for SHA512 algorithm (key length > digest size)', () { Uint8List actualHMACKey = base64Decode( 'ZXhjbHVkZSB3ZXN0IG5vYmxlIHB1cml0eSBiZXlvbmQgaWxsbmVzcyBzb3VwIHJlc2VtYmxlIGF0b20gb2J2aW91cyBtZXRob2QgZmVzdGl2YWwgbmFtZSBpZGVudGlmeSBlbGVwaGFudCBzYXRpc2Z5IHdlZGRpbmcgaG9uZXkgY2VydGFpbiB0b2UgZXJvZGU='); - HMAC actualHMAC = HMAC(hash: sha512, key: actualHMACKey); + HMAC actualHMAC = HMAC(hash: Sha512(), key: actualHMACKey); test('Should [return HMAC digest] constructed using SHA256 algorithm (empty chunks)', () { // Act diff --git a/test/hash/sha/hash/digest_sink_test.dart b/test/hash/sha/hash/digest_sink_test.dart new file mode 100644 index 00000000..3f407adf --- /dev/null +++ b/test/hash/sha/hash/digest_sink_test.dart @@ -0,0 +1,28 @@ +import 'dart:typed_data'; + +import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; +import 'package:cryptography_utils/src/hash/sha/hash/digest_sink.dart'; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; + +// ignore_for_file: cascade_invocations +void main() { + group('Test of DigestSink.add()', () { + test('Should [return valueDigest] constructed from given data', () { + // Arrange + DigestSink actualDigestSink = DigestSink(); + Digest actualDigest1 = Digest(Uint8List.fromList([1, 2, 3, 4])); + Digest actualDigest2 = Digest(Uint8List.fromList([5, 6, 7, 8])); + + // Act + actualDigestSink.add(actualDigest1); + actualDigestSink.add(actualDigest2); + Digest actualValueDigest = actualDigestSink.valueDigest; + + // Assert + Digest expectedValueDigest = Digest(Uint8List.fromList([1, 2, 3, 4])); + + expect(actualValueDigest, expectedValueDigest); + }); + }); +} diff --git a/test/hash/sha/sha256/sha256_sink_test.dart b/test/hash/sha/sha256/sha256_sink_test.dart new file mode 100644 index 00000000..6e2df112 --- /dev/null +++ b/test/hash/sha/sha256/sha256_sink_test.dart @@ -0,0 +1,30 @@ +import 'dart:typed_data'; + +import 'package:cryptography_utils/src/hash/sha/hash/digest_sink.dart'; +import 'package:cryptography_utils/src/hash/sha/sha256/sha256_sink.dart'; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; + +// ignore_for_file: cascade_invocations +void main() { + group('Tests of Sha256Sink.updateHash()', () { + test('Should [return hash] constructed from given data', () { + // Arrange + String actualDataToHash = 'abcdefghijklmnopqrstuvwxyz'; + Uint32List actualUint32List = Uint32List.fromList(actualDataToHash.codeUnits); + DigestSink actualDigestSink = DigestSink(); + Sha256Sink actualSha256Sink = Sha256Sink(actualDigestSink); + + // Act + actualSha256Sink.updateHash(actualUint32List); + + Uint32List actualDigestUint32List = actualSha256Sink.digestUint32List; + + // Assert + Uint32List expectedDigestUint32List = + Uint32List.fromList([402731661, 1055510437, 791927637, 2947656330, 1514833154, 2081851324, 3567160327, 163114491]); + + expect(actualDigestUint32List, expectedDigestUint32List); + }); + }); +} diff --git a/test/hash/sha/sha256/sha256_test.dart b/test/hash/sha/sha256/sha256_test.dart new file mode 100644 index 00000000..1ed0a6bb --- /dev/null +++ b/test/hash/sha/sha256/sha256_test.dart @@ -0,0 +1,25 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; +import 'package:cryptography_utils/src/hash/sha/sha256/sha256.dart'; +import 'package:test/test.dart'; + +/// For calculating [expectedHashString] an online calculator was used: https://emn178.github.io/online-tools/sha256.html +void main() { + group('Tests of Sha256.convert()', () { + test('Should [return hash] constructed from given data', () { + // Arrange + Uint8List actualDataToHash = utf8.encode('123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~'); + + // Act + Digest actualDigest = Sha256().convert(actualDataToHash); + String actualHashString = base64Encode(actualDigest.byteList); + + // Assert + String expectedHashString = '3wD7XtFKJSyhir71QWYpVt043ekXhh67rrDyHE+EsiQ='; + + expect(actualHashString, expectedHashString); + }); + }); +} diff --git a/test/hash/sha/sha512/sha512_sink_test.dart b/test/hash/sha/sha512/sha512_sink_test.dart new file mode 100644 index 00000000..524b5983 --- /dev/null +++ b/test/hash/sha/sha512/sha512_sink_test.dart @@ -0,0 +1,33 @@ +import 'dart:typed_data'; + +import 'package:cryptography_utils/src/hash/sha/hash/digest_sink.dart'; +import 'package:cryptography_utils/src/hash/sha/sha512/sha_512_sink.dart'; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; + +// ignore_for_file: cascade_invocations +void main() { + group('Tests of Sha512Sink.updateHash()', () { + test('Should [return hash] constructed from given data', () { + // Arrange + String actualDataToHash = '123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~'; + Uint32List actualUint32List = Uint32List.fromList(actualDataToHash.codeUnits); + DigestSink actualDigestSink = DigestSink(); + Sha512Sink actualSha512Sink = Sha512Sink(actualDigestSink); + + // Act + actualSha512Sink.updateHash(actualUint32List); + Uint32List actualDigestUint32List = actualSha512Sink.digestUint32List; + + // Assert + Uint32List expectedDigestUint32List = Uint32List.fromList([ + 3492118963, 1627087956, 3150871713, 3630638959, // + 3359712394, 1593454716, 1080073699, 2608846795, + 1817179099, 2060845797, 3341868678, 1197038725, + 1082521416, 2706134826, 1898010856, 931400256 + ]); + + expect(actualDigestUint32List, expectedDigestUint32List); + }); + }); +} diff --git a/test/hash/sha/sha512/sha512_test.dart b/test/hash/sha/sha512/sha512_test.dart new file mode 100644 index 00000000..fa349abf --- /dev/null +++ b/test/hash/sha/sha512/sha512_test.dart @@ -0,0 +1,26 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; +import 'package:cryptography_utils/src/hash/sha/sha512/sha512.dart'; +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; + +/// For calculating [expectedHashString] an online calculator was used: https://emn178.github.io/online-tools/sha512.html +void main() { + group('Tests of Sha512.convert()', () { + test('Should [return hash] constructed from given data', () { + // Arrange + Uint8List actualDataToHash = utf8.encode('123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~'); + + // Act + Digest actualDigest = Sha512().convert(actualDataToHash); + String actualDigestString = base64Encode(actualDigest.byteList); + + // Assert + String expectedDigestString = '+kbk+wTR/3g89X/h3p3p4V9g62usHUWM+x/aqFGvJtGUqASue9AFWm5Uc08g6E76HxO3DskHdInuJlzRqVnMSQ=='; + + expect(actualDigestString, expectedDigestString); + }); + }); +}