twonly-app-dependencies/pointycastle/lib/key_derivators/concat_kdf.dart
2025-12-07 16:10:41 +01:00

62 lines
1.9 KiB
Dart

import 'dart:typed_data';
import 'package:pointycastle/api.dart';
import 'package:pointycastle/key_derivators/api.dart';
import 'package:pointycastle/src/impl/base_key_derivator.dart';
import 'package:pointycastle/src/registry/registry.dart';
class ConcatKDFDerivator extends BaseKeyDerivator {
/// Intended for internal use.
static final FactoryConfig factoryConfig =
DynamicFactoryConfig.suffix(KeyDerivator, '/ConcatKDF', (_, Match match) {
final digestName = match.group(1);
final digest = Digest(digestName!);
return () {
return ConcatKDFDerivator(digest);
};
});
final Digest _digest;
late final HkdfParameters _parameters;
ConcatKDFDerivator(this._digest);
@override
String get algorithmName => '${_digest.algorithmName}/ConcatKDF';
@override
int deriveKey(Uint8List inp, int inpOff, Uint8List out, int outOff) {
_digest.reset();
var reps = _getReps(_parameters.desiredKeyLength, _digest.digestSize * 8);
var output = Uint8List(reps * _digest.digestSize);
var counter = Uint8List(4);
for (var i = 1; i <= reps; i++) {
var counterInt = i.toUnsigned(32);
counter[0] = (counterInt >> 24) & 255;
counter[1] = (counterInt >> 16) & 255;
counter[2] = (counterInt >> 8) & 255;
counter[3] = counterInt & 255;
_digest.update(counter, 0, 4);
_digest.update(_parameters.ikm, 0, _parameters.ikm.length);
_digest.update(_parameters.salt ?? inp.sublist(inpOff), 0,
_parameters.salt?.length ?? inp.sublist(inpOff).length);
_digest.doFinal(output, (i - 1) * _digest.digestSize);
}
out.setAll(outOff, output.getRange(0, keySize));
return keySize;
}
int _getReps(int keydatalen, int messagedigestlen) {
return (keydatalen / messagedigestlen).ceil();
}
@override
void init(covariant HkdfParameters params) {
_parameters = params;
}
@override
int get keySize => (_parameters.desiredKeyLength / 8).ceil();
}