114 lines
2.8 KiB
Dart
114 lines
2.8 KiB
Dart
// This file has been migrated.
|
|
|
|
library impl.digest.cshake;
|
|
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:pointycastle/api.dart';
|
|
import 'package:pointycastle/digests/shake.dart';
|
|
import 'package:pointycastle/digests/xof_utils.dart';
|
|
import 'package:pointycastle/src/registry/registry.dart';
|
|
import 'package:pointycastle/src/utils.dart';
|
|
|
|
///
|
|
/// implementation of SHAKE based on following KeccakNISTInterface.c from http://keccak.noekeon.org/
|
|
///
|
|
/// Following the naming conventions used in the C source code to enable easy review of the implementation.
|
|
///
|
|
class CSHAKEDigest extends SHAKEDigest implements Xof {
|
|
static final RegExp _cshakeREGEX = RegExp(r'^CSHAKE-([0-9]+)$');
|
|
|
|
/// Intended for internal use.
|
|
static final FactoryConfig factoryConfig = DynamicFactoryConfig(
|
|
Digest,
|
|
_cshakeREGEX,
|
|
(_, final Match match) => () {
|
|
var bitLength = int.parse(match.group(1)!);
|
|
return CSHAKEDigest(bitLength);
|
|
});
|
|
|
|
Uint8List? _diff;
|
|
final _padding = Uint8List(100);
|
|
|
|
CSHAKEDigest([int bitLength = 256, Uint8List? N, Uint8List? S]) {
|
|
switch (bitLength) {
|
|
case 128:
|
|
case 256:
|
|
init(bitLength);
|
|
if ((N == null || N.isEmpty) && (S == null || S.isEmpty)) {
|
|
_diff = null;
|
|
} else {
|
|
_diff = concatUint8List([
|
|
XofUtils.leftEncode(rate ~/ 8),
|
|
_encodeString(N),
|
|
_encodeString(S)
|
|
]);
|
|
_diffPadAndAbsorb();
|
|
}
|
|
|
|
break;
|
|
default:
|
|
throw StateError(
|
|
'invalid bitLength ($bitLength) for CSHAKE must only be 128 or 256');
|
|
}
|
|
}
|
|
|
|
@override
|
|
String get algorithmName => 'CSHAKE-$fixedOutputLength';
|
|
@override
|
|
int doOutput(Uint8List out, int outOff, int outLen) {
|
|
if (_diff != null) {
|
|
if (!squeezing) {
|
|
absorbBits(0x00, 2);
|
|
}
|
|
|
|
squeeze(out, outOff, outLen * 8);
|
|
|
|
return outLen;
|
|
} else {
|
|
return super.doOutput(out, outOff, outLen);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void update(Uint8List inp, int inpOff, int len) {
|
|
absorbRange(inp, inpOff, len);
|
|
}
|
|
|
|
@override
|
|
void reset() {
|
|
super.reset();
|
|
|
|
if (_diff != null) {
|
|
_diffPadAndAbsorb();
|
|
}
|
|
}
|
|
|
|
// bytepad in SP 800-185
|
|
void _diffPadAndAbsorb() {
|
|
var blockSize = rate ~/ 8;
|
|
absorbRange(_diff!, 0, _diff!.length);
|
|
|
|
var delta = _diff!.length % blockSize;
|
|
|
|
// only add padding if needed
|
|
if (delta != 0) {
|
|
var required = blockSize - delta;
|
|
|
|
while (required > _padding.length) {
|
|
absorbRange(_padding, 0, _padding.length);
|
|
required -= _padding.length;
|
|
}
|
|
|
|
absorbRange(_padding, 0, required);
|
|
}
|
|
}
|
|
|
|
Uint8List _encodeString(Uint8List? str) {
|
|
if (str == null || str.isEmpty) {
|
|
return XofUtils.leftEncode(0);
|
|
}
|
|
|
|
return concatUint8List([XofUtils.leftEncode(str.length * 8), str]);
|
|
}
|
|
}
|