82 lines
2.2 KiB
Dart
82 lines
2.2 KiB
Dart
// Copyright (c) 2023, Sudipto Chandra
|
|
// All rights reserved. Check LICENSE file for details.
|
|
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:hashlib/src/core/hash_base.dart';
|
|
|
|
/// Base class used by block hash algorithms
|
|
abstract class BlockHashBase<T extends BlockHashSink> extends HashBase<T> {
|
|
const BlockHashBase();
|
|
}
|
|
|
|
/// Base class used by block hash algorithm sink implementations
|
|
abstract class BlockHashSink extends HashDigestSink {
|
|
/// The current position of data in the [buffer]
|
|
int pos = 0;
|
|
|
|
/// The message length in bytes
|
|
int messageLength = 0;
|
|
|
|
/// The internal block length of the algorithm in bytes
|
|
final int blockLength;
|
|
|
|
/// The main buffer
|
|
final Uint8List buffer;
|
|
|
|
/// The [buffer] as Uint32List
|
|
late final Uint32List sbuffer = Uint32List.view(buffer.buffer);
|
|
|
|
/// The [buffer] as ByteData
|
|
late final ByteData bdata = buffer.buffer.asByteData();
|
|
|
|
/// Get the message length in bits
|
|
int get messageLengthInBits => messageLength << 3;
|
|
|
|
/// Initialize a new sink for the block hash
|
|
///
|
|
/// Parameters:
|
|
/// - [blockLength] is the length of each block in each [$update] call.
|
|
/// - [bufferLength] is the buffer length where blocks are stored temporarily
|
|
BlockHashSink(this.blockLength, {int? bufferLength})
|
|
: assert(blockLength > 0 && (bufferLength ?? 0) >= 0),
|
|
buffer = Uint8List(bufferLength ?? blockLength);
|
|
|
|
@override
|
|
void reset() {
|
|
pos = 0;
|
|
messageLength = 0;
|
|
super.reset();
|
|
}
|
|
|
|
@override
|
|
void $process(List<int> chunk, int start, int end) {
|
|
int t = start;
|
|
if (pos > 0) {
|
|
for (; t < end && pos < blockLength; pos++, t++) {
|
|
buffer[pos] = chunk[t];
|
|
}
|
|
messageLength += t - start;
|
|
if (pos < blockLength) return;
|
|
|
|
$update(buffer);
|
|
pos = 0;
|
|
}
|
|
|
|
while ((end - t) >= blockLength) {
|
|
messageLength += blockLength;
|
|
$update(chunk, t);
|
|
t += blockLength;
|
|
}
|
|
|
|
messageLength += end - t;
|
|
for (; t < end; pos++, t++) {
|
|
buffer[pos] = chunk[t];
|
|
}
|
|
}
|
|
|
|
/// Internal method to update the message-digest with a single [block].
|
|
///
|
|
/// The method starts reading the block from [offset] index
|
|
void $update(List<int> block, [int offset = 0, bool last = false]);
|
|
}
|