Skip to content

Commit 8d749e4

Browse files
authored
Feature: SHA256 (#5)
The purpose of this branch is to remove the crypto library created by Dart developers from the codec_utils library. It also ensures the independence of codec_utils from our other library - cryptography_utils. This will prevent a recursive dependency between them. The SHA256 algorithm is used in Xoshiro (pseudorandom number generator) and Base58 (encoding scheme). List of changes: - created a_hash.dart, to serve as an abstraction for cryptographic hash functions by managing the conversion of byte input into a digest - created a_hash_sink.dart, to efficiently process streaming hash input by handling incoming data in chunks, managing buffering and ensuring correct endian formatting - created digest.dart, to represent the final output of hashing algorithm - created digest_sink.dart, to ensure that only the first received digest is stored, preventing overwrites - created a_sha_32bit_sink.dart, sha256.dart and sha256_sink.dart, to initialize the digest state, configure hash - computation, define a block size and provide hashing logic for SHA-256
1 parent 73196e7 commit 8d749e4

File tree

13 files changed

+611
-10
lines changed

13 files changed

+611
-10
lines changed

lib/src/codecs/base/base58_codec.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import 'dart:typed_data';
3333

3434
import 'package:codec_utils/src/utils/big_int_utils.dart';
35-
import 'package:crypto/crypto.dart';
35+
import 'package:codec_utils/src/utils/sha/sha256/sha256.dart';
3636

3737
/// The [Base58Codec] class is designed for encoding data using the Base58 encoding scheme.
3838
class Base58Codec {
@@ -98,7 +98,7 @@ class Base58Codec {
9898
}
9999

100100
static List<int> _computeChecksum(Uint8List dataBytes) {
101-
Uint8List doubleSha256Digest = Uint8List.fromList(sha256.convert(sha256.convert(dataBytes).bytes).bytes);
101+
Uint8List doubleSha256Digest = Sha256().convert(Sha256().convert(dataBytes).byteList).byteList;
102102
return doubleSha256Digest.sublist(0, 4);
103103
}
104104
}

lib/src/utils/sha/hash/a_hash.dart

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//This class was primarily influenced by:
2+
// Copyright 2015, the Dart project authors.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are
6+
// met:
7+
//
8+
// * Redistributions of source code must retain the above copyright
9+
// notice, this list of conditions and the following disclaimer.
10+
// * Redistributions in binary form must reproduce the above
11+
// copyright notice, this list of conditions and the following
12+
// disclaimer in the documentation and/or other materials provided
13+
// with the distribution.
14+
// * Neither the name of Google LLC nor the names of its
15+
// contributors may be used to endorse or promote products derived
16+
// from this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
30+
import 'dart:convert';
31+
32+
import 'package:codec_utils/src/utils/sha/hash/digest.dart';
33+
import 'package:codec_utils/src/utils/sha/hash/digest_sink.dart';
34+
35+
/// [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.
36+
abstract class AHash extends Converter<List<int>, Digest> {
37+
@override
38+
Digest convert(List<int> input) {
39+
DigestSink digestSink = DigestSink();
40+
startChunkedConversion(digestSink)
41+
..add(input)
42+
..close();
43+
return digestSink.valueDigest;
44+
}
45+
46+
@override
47+
ByteConversionSink startChunkedConversion(Sink<Digest> sink);
48+
49+
int get blockSize;
50+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
//This class was primarily influenced by:
2+
// Copyright 2015, the Dart project authors.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are
6+
// met:
7+
//
8+
// * Redistributions of source code must retain the above copyright
9+
// notice, this list of conditions and the following disclaimer.
10+
// * Redistributions in binary form must reproduce the above
11+
// copyright notice, this list of conditions and the following
12+
// disclaimer in the documentation and/or other materials provided
13+
// with the distribution.
14+
// * Neither the name of Google LLC nor the names of its
15+
// contributors may be used to endorse or promote products derived
16+
// from this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
import 'dart:typed_data';
30+
31+
import 'package:codec_utils/src/utils/sha/hash/digest.dart';
32+
import 'package:typed_data/typed_buffers.dart';
33+
34+
/// [AHashSink] is a base class for processing streaming hash input efficiently. It handles incoming data in chunks, manages buffering, and ensures correct endian formatting.
35+
abstract class AHashSink implements Sink<List<int>> {
36+
static const int bitsPerByte = 8;
37+
static const int bytesPerWord = 4;
38+
static const int mask32 = 0xFFFFFFFF;
39+
40+
final Sink<Digest> _sink;
41+
final Endian _endian;
42+
final Uint32List _currentUint8List;
43+
final int _signatureBytes;
44+
final Uint8Buffer _pendingUint8Buffer = Uint8Buffer();
45+
46+
int _lengthInBytes = 0;
47+
bool _closedBool = false;
48+
49+
AHashSink(this._sink, int chunkSize, {Endian endian = Endian.big, int signaturesBytes = 8})
50+
: _endian = endian,
51+
_signatureBytes = signaturesBytes,
52+
_currentUint8List = Uint32List(chunkSize);
53+
54+
@override
55+
void add(List<int> dataList) {
56+
if (_closedBool) {
57+
return;
58+
}
59+
_lengthInBytes += dataList.length;
60+
_pendingUint8Buffer.addAll(dataList);
61+
_applyIterate();
62+
}
63+
64+
@override
65+
void close() {
66+
if (_closedBool) {
67+
return;
68+
}
69+
_closedBool = true;
70+
_finalizeData();
71+
_applyIterate();
72+
_sink
73+
..add(Digest(_applyByteDigest()))
74+
..close();
75+
}
76+
77+
Uint32List get digestUint32List;
78+
79+
void updateHash(Uint32List inputUint32List);
80+
81+
void _applyIterate() {
82+
ByteData pendingByteData = _pendingUint8Buffer.buffer.asByteData();
83+
int pendingData = _pendingUint8Buffer.length ~/ _currentUint8List.lengthInBytes;
84+
85+
for (int i = 0; i < pendingData; i++) {
86+
for (int j = 0; j < _currentUint8List.length; j++) {
87+
_currentUint8List[j] = pendingByteData.getUint32(i * _currentUint8List.lengthInBytes + j * bytesPerWord, _endian);
88+
}
89+
updateHash(_currentUint8List);
90+
}
91+
92+
_pendingUint8Buffer.removeRange(0, pendingData * _currentUint8List.lengthInBytes);
93+
}
94+
95+
Uint8List _applyByteDigest() {
96+
if (_endian == Endian.host) {
97+
return digestUint32List.buffer.asUint8List();
98+
}
99+
Uint32List cacheUint32List = digestUint32List;
100+
Uint8List digestUint8List = Uint8List(cacheUint32List.lengthInBytes);
101+
ByteData currentByteData = digestUint8List.buffer.asByteData();
102+
for (int i = 0; i < cacheUint32List.length; i++) {
103+
currentByteData.setUint32(i * bytesPerWord, cacheUint32List[i]);
104+
}
105+
return digestUint8List;
106+
}
107+
108+
void _finalizeData() {
109+
_pendingUint8Buffer.add(0x80);
110+
int contentsLength = _lengthInBytes + 1 + _signatureBytes;
111+
int finalizedLength = _applyRoundUp(contentsLength, _currentUint8List.lengthInBytes);
112+
113+
for (int i = 0; i < finalizedLength - contentsLength; i++) {
114+
_pendingUint8Buffer.add(0);
115+
}
116+
117+
int lengthInBits = _lengthInBytes * bitsPerByte;
118+
int offsetOutput = _pendingUint8Buffer.length + (_signatureBytes - 8);
119+
120+
_pendingUint8Buffer.addAll(Uint8List(_signatureBytes));
121+
122+
ByteData currentByteData = _pendingUint8Buffer.buffer.asByteData();
123+
int highBits = lengthInBits ~/ 0x100000000;
124+
int lowBits = lengthInBits & mask32;
125+
126+
if (_endian == Endian.big) {
127+
currentByteData
128+
..setUint32(offsetOutput, highBits, _endian)
129+
..setUint32(offsetOutput + bytesPerWord, lowBits, _endian);
130+
} else {
131+
currentByteData
132+
..setUint32(offsetOutput, lowBits, _endian)
133+
..setUint32(offsetOutput + bytesPerWord, highBits, _endian);
134+
}
135+
}
136+
137+
int _applyRoundUp(int value, int multiple) {
138+
return (value + multiple - 1) & -multiple;
139+
}
140+
}

lib/src/utils/sha/hash/digest.dart

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//This class was primarily influenced by:
2+
// Copyright 2015, the Dart project authors.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are
6+
// met:
7+
//
8+
// * Redistributions of source code must retain the above copyright
9+
// notice, this list of conditions and the following disclaimer.
10+
// * Redistributions in binary form must reproduce the above
11+
// copyright notice, this list of conditions and the following
12+
// disclaimer in the documentation and/or other materials provided
13+
// with the distribution.
14+
// * Neither the name of Google LLC nor the names of its
15+
// contributors may be used to endorse or promote products derived
16+
// from this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
import 'dart:typed_data';
30+
31+
import 'package:equatable/equatable.dart';
32+
33+
/// [Digest] representing the final output of a hashing algorithm, encapsulating the computed hash value as a list of bytes.
34+
class Digest extends Equatable {
35+
final Uint8List byteList;
36+
37+
const Digest(this.byteList);
38+
39+
@override
40+
List<Uint8List> get props => <Uint8List>[byteList];
41+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//This class was primarily influenced by:
2+
// Copyright 2015, the Dart project authors.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are
6+
// met:
7+
//
8+
// * Redistributions of source code must retain the above copyright
9+
// notice, this list of conditions and the following disclaimer.
10+
// * Redistributions in binary form must reproduce the above
11+
// copyright notice, this list of conditions and the following
12+
// disclaimer in the documentation and/or other materials provided
13+
// with the distribution.
14+
// * Neither the name of Google LLC nor the names of its
15+
// contributors may be used to endorse or promote products derived
16+
// from this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
30+
import 'package:codec_utils/src/utils/sha/hash/digest.dart';
31+
32+
/// [DigestSink] acts as a simple sink for capturing a digestValue. It ensures that only the first received digest is stored, preventing overwrites.
33+
class DigestSink implements Sink<Digest> {
34+
Digest? _valueDigest;
35+
36+
@override
37+
void add(Digest valueDigest) {
38+
if (_valueDigest != null) {
39+
return;
40+
}
41+
_valueDigest = valueDigest;
42+
}
43+
44+
@override
45+
void close() {}
46+
47+
Digest get valueDigest => _valueDigest!;
48+
}

0 commit comments

Comments
 (0)