Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/src/codecs/base/base58_codec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import 'dart:typed_data';

import 'package:codec_utils/src/utils/big_int_utils.dart';
import 'package:crypto/crypto.dart';
import 'package:codec_utils/src/utils/sha/sha256/sha256.dart';

/// The [Base58Codec] class is designed for encoding data using the Base58 encoding scheme.
class Base58Codec {
Expand Down Expand Up @@ -98,7 +98,7 @@ class Base58Codec {
}

static List<int> _computeChecksum(Uint8List dataBytes) {
Uint8List doubleSha256Digest = Uint8List.fromList(sha256.convert(sha256.convert(dataBytes).bytes).bytes);
Uint8List doubleSha256Digest = Sha256().convert(Sha256().convert(dataBytes).byteList).byteList;
return doubleSha256Digest.sublist(0, 4);
}
}
50 changes: 50 additions & 0 deletions lib/src/utils/sha/hash/a_hash.dart
Original file line number Diff line number Diff line change
@@ -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:codec_utils/src/utils/sha/hash/digest.dart';
import 'package:codec_utils/src/utils/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<List<int>, Digest> {
@override
Digest convert(List<int> input) {
DigestSink digestSink = DigestSink();
startChunkedConversion(digestSink)
..add(input)
..close();
return digestSink.valueDigest;
}

@override
ByteConversionSink startChunkedConversion(Sink<Digest> sink);

int get blockSize;
}
140 changes: 140 additions & 0 deletions lib/src/utils/sha/hash/a_hash_sink.dart
Original file line number Diff line number Diff line change
@@ -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:codec_utils/src/utils/sha/hash/digest.dart';
import 'package:typed_data/typed_buffers.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<List<int>> {
static const int bitsPerByte = 8;
static const int bytesPerWord = 4;
static const int mask32 = 0xFFFFFFFF;

final Sink<Digest> _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<int> 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;
}
}
41 changes: 41 additions & 0 deletions lib/src/utils/sha/hash/digest.dart
Original file line number Diff line number Diff line change
@@ -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<Uint8List> get props => <Uint8List>[byteList];
}
48 changes: 48 additions & 0 deletions lib/src/utils/sha/hash/digest_sink.dart
Original file line number Diff line number Diff line change
@@ -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:codec_utils/src/utils/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> {
Digest? _valueDigest;

@override
void add(Digest valueDigest) {
if (_valueDigest != null) {
return;
}
_valueDigest = valueDigest;
}

@override
void close() {}

Digest get valueDigest => _valueDigest!;
}
Loading
Loading