// See file LICENSE for more information. library impl.secure_random.fortuna_random; import 'dart:typed_data'; import 'package:pointycastle/api.dart'; import 'package:pointycastle/block/aes.dart'; import 'package:pointycastle/random/auto_seed_block_ctr_random.dart'; import 'package:pointycastle/src/registry/registry.dart'; /// An implementation of [SecureRandom] as specified in the Fortuna algorithm. class FortunaRandom implements SecureRandom { static final FactoryConfig factoryConfig = StaticFactoryConfig(SecureRandom, 'Fortuna', () => FortunaRandom()); final AESEngine _aes; late AutoSeedBlockCtrRandom _prng; @override String get algorithmName => 'Fortuna'; FortunaRandom() : _aes = AESEngine() { _prng = AutoSeedBlockCtrRandom(_aes, false); } @override void seed(covariant KeyParameter param) { if (param.key.length != 32) { throw ArgumentError('Fortuna PRNG can only be used with 256 bits keys'); } final iv = Uint8List(16); iv[15] = 1; _prng.seed(ParametersWithIV(param, iv)); } @override int nextUint8() => _prng.nextUint8(); @override int nextUint16() => _prng.nextUint16(); @override int nextUint32() => _prng.nextUint32(); @override BigInt nextBigInteger(int bitLength) => _prng.nextBigInteger(bitLength); @override Uint8List nextBytes(int count) { if (count > 1048576) { throw ArgumentError( 'Fortuna PRNG cannot generate more than 1MB of random data per invocation'); } return _prng.nextBytes(count); } }