blob: d1585d90a8b18fd090e8b1b7fb769b0eac0cd2ea [file] [log] [blame]
// See file LICENSE for more information.
library impl.secure_random.block_ctr_random;
import 'dart:typed_data';
import 'package:pointycastle/api.dart';
import 'package:pointycastle/src/registry/registry.dart';
import 'package:pointycastle/src/ufixnum.dart';
import 'package:pointycastle/src/impl/secure_random_base.dart';
/// An implementation of [SecureRandom] that uses a [BlockCipher] with CTR mode to generate random
/// values.
class BlockCtrRandom extends SecureRandomBase implements SecureRandom {
/// Intended for internal use.
static final FactoryConfig factoryConfig = DynamicFactoryConfig.regex(
SecureRandom,
r'^(.*)/CTR/PRNG$',
(_, final Match match) => () {
var blockCipherName = match.group(1);
var blockCipher = BlockCipher(blockCipherName!);
return BlockCtrRandom(blockCipher);
});
final BlockCipher cipher;
late Uint8List _input;
late Uint8List _output;
late int _used;
BlockCtrRandom(this.cipher) {
_input = Uint8List(cipher.blockSize);
_output = Uint8List(cipher.blockSize);
_used = _output.length;
}
@override
String get algorithmName => '${cipher.algorithmName}/CTR/PRNG';
@override
void seed(CipherParameters params) {
_used = _output.length;
if (params is ParametersWithIV) {
_input.setAll(0, params.iv);
cipher.init(true, params.parameters!);
} else {
cipher.init(true, params);
}
}
@override
int nextUint8() {
if (_used == _output.length) {
cipher.processBlock(_input, 0, _output, 0);
_used = 0;
_incrementInput();
}
return clip8(_output[_used++]);
}
void _incrementInput() {
var offset = _input.length;
do {
offset--;
_input[offset] += 1;
} while (_input[offset] == 0);
}
}