diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 5c868a7e..ebc15455 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -15,3 +15,4 @@ Shammah Chancellor Rick Bellens Deniz Türkoglu Yurii Baryshev +Eric Prokop und Nils Wieler Hard- und Softwareentwicklung GbR diff --git a/lib/export.dart b/lib/export.dart index 13ea0a77..67063e42 100644 --- a/lib/export.dart +++ b/lib/export.dart @@ -79,6 +79,7 @@ export 'package:pointycastle/paddings/iso7816d4.dart'; export 'package:pointycastle/random/auto_seed_block_ctr_random.dart'; export 'package:pointycastle/random/block_ctr_random.dart'; export 'package:pointycastle/random/fortuna_random.dart'; +export 'package:pointycastle/random/dart_secure_random.dart'; // signers export 'package:pointycastle/signers/ecdsa_signer.dart'; diff --git a/lib/random/dart_secure_random.dart b/lib/random/dart_secure_random.dart new file mode 100644 index 00000000..de55dd34 --- /dev/null +++ b/lib/random/dart_secure_random.dart @@ -0,0 +1,48 @@ +// See file LICENSE for more information. + +library impl.secure_random.dart_secure_random; + +import 'dart:math'; + +import 'package:pointycastle/api.dart'; +import 'package:pointycastle/src/impl/secure_random_base.dart'; +import 'package:pointycastle/src/registry/registry.dart'; + +/// An implementation of [SecureRandom] that uses darts built-in +/// [Random] to generate random bytes. +/// +/// This implementation does not give any security guarantees, but +/// trusts the dart [Random] implementation to be cryptographically secure. +class DartSecureRandom extends SecureRandomBase implements SecureRandom { + static const String _algorithmName = 'DartSecure'; + static final FactoryConfig factoryConfig = StaticFactoryConfig( + SecureRandom, _algorithmName, () => DartSecureRandom()); + + final Random _random; + + /// A newly created secure dart [Random] is used for byte generation. + DartSecureRandom() : _random = Random.secure(); + + /// Uses an insecure dart [Random]. This constructor should not be used + /// in production! + /// + /// It is intended to be used during development when + /// generating many cryptographically secure numbers takes + /// to much time. + DartSecureRandom.insecure([int? seed]) : _random = Random(seed); + + /// Uses an explicitly given dart [Random] for all operations. + DartSecureRandom.withRandom(Random random) : _random = random; + + @override + String get algorithmName => _algorithmName; + + @override + int nextUint8() { + return _random.nextInt(256); + } + + /// The dart [Random] can not be seeded, so this is a no-op. + @override + void seed(CipherParameters params) {} +} diff --git a/lib/src/registry/registration.dart b/lib/src/registry/registration.dart index a89e756e..1e9ed8c1 100644 --- a/lib/src/registry/registration.dart +++ b/lib/src/registry/registration.dart @@ -91,6 +91,7 @@ import 'package:pointycastle/paddings/pkcs7.dart'; import 'package:pointycastle/random/auto_seed_block_ctr_random.dart'; import 'package:pointycastle/random/block_ctr_random.dart'; import 'package:pointycastle/random/fortuna_random.dart'; +import 'package:pointycastle/random/dart_secure_random.dart'; import 'package:pointycastle/signers/ecdsa_signer.dart'; import 'package:pointycastle/signers/rsa_signer.dart'; import 'package:pointycastle/src/registry/registry.dart'; @@ -239,6 +240,7 @@ void _registerRandoms(FactoryRegistry registry) { registry.register(AutoSeedBlockCtrRandom.factoryConfig); registry.register(BlockCtrRandom.factoryConfig); registry.register(FortunaRandom.factoryConfig); + registry.register(DartSecureRandom.factoryConfig); } void _registerSigners(FactoryRegistry registry) { diff --git a/test/all_tests_web.dart b/test/all_tests_web.dart index a5c8fec3..28053820 100644 --- a/test/all_tests_web.dart +++ b/test/all_tests_web.dart @@ -51,6 +51,7 @@ import 'random/auto_seed_block_ctr_random_test.dart' as auto_seed_block_ctr_random_test; import 'random/block_ctr_random_test.dart' as block_ctr_random_test; import 'random/fortuna_random_test.dart' as fortuna_random_test; +import 'random/dart_secure_random_test.dart' as dart_secure_random_test; import 'random/fixed_rng_test.dart' as fixed_rng_test; import 'signers/ecdsa_signer_test.dart' as ecdsa_signer_test; import 'signers/pss_signer_test.dart' as pss_signer_test; @@ -110,6 +111,7 @@ void main() { auto_seed_block_ctr_random_test.main(); block_ctr_random_test.main(); fortuna_random_test.main(); + dart_secure_random_test.main(); fixed_rng_test.main(); ecdsa_signer_test.main(); rsa_signer_test.main(); diff --git a/test/random/dart_secure_random_test.dart b/test/random/dart_secure_random_test.dart new file mode 100644 index 00000000..8c9cc5c9 --- /dev/null +++ b/test/random/dart_secure_random_test.dart @@ -0,0 +1,25 @@ +// See file LICENSE for more information. + +library test.random.dart_secure_random_test; + +import 'package:pointycastle/pointycastle.dart'; + +import 'package:test/test.dart'; + +void main() { + group('DartSecure:', () { + final rnd = SecureRandom('DartSecure'); + + test('${rnd.algorithmName}', () { + var randomBytes = rnd.nextBytes(256); + var allZero = true; + for (var i = 0; i < randomBytes.length; i++) { + if (randomBytes[i] != 0) { + allZero = false; + break; + } + } + expect(allZero, false); + }); + }); +}