diff --git a/config.lock.yaml b/config.lock.yaml index 880e828..cc14be3 100644 --- a/config.lock.yaml +++ b/config.lock.yaml @@ -3,17 +3,17 @@ dots_indicator: 508f5883ac79bdbc10254092de3f28f571d261cd ed25519_edwards: 7353ba759ea9f4646cbf481c2ef949625c8ce4cf flutter_sharing_intent: aa1672f547d6579585fa27df0b28ffa2a2544aaa hand_signature: 1beedb164d093643365b0832277c377353c7464f -hashlib: 983cdbd5ee2529b908876b57a7217c09c6bc148a +hashlib: bc9c2f8dd7bbc72f47ccab0ce1111d40259c49bc hashlib_codecs: 2a966c37c3b9b1f5541ae88e99ab34acf3fc968b introduction_screen: 4a90e557630b28834479ed9c64a9d2d0185d8e48 libsignal_protocol_dart: 618f0c0b49534245a640a31d204265440cbac9ee lottie: 4f1a5a52bdf1e1c1e12fa97c96174dcb05419e19 mutex: 84ca903a3ac863735e3228c75a212133621f680f -no_screenshot: 8e19a8d0e30bd1d5000425cabac7ef3e3da4d5ea +no_screenshot: 57b4a072e9193b4fa1257a6f1acb13ef307625e7 optional: 71c638891ce4f2aff35c7387727989f31f9d877d photo_view: a13ca2fc387a3fb1276126959e092c44d0029987 pointycastle: bbd8569f68a7fccbdf0b92d0b44a9219c126c8dd -qr: ff808bb3f354e6a7029ec953cbe0144a42021db6 +qr: 7b1e9665ca976f484e7975356cf26fc7a0ccf02e qr_flutter: d5e7206396105d643113618290bbcc755d05f492 restart_app: 12339f63bf8e9631e619c4f9f6b4e013fa324715 x25519: ecb1d357714537bba6e276ef45f093846d4beaee diff --git a/hashlib/lib/src/random/generator_js.dart b/hashlib/lib/src/random/generator_js.dart index 99f6fbb..acbf1a9 100644 --- a/hashlib/lib/src/random/generator_js.dart +++ b/hashlib/lib/src/random/generator_js.dart @@ -1,24 +1,38 @@ -// Copyright (c) 2024, Sudipto Chandra +// Copyright (c) 2025, Sudipto Chandra // All rights reserved. Check LICENSE file for details. -import 'dart:async'; import 'dart:math' show Random; +import 'generator_js_legacy.dart' + if (dart.library.js_interop) 'generator_js_interop.dart'; + const int _mask32 = 0xFFFFFFFF; -int _seedCounter = Zone.current.hashCode; +/// For Node.js environment + dart2js compiler +class NodeRandom extends CryptoRandom implements Random { + @override + int nextInt(final int max) { + if (max < 1 || max > _mask32 + 1) { + throw RangeError.range( + max, 1, _mask32 + 1, 'max', 'max must be <= (1 << 32)'); + } + return cryptoRandomInt(max); + } + + @override + double nextDouble() { + final int first26Bits = nextInt(1 << 26); + final int next27Bits = nextInt(1 << 27); + final int random53Bits = (first26Bits << 27) + next27Bits; // JS int limit + return random53Bits / (1 << 53); + } + + @override + bool nextBool() => nextInt(2) == 1; +} /// Returns a secure random generator in JS runtime -Random secureRandom() => Random($generateSeed()); +Random secureRandom() => NodeRandom(); -/// Generates a random seed in JS runtime -int $generateSeed() { - int code = DateTime.now().millisecondsSinceEpoch; - code -= _seedCounter++; - if (code.bitLength & 1 == 1) { - code *= ~code; - } - code ^= ~_seedCounter << 5; - _seedCounter += code & 7; - return code & _mask32; -} +/// Generates a random seed +int $generateSeed() => secureRandom().nextInt(_mask32); diff --git a/hashlib/lib/src/random/generator_js_interop.dart b/hashlib/lib/src/random/generator_js_interop.dart new file mode 100644 index 0000000..ef8cdcf --- /dev/null +++ b/hashlib/lib/src/random/generator_js_interop.dart @@ -0,0 +1,25 @@ +// Copyright (c) 2025, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +import 'dart:js_interop'; + +@JS() +@staticInterop +class Crypto {} + +extension on Crypto { + external int randomInt(final int max); +} + +@JS('require') +external Crypto require(final String id); + +/// For Node.js environment + dart2js compiler +abstract class CryptoRandom { + Crypto? _crypto; + + int cryptoRandomInt(final int max) { + _crypto ??= require('crypto'); + return _crypto!.randomInt(max); + } +} diff --git a/hashlib/lib/src/random/generator_js_legacy.dart b/hashlib/lib/src/random/generator_js_legacy.dart new file mode 100644 index 0000000..c2f73c2 --- /dev/null +++ b/hashlib/lib/src/random/generator_js_legacy.dart @@ -0,0 +1,29 @@ +// Copyright (c) 2025, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +// Dart v2.19 compatible version +// Works with dart2js in a Node.js runtime (where `require` exists). + +// ignore_for_file: deprecated_member_use + +import 'dart:js' as js; + +js.JsObject _require(String id) { + final r = js.context['require']; + if (r == null) { + throw StateError("`require` is not available."); + } + return (r as js.JsFunction).apply([id]) as js.JsObject; +} + +/// For Node.js environment + dart2js compiler +abstract class CryptoRandom { + js.JsObject? _crypto; + js.JsFunction? _randomInt; + + int cryptoRandomInt(final int max) { + _crypto ??= _require('crypto'); + _randomInt ??= _crypto!['randomInt'] as js.JsFunction; + return (_randomInt!.apply([max]) as num).toInt(); + } +} diff --git a/hashlib/lib/src/random/generator_vm.dart b/hashlib/lib/src/random/generator_vm.dart index 3c2bb5d..6e23e0c 100644 --- a/hashlib/lib/src/random/generator_vm.dart +++ b/hashlib/lib/src/random/generator_vm.dart @@ -11,6 +11,4 @@ Random secureRandom() => Random.secure(); /// Generates a random seed @pragma('vm:prefer-inline') -int $generateSeed() => - (DateTime.now().microsecondsSinceEpoch & _mask32) ^ - Random.secure().nextInt(_mask32); +int $generateSeed() => Random.secure().nextInt(_mask32); diff --git a/hashlib/lib/src/random/generators.dart b/hashlib/lib/src/random/generators.dart index 31462e1..e916b47 100644 --- a/hashlib/lib/src/random/generators.dart +++ b/hashlib/lib/src/random/generators.dart @@ -11,8 +11,12 @@ import 'package:hashlib/src/algorithms/sm3.dart'; import 'package:hashlib/src/algorithms/xxh64/xxh64.dart'; import 'package:hashlib/src/core/hash_base.dart'; -import 'generator_vm.dart' if (dart.library.js) 'generator_js.dart'; -export 'generator_vm.dart' if (dart.library.js) 'generator_js.dart'; +import 'generator_vm.dart' + if (dart.library.html) 'generator_vm.dart' + if (dart.library.js) 'generator_js.dart'; +export 'generator_vm.dart' + if (dart.library.html) 'generator_vm.dart' + if (dart.library.js) 'generator_js.dart'; const int _mask32 = 0xFFFFFFFF; @@ -34,13 +38,13 @@ enum RNG { case RNG.keccak: return _keccakGenerateor(seed); case RNG.sha256: - return _hashGenerateor(SHA256Hash(), seed); + return _hashGenerator(SHA256Hash(), seed); case RNG.md5: - return _hashGenerateor(MD4Hash(), seed); + return _hashGenerator(MD4Hash(), seed); case RNG.xxh64: - return _hashGenerateor(XXHash64Sink(111), seed); + return _hashGenerator(XXHash64Sink(111), seed); case RNG.sm3: - return _hashGenerateor(SM3Hash(), seed); + return _hashGenerator(SM3Hash(), seed); case RNG.system: return _systemGenerator(seed); case RNG.secure: @@ -115,7 +119,7 @@ NextIntFunction _keccakGenerateor([int? seed]) { } /// Returns a iterable of 32-bit integers generated from the [sink]. -NextIntFunction _hashGenerateor( +NextIntFunction _hashGenerator( HashDigestSink sink, [ int? seed, ]) { diff --git a/hashlib/pubspec.yaml b/hashlib/pubspec.yaml index 32b9742..8e897f2 100644 --- a/hashlib/pubspec.yaml +++ b/hashlib/pubspec.yaml @@ -1,7 +1,7 @@ name: hashlib description: Secure hash functions, checksum generators, and key derivation algorithms optimized for Dart. homepage: https://github.com/bitanon/hashlib -version: 2.2.0 +version: 2.3.0 environment: sdk: '>=2.19.0 <4.0.0' diff --git a/hashlib/test/bcrypt/bcrypt_2a_test.dart b/hashlib/test/bcrypt/bcrypt_2a_test.dart new file mode 100644 index 0000000..db47c67 --- /dev/null +++ b/hashlib/test/bcrypt/bcrypt_2a_test.dart @@ -0,0 +1,134 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +import 'dart:convert'; + +import 'package:hashlib/hashlib.dart'; +import 'package:test/test.dart'; + +void main() { + group('bcrypt version 2a', () { + // http://cvsweb.openwall.com/cgi/cvsweb.cgi/Owl/packages/glibc/crypt_blowfish/wrapper.c?rev=HEAD + test(r"$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s.", () { + const password = r""; + const encoded = + r"$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s."; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + // https://stackoverflow.com/a/12761326/774398 + test(r"$2a$10$.TtQJ4Jr6isd4Hp.mVfZeuh6Gws4rOQ/vdBczhDx.19NFK0Y84Dle", () { + const password = r"ππππππππ"; + const encoded = + r"$2a$10$.TtQJ4Jr6isd4Hp.mVfZeuh6Gws4rOQ/vdBczhDx.19NFK0Y84Dle"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + // https://bitbucket.org/vadim/bcrypt.net/src/464c41416dc9/BCrypt.Net.Test/TestBCrypt.cs?fileviewer=file-view-default + test(r"$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye", () { + const password = r""; + const encoded = + r"$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe", () { + const password = r"a"; + const encoded = + r"$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i", () { + const password = r"abc"; + const encoded = + r"$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC", () { + const password = r"abcdefghijklmnopqrstuvwxyz"; + const encoded = + r"$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO", () { + const password = r"~!@#$%^&*() ~!@#$%^&*()PNBFRD"; + const encoded = + r"$2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + // https://github.com/pyca/bcrypt/blob/main/tests/test_bcrypt.py + test(r"$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW", () { + var password = "U*U"; + var encoded = + r"$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK", () { + var password = "U*U*"; + var encoded = + r"$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a", () { + var password = "U*U*U"; + var encoded = + r"$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui", () { + var password = "0123456789abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + "chars after 72 are ignored"; + var encoded = + r"$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6", () { + var password = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "chars after 72 are ignored as usual"; + var encoded = + r"$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6"; + var output = bcrypt(password.codeUnits, encoded); + expect(output, equals(encoded)); + }); + + test(r"$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", () { + var password = "\xa3"; + var encoded = + r"$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq"; + var output = bcrypt(password.codeUnits, encoded); + expect(output, equals(encoded)); + }); + + test(r"$2a$04$tecY.9ylRInW/rAAzXCXPOOlyYeCNzmNTzPDNSIFztFMKbvs/s5XG", () { + var password = + "g7\r\x01\xf3\xd4\xd0\xa9JB^\x18\x007P\xb2N\xc7\x1c\xee\x87&\x83C" + "\x8b\xe8\x18\xc5>\x86\x14/\xd6\xcc\x1cJ\xde\xd7ix\xeb\xdeO\xef" + "\xe1i\xac\xcb\x03\x96v1' \xd6@.m\xa5!\xa0\xef\xc0("; + var encoded = + r"$2a$04$tecY.9ylRInW/rAAzXCXPOOlyYeCNzmNTzPDNSIFztFMKbvs/s5XG"; + var output = bcrypt(password.codeUnits, encoded); + expect(output, equals(encoded)); + }); + }); +} diff --git a/hashlib/test/bcrypt/bcrypt_2b_test.dart b/hashlib/test/bcrypt/bcrypt_2b_test.dart new file mode 100644 index 0000000..1f6d854 --- /dev/null +++ b/hashlib/test/bcrypt/bcrypt_2b_test.dart @@ -0,0 +1,186 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +import 'dart:convert'; + +import 'package:hashlib/hashlib.dart'; +import 'package:test/test.dart'; + +void main() { + // https://github.com/pyca/bcrypt/blob/main/tests/test_bcrypt.py + group('bcrypt version 2b', () { + test(r"$2b$04$cVWp4XaNU8a4v1uMRum2SO026BWLIoQMD/TXg5uZV.0P.uO8m3YEm", () { + var password = "Kk4DQuMMfZL9o"; + var encoded = + r"$2b$04$cVWp4XaNU8a4v1uMRum2SO026BWLIoQMD/TXg5uZV.0P.uO8m3YEm"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$pQ7gRO7e6wx/936oXhNjrOUNOHL1D0h1N2IDbJZYs.1ppzSof6SPy", () { + var password = "9IeRXmnGxMYbs"; + var encoded = + r"$2b$04$pQ7gRO7e6wx/936oXhNjrOUNOHL1D0h1N2IDbJZYs.1ppzSof6SPy"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$SQe9knOzepOVKoYXo9xTteNYr6MBwVz4tpriJVe3PNgYufGIsgKcW", () { + var password = "xVQVbwa1S0M8r"; + var encoded = + r"$2b$04$SQe9knOzepOVKoYXo9xTteNYr6MBwVz4tpriJVe3PNgYufGIsgKcW"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$eH8zX.q5Q.j2hO1NkVYJQOM6KxntS/ow3.YzVmFrE4t//CoF4fvne", () { + var password = "Zfgr26LWd22Za"; + var encoded = + r"$2b$04$eH8zX.q5Q.j2hO1NkVYJQOM6KxntS/ow3.YzVmFrE4t//CoF4fvne"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$ahiTdwRXpUG2JLRcIznxc.s1.ydaPGD372bsGs8NqyYjLY1inG5n2", () { + var password = "Tg4daC27epFBE"; + var encoded = + r"$2b$04$ahiTdwRXpUG2JLRcIznxc.s1.ydaPGD372bsGs8NqyYjLY1inG5n2"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$nQn78dV0hGHf5wUBe0zOFu8n07ZbWWOKoGasZKRspZxtt.vBRNMIy", () { + var password = "xhQPMmwh5ALzW"; + var encoded = + r"$2b$04$nQn78dV0hGHf5wUBe0zOFu8n07ZbWWOKoGasZKRspZxtt.vBRNMIy"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$cvXudZ5ugTg95W.rOjMITuM1jC0piCl3zF5cmGhzCibHZrNHkmckG", () { + var password = "59je8h5Gj71tg"; + var encoded = + r"$2b$04$cvXudZ5ugTg95W.rOjMITuM1jC0piCl3zF5cmGhzCibHZrNHkmckG"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$YYjtiq4Uh88yUsExO0RNTuEJ.tZlsONac16A8OcLHleWFjVawfGvO", () { + var password = "wT4fHJa2N9WSW"; + var encoded = + r"$2b$04$YYjtiq4Uh88yUsExO0RNTuEJ.tZlsONac16A8OcLHleWFjVawfGvO"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$WLTjgY/pZSyqX/fbMbJzf.qxCeTMQOzgL.CimRjMHtMxd/VGKojMu", () { + var password = "uSgFRnQdOgm4S"; + var encoded = + r"$2b$04$WLTjgY/pZSyqX/fbMbJzf.qxCeTMQOzgL.CimRjMHtMxd/VGKojMu"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$2moPs/x/wnCfeQ5pCheMcuSJQ/KYjOZG780UjA/SiR.KsYWNrC7SG", () { + var password = "tEPtJZXur16Vg"; + var encoded = + r"$2b$04$2moPs/x/wnCfeQ5pCheMcuSJQ/KYjOZG780UjA/SiR.KsYWNrC7SG"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$HrEYC/AQ2HS77G78cQDZQ.r44WGcruKw03KHlnp71yVQEwpsi3xl2", () { + var password = "vvho8C6nlVf9K"; + var encoded = + r"$2b$04$HrEYC/AQ2HS77G78cQDZQ.r44WGcruKw03KHlnp71yVQEwpsi3xl2"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$vVYgSTfB8KVbmhbZE/k3R.ux9A0lJUM4CZwCkHI9fifke2.rTF7MG", () { + var password = "5auCCY9by0Ruf"; + var encoded = + r"$2b$04$vVYgSTfB8KVbmhbZE/k3R.ux9A0lJUM4CZwCkHI9fifke2.rTF7MG"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$JfoNrR8.doieoI8..F.C1OQgwE3uTeuardy6lw0AjALUzOARoyf2m", () { + var password = "GtTkR6qn2QOZW"; + var encoded = + r"$2b$04$JfoNrR8.doieoI8..F.C1OQgwE3uTeuardy6lw0AjALUzOARoyf2m"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$HP3I0PUs7KBEzMBNFw7o3O7f/uxaZU7aaDot1quHMgB2yrwBXsgyy", () { + var password = "zKo8vdFSnjX0f"; + var encoded = + r"$2b$04$HP3I0PUs7KBEzMBNFw7o3O7f/uxaZU7aaDot1quHMgB2yrwBXsgyy"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$xnFVhJsTzsFBTeP3PpgbMeMREb6rdKV9faW54Sx.yg9plf4jY8qT6", () { + var password = "I9VfYlacJiwiK"; + var encoded = + r"$2b$04$xnFVhJsTzsFBTeP3PpgbMeMREb6rdKV9faW54Sx.yg9plf4jY8qT6"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$WQp9.igoLqVr6Qk70mz6xuRxE0RttVXXdukpR9N54x17ecad34ZF6", () { + var password = "VFPO7YXnHQbQO"; + var encoded = + r"$2b$04$WQp9.igoLqVr6Qk70mz6xuRxE0RttVXXdukpR9N54x17ecad34ZF6"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$xgZtlonpAHSU/njOCdKztOPuPFzCNVpB4LGicO4/OGgHv.uKHkwsS", () { + var password = "VDx5BdxfxstYk"; + var encoded = + r"$2b$04$xgZtlonpAHSU/njOCdKztOPuPFzCNVpB4LGicO4/OGgHv.uKHkwsS"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$2Siw3Nv3Q/gTOIPetAyPr.GNj3aO0lb1E5E9UumYGKjP9BYqlNWJe", () { + var password = "dEe6XfVGrrfSH"; + var encoded = + r"$2b$04$2Siw3Nv3Q/gTOIPetAyPr.GNj3aO0lb1E5E9UumYGKjP9BYqlNWJe"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$7/Qj7Kd8BcSahPO4khB8me4ssDJCW3r4OGYqPF87jxtrSyPj5cS5m", () { + var password = "cTT0EAFdwJiLn"; + var encoded = + r"$2b$04$7/Qj7Kd8BcSahPO4khB8me4ssDJCW3r4OGYqPF87jxtrSyPj5cS5m"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$04$VvlCUKbTMjaxaYJ.k5juoecpG/7IzcH1AkmqKi.lIZMVIOLClWAk.", () { + var password = "J8eHUDuxBB520"; + var encoded = + r"$2b$04$VvlCUKbTMjaxaYJ.k5juoecpG/7IzcH1AkmqKi.lIZMVIOLClWAk."; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + + test(r"$2b$10$keO.ZZs22YtygVF6BLfhGOI/JjshJYPp8DZsUtym6mJV2Eha2Hdd.", () { + var password = [ + 125, 62, 179, 254, 241, 139, 160, 230, 40, 162, 76, 122, 113, 195, // + 80, 127, 204, 200, 98, 123, 249, 20, 246, 246, 96, 129, 71, 53, 236, + 29, 135, 16, 191, 167, 225, 125, 73, 55, 32, 150, 223, 99, 242, 191, + 179, 86, 104, 223, 77, 136, 113, 247, 255, 27, 130, 126, 122, 19, 221, + 233, 132, 0, 221, 52 + ]; + var encoded = + r"$2b$10$keO.ZZs22YtygVF6BLfhGOI/JjshJYPp8DZsUtym6mJV2Eha2Hdd."; + var output = bcrypt(password, encoded); + expect(output, equals(encoded)); + }); + }); +} diff --git a/hashlib/test/bcrypt/bcrypt_2y_test.dart b/hashlib/test/bcrypt/bcrypt_2y_test.dart new file mode 100644 index 0000000..9f7564d --- /dev/null +++ b/hashlib/test/bcrypt/bcrypt_2y_test.dart @@ -0,0 +1,24 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +import 'package:hashlib/hashlib.dart'; +import 'package:test/test.dart'; + +void main() { + group('bcrypt version 2y', () { + test(r"$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", () { + var password = "\xa3"; + var encoded = + r"$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq"; + var output = bcrypt(password.codeUnits, encoded); + expect(output, equals(encoded)); + }); + test(r"$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", () { + var password = "\xff\xff\xa3"; + var encoded = + r"$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e"; + var output = bcrypt(password.codeUnits, encoded); + expect(output, equals(encoded)); + }); + }); +} diff --git a/hashlib/test/bcrypt/bcrypt_basic_test.dart b/hashlib/test/bcrypt/bcrypt_basic_test.dart new file mode 100644 index 0000000..5d0b8b0 --- /dev/null +++ b/hashlib/test/bcrypt/bcrypt_basic_test.dart @@ -0,0 +1,221 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +import 'dart:convert'; + +import 'package:hashlib/codecs.dart'; +import 'package:hashlib/hashlib.dart'; +import 'package:test/test.dart'; + +void main() { + group('bcrypt functionality', () { + test("name", () { + expect(Bcrypt(cost: 10).name, r'Bcrypt/2b'); + expect(Bcrypt(cost: 10, version: BcryptVersion.$2a).name, r'Bcrypt/2a'); + expect(Bcrypt(cost: 10, version: BcryptVersion.$2x).name, r'Bcrypt/2x'); + expect(Bcrypt(cost: 10, version: BcryptVersion.$2y).name, r'Bcrypt/2y'); + expect(Bcrypt(cost: 10, version: BcryptVersion.$2b).name, r'Bcrypt/2b'); + }); + + // http://openwall.info/wiki/john/sample-hashes + test("bcrypt", () { + const password = r"password"; + const salt = r"$2a$05$bvIG6Nmid91Mu9RcmmWZfO"; + const encoded = + r"$2a$05$bvIG6Nmid91Mu9RcmmWZfO5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe"; + var output = bcrypt(utf8.encode(password), salt); + expect(output, equals(encoded)); + }); + + test("bcryptVerify", () { + const password = r"password"; + const encoded = + r"$2a$05$bvIG6Nmid91Mu9RcmmWZfO5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe"; + expect(bcryptVerify(encoded, password.codeUnits), true); + }); + + test("bcryptSalt", () { + final salt = bcryptSalt(nb: 5, version: BcryptVersion.$2a); + expect(salt.length, 29); + expect(salt, startsWith(r"$2a$05$")); + }); + + test("bcryptSalt with security", () { + final salt = bcryptSalt(security: BcryptSecurity.strong); + expect(salt.length, 29); + expect(salt, startsWith(r"$2b$15$")); + }); + + test("bcryptSalt with security overrides", () { + final salt = bcryptSalt(security: BcryptSecurity.strong, nb: 10); + expect(salt.length, 29); + expect(salt, startsWith(r"$2b$10$")); + }); + + test("bcryptDigest", () { + var password = "password".codeUnits; + var salt = fromBase64( + "bvIG6Nmid91Mu9RcmmWZfO", + codec: Base64Codec.bcrypt, + ); + var result = fromBase64( + '5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe', + codec: Base64Codec.bcrypt, + ); + const encoded = + r"$2a$05$bvIG6Nmid91Mu9RcmmWZfO5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe"; + final output = bcryptDigest( + password, + nb: 5, + salt: salt, + version: BcryptVersion.$2a, + ); + expect(output.bytes, equals(result)); + expect(output.encoded(), equals(encoded)); + expect(output.toString(), equals(encoded)); + }); + test("bcryptDigest with security", () { + var password = "password".codeUnits; + var salt = fromBase64( + "bvIG6Nmid91Mu9RcmmWZfO", + codec: Base64Codec.bcrypt, + ); + var result = fromBase64( + '5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe', + codec: Base64Codec.bcrypt, + ); + final output = bcryptDigest( + password, + salt: salt, + version: BcryptVersion.$2a, + security: BcryptSecurity.little, + ); + expect(output.bytes, equals(result)); + }); + test("Bcrypt instance with security", () { + var password = "password".codeUnits; + var salt = fromBase64( + "bvIG6Nmid91Mu9RcmmWZfO", + codec: Base64Codec.bcrypt, + ); + var result = fromBase64( + '5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe', + codec: Base64Codec.bcrypt, + ); + final output = Bcrypt.fromSecurity( + BcryptSecurity.little, + salt: salt, + version: BcryptVersion.$2a, + ).convert(password); + expect(output.bytes, equals(result)); + }); + test("The cost must be at least 0", () { + BcryptContext(cost: 0); + expect(() => BcryptContext(cost: -10), throwsArgumentError); + expect(() => BcryptContext(cost: -1), throwsArgumentError); + }); + test("The cost must be at most 31", () { + BcryptContext(cost: 31); + expect(() => BcryptContext(cost: 32), throwsArgumentError); + expect(() => BcryptContext(cost: 100), throwsArgumentError); + }); + test("The salt must be exactly 16-bytes", () { + BcryptContext(cost: 4, salt: List.filled(16, 0)); + expect( + () => BcryptContext(cost: 4, salt: []), + throwsArgumentError, + ); + expect( + () => BcryptContext(cost: 4, salt: List.filled(15, 0)), + throwsArgumentError, + ); + expect( + () => BcryptContext(cost: 4, salt: List.filled(17, 0)), + throwsArgumentError, + ); + }); + test("Bcrypt from encoded", () { + Bcrypt.fromEncoded(fromCrypt(r"$2a$05$bvIG6Nmid91Mu9RcmmWZfO")); + }); + test("Bcrypt from encoded with invalid version", () { + expect( + () => Bcrypt.fromEncoded(fromCrypt(r"$2c$05$bvIG6Nmid91Mu9RcmmWZfO")), + throwsA( + isA().having( + (e) => e.message, + 'message', + 'Invalid version', + ), + ), + ); + }); + test("Bcrypt from encoded with invalid cost", () { + expect( + () => Bcrypt.fromEncoded(fromCrypt(r"$2x$bvIG6Nmid91Mu9RcmmWZfO")), + throwsA( + isA().having( + (e) => e.message, + 'message', + 'Invalid cost', + ), + ), + ); + expect( + () => Bcrypt.fromEncoded(fromCrypt(r"$2y$32$bvIG6Nmid91Mu9RcmmWZfO")), + throwsA( + isA().having( + (e) => e.message, + 'message', + 'The cost must be at most 31', + ), + ), + ); + expect( + () => Bcrypt.fromEncoded(fromCrypt(r"$2y$-1$bvIG6Nmid91Mu9RcmmWZfO")), + throwsA( + isA().having( + (e) => e.message, + 'message', + 'The cost must be at least 0', + ), + ), + ); + }); + test("Bcrypt from encoded with invalid salt", () { + expect( + () => Bcrypt.fromEncoded(fromCrypt(r"$2b$05$bvIG6Nmid91Mu9RcmmWZf")), + throwsA( + isA().having( + (e) => e.message, + 'message', + 'Invalid hash', + ), + ), + ); + expect( + () => Bcrypt.fromEncoded(fromCrypt(r"$2b$05$bvIG6Nmid91Mu9RcmmWZf0")), + throwsA( + isA().having( + (e) => e.message, + 'message', + 'Invalid length', + ), + ), + ); + expect( + () => Bcrypt.fromEncoded(fromCrypt( + r"$2b$05$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1")), + throwsA( + isA().having( + (e) => e.message, + 'message', + 'Invalid hash', + ), + ), + ); + Bcrypt.fromEncoded(fromCrypt( + r"$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s1", + )); + }); + }); +} diff --git a/hashlib/test/bcrypt/bcrypt_cost_test.dart b/hashlib/test/bcrypt/bcrypt_cost_test.dart new file mode 100644 index 0000000..f9cee55 --- /dev/null +++ b/hashlib/test/bcrypt/bcrypt_cost_test.dart @@ -0,0 +1,110 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +import 'dart:convert'; + +import 'package:hashlib/hashlib.dart'; +import 'package:test/test.dart'; + +void main() { + group('bcrypt big cost', () { + test(r"$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW", () { + const password = r""; + const encoded = + r"$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO", () { + const password = r""; + const encoded = + r"$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V.", () { + const password = r"a"; + const encoded = + r"$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V."; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u", () { + const password = r"a"; + const encoded = + r"$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS", () { + const password = r"a"; + const encoded = + r"$2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm", () { + const password = r"abc"; + const encoded = + r"$2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi", () { + const password = r"abc"; + const encoded = + r"$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q", () { + const password = r"abc"; + const encoded = + r"$2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz.", () { + const password = r"abcdefghijklmnopqrstuvwxyz"; + const encoded = + r"$2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz."; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq", () { + const password = r"abcdefghijklmnopqrstuvwxyz"; + const encoded = + r"$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG", () { + const password = r"abcdefghijklmnopqrstuvwxyz"; + const encoded = + r"$2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW", () { + const password = r"~!@#$%^&*() ~!@#$%^&*()PNBFRD"; + const encoded = + r"$2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS", () { + const password = r"~!@#$%^&*() ~!@#$%^&*()PNBFRD"; + const encoded = + r"$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + test(r"$2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC", () { + const password = r"~!@#$%^&*() ~!@#$%^&*()PNBFRD"; + const encoded = + r"$2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC"; + var output = bcrypt(utf8.encode(password), encoded); + expect(output, equals(encoded)); + }); + }, skip: true); +} diff --git a/hashlib/test/bcrypt_test.dart b/hashlib/test/bcrypt_test.dart deleted file mode 100644 index ef8437b..0000000 --- a/hashlib/test/bcrypt_test.dart +++ /dev/null @@ -1,643 +0,0 @@ -// Copyright (c) 2023, Sudipto Chandra -// All rights reserved. Check LICENSE file for details. - -import 'dart:convert'; - -import 'package:hashlib/codecs.dart'; -import 'package:hashlib/hashlib.dart'; -import 'package:test/test.dart'; - -void main() { - group('bcrypt test', () { - group('functionality test', () { - test("name", () { - expect(Bcrypt(cost: 10).name, r'Bcrypt/2b'); - expect(Bcrypt(cost: 10, version: BcryptVersion.$2a).name, r'Bcrypt/2a'); - expect(Bcrypt(cost: 10, version: BcryptVersion.$2x).name, r'Bcrypt/2x'); - expect(Bcrypt(cost: 10, version: BcryptVersion.$2y).name, r'Bcrypt/2y'); - expect(Bcrypt(cost: 10, version: BcryptVersion.$2b).name, r'Bcrypt/2b'); - }); - - // http://openwall.info/wiki/john/sample-hashes - test("bcrypt", () { - const password = r"password"; - const salt = r"$2a$05$bvIG6Nmid91Mu9RcmmWZfO"; - const encoded = - r"$2a$05$bvIG6Nmid91Mu9RcmmWZfO5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe"; - var output = bcrypt(utf8.encode(password), salt); - expect(output, equals(encoded)); - }); - - test("bcryptVerify", () { - const password = r"password"; - const encoded = - r"$2a$05$bvIG6Nmid91Mu9RcmmWZfO5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe"; - expect(bcryptVerify(encoded, password.codeUnits), true); - }); - - test("bcryptSalt", () { - final salt = bcryptSalt(nb: 5, version: BcryptVersion.$2a); - expect(salt.length, 29); - expect(salt, startsWith(r"$2a$05$")); - }); - - test("bcryptSalt with security", () { - final salt = bcryptSalt(security: BcryptSecurity.strong); - expect(salt.length, 29); - expect(salt, startsWith(r"$2b$15$")); - }); - - test("bcryptSalt with security overrides", () { - final salt = bcryptSalt(security: BcryptSecurity.strong, nb: 10); - expect(salt.length, 29); - expect(salt, startsWith(r"$2b$10$")); - }); - - test("bcryptDigest", () { - var password = "password".codeUnits; - var salt = fromBase64( - "bvIG6Nmid91Mu9RcmmWZfO", - codec: Base64Codec.bcrypt, - ); - var result = fromBase64( - '5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe', - codec: Base64Codec.bcrypt, - ); - const encoded = - r"$2a$05$bvIG6Nmid91Mu9RcmmWZfO5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe"; - final output = bcryptDigest( - password, - nb: 5, - salt: salt, - version: BcryptVersion.$2a, - ); - expect(output.bytes, equals(result)); - expect(output.encoded(), equals(encoded)); - expect(output.toString(), equals(encoded)); - }); - test("bcryptDigest with security", () { - var password = "password".codeUnits; - var salt = fromBase64( - "bvIG6Nmid91Mu9RcmmWZfO", - codec: Base64Codec.bcrypt, - ); - var result = fromBase64( - '5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe', - codec: Base64Codec.bcrypt, - ); - final output = bcryptDigest( - password, - salt: salt, - version: BcryptVersion.$2a, - security: BcryptSecurity.little, - ); - expect(output.bytes, equals(result)); - }); - test("Bcrypt instance with security", () { - var password = "password".codeUnits; - var salt = fromBase64( - "bvIG6Nmid91Mu9RcmmWZfO", - codec: Base64Codec.bcrypt, - ); - var result = fromBase64( - '5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe', - codec: Base64Codec.bcrypt, - ); - final output = Bcrypt.fromSecurity( - BcryptSecurity.little, - salt: salt, - version: BcryptVersion.$2a, - ).convert(password); - expect(output.bytes, equals(result)); - }); - test("The cost must be at least 0", () { - BcryptContext(cost: 0); - expect(() => BcryptContext(cost: -10), throwsArgumentError); - expect(() => BcryptContext(cost: -1), throwsArgumentError); - }); - test("The cost must be at most 31", () { - BcryptContext(cost: 31); - expect(() => BcryptContext(cost: 32), throwsArgumentError); - expect(() => BcryptContext(cost: 100), throwsArgumentError); - }); - test("The salt must be exactly 16-bytes", () { - BcryptContext(cost: 4, salt: List.filled(16, 0)); - expect( - () => BcryptContext(cost: 4, salt: []), - throwsArgumentError, - ); - expect( - () => BcryptContext(cost: 4, salt: List.filled(15, 0)), - throwsArgumentError, - ); - expect( - () => BcryptContext(cost: 4, salt: List.filled(17, 0)), - throwsArgumentError, - ); - }); - test("Bcrypt from encoded", () { - Bcrypt.fromEncoded(fromCrypt(r"$2a$05$bvIG6Nmid91Mu9RcmmWZfO")); - }); - test("Bcrypt from encoded with invalid version", () { - expect( - () => Bcrypt.fromEncoded(fromCrypt(r"$2c$05$bvIG6Nmid91Mu9RcmmWZfO")), - throwsA( - isA().having( - (e) => e.message, - 'message', - 'Invalid version', - ), - ), - ); - }); - test("Bcrypt from encoded with invalid cost", () { - expect( - () => Bcrypt.fromEncoded(fromCrypt(r"$2x$bvIG6Nmid91Mu9RcmmWZfO")), - throwsA( - isA().having( - (e) => e.message, - 'message', - 'Invalid cost', - ), - ), - ); - expect( - () => Bcrypt.fromEncoded(fromCrypt(r"$2y$32$bvIG6Nmid91Mu9RcmmWZfO")), - throwsA( - isA().having( - (e) => e.message, - 'message', - 'The cost must be at most 31', - ), - ), - ); - expect( - () => Bcrypt.fromEncoded(fromCrypt(r"$2y$-1$bvIG6Nmid91Mu9RcmmWZfO")), - throwsA( - isA().having( - (e) => e.message, - 'message', - 'The cost must be at least 0', - ), - ), - ); - }); - test("Bcrypt from encoded with invalid salt", () { - expect( - () => Bcrypt.fromEncoded(fromCrypt(r"$2b$05$bvIG6Nmid91Mu9RcmmWZf")), - throwsA( - isA().having( - (e) => e.message, - 'message', - 'Invalid hash', - ), - ), - ); - expect( - () => Bcrypt.fromEncoded(fromCrypt(r"$2b$05$bvIG6Nmid91Mu9RcmmWZf0")), - throwsA( - isA().having( - (e) => e.message, - 'message', - 'Invalid length', - ), - ), - ); - expect( - () => Bcrypt.fromEncoded(fromCrypt( - r"$2b$05$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1")), - throwsA( - isA().having( - (e) => e.message, - 'message', - 'Invalid hash', - ), - ), - ); - Bcrypt.fromEncoded(fromCrypt( - r"$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s1", - )); - }); - }); - - group('version 2a', () { - // http://cvsweb.openwall.com/cgi/cvsweb.cgi/Owl/packages/glibc/crypt_blowfish/wrapper.c?rev=HEAD - test(r"$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s.", () { - const password = r""; - const encoded = - r"$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s."; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - // https://stackoverflow.com/a/12761326/774398 - test(r"$2a$10$.TtQJ4Jr6isd4Hp.mVfZeuh6Gws4rOQ/vdBczhDx.19NFK0Y84Dle", () { - const password = r"ππππππππ"; - const encoded = - r"$2a$10$.TtQJ4Jr6isd4Hp.mVfZeuh6Gws4rOQ/vdBczhDx.19NFK0Y84Dle"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - // https://bitbucket.org/vadim/bcrypt.net/src/464c41416dc9/BCrypt.Net.Test/TestBCrypt.cs?fileviewer=file-view-default - test(r"$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye", () { - const password = r""; - const encoded = - r"$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe", () { - const password = r"a"; - const encoded = - r"$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i", () { - const password = r"abc"; - const encoded = - r"$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC", () { - const password = r"abcdefghijklmnopqrstuvwxyz"; - const encoded = - r"$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO", () { - const password = r"~!@#$%^&*() ~!@#$%^&*()PNBFRD"; - const encoded = - r"$2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - // https://github.com/pyca/bcrypt/blob/main/tests/test_bcrypt.py - test(r"$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW", () { - var password = "U*U"; - var encoded = - r"$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK", () { - var password = "U*U*"; - var encoded = - r"$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a", () { - var password = "U*U*U"; - var encoded = - r"$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui", () { - var password = "0123456789abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - "chars after 72 are ignored"; - var encoded = - r"$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6", () { - var password = "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "chars after 72 are ignored as usual"; - var encoded = - r"$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6"; - var output = bcrypt(password.codeUnits, encoded); - expect(output, equals(encoded)); - }); - - test(r"$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", () { - var password = "\xa3"; - var encoded = - r"$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq"; - var output = bcrypt(password.codeUnits, encoded); - expect(output, equals(encoded)); - }); - - test(r"$2a$04$tecY.9ylRInW/rAAzXCXPOOlyYeCNzmNTzPDNSIFztFMKbvs/s5XG", () { - var password = - "g7\r\x01\xf3\xd4\xd0\xa9JB^\x18\x007P\xb2N\xc7\x1c\xee\x87&\x83C" - "\x8b\xe8\x18\xc5>\x86\x14/\xd6\xcc\x1cJ\xde\xd7ix\xeb\xdeO\xef" - "\xe1i\xac\xcb\x03\x96v1' \xd6@.m\xa5!\xa0\xef\xc0("; - var encoded = - r"$2a$04$tecY.9ylRInW/rAAzXCXPOOlyYeCNzmNTzPDNSIFztFMKbvs/s5XG"; - var output = bcrypt(password.codeUnits, encoded); - expect(output, equals(encoded)); - }); - }); - - group('version 2y', () { - test(r"$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", () { - var password = "\xa3"; - var encoded = - r"$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq"; - var output = bcrypt(password.codeUnits, encoded); - expect(output, equals(encoded)); - }); - test(r"$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", () { - var password = "\xff\xff\xa3"; - var encoded = - r"$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e"; - var output = bcrypt(password.codeUnits, encoded); - expect(output, equals(encoded)); - }); - }); - - // https://github.com/pyca/bcrypt/blob/main/tests/test_bcrypt.py - group('version 2b', () { - test(r"$2b$04$cVWp4XaNU8a4v1uMRum2SO026BWLIoQMD/TXg5uZV.0P.uO8m3YEm", () { - var password = "Kk4DQuMMfZL9o"; - var encoded = - r"$2b$04$cVWp4XaNU8a4v1uMRum2SO026BWLIoQMD/TXg5uZV.0P.uO8m3YEm"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$pQ7gRO7e6wx/936oXhNjrOUNOHL1D0h1N2IDbJZYs.1ppzSof6SPy", () { - var password = "9IeRXmnGxMYbs"; - var encoded = - r"$2b$04$pQ7gRO7e6wx/936oXhNjrOUNOHL1D0h1N2IDbJZYs.1ppzSof6SPy"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$SQe9knOzepOVKoYXo9xTteNYr6MBwVz4tpriJVe3PNgYufGIsgKcW", () { - var password = "xVQVbwa1S0M8r"; - var encoded = - r"$2b$04$SQe9knOzepOVKoYXo9xTteNYr6MBwVz4tpriJVe3PNgYufGIsgKcW"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$eH8zX.q5Q.j2hO1NkVYJQOM6KxntS/ow3.YzVmFrE4t//CoF4fvne", () { - var password = "Zfgr26LWd22Za"; - var encoded = - r"$2b$04$eH8zX.q5Q.j2hO1NkVYJQOM6KxntS/ow3.YzVmFrE4t//CoF4fvne"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$ahiTdwRXpUG2JLRcIznxc.s1.ydaPGD372bsGs8NqyYjLY1inG5n2", () { - var password = "Tg4daC27epFBE"; - var encoded = - r"$2b$04$ahiTdwRXpUG2JLRcIznxc.s1.ydaPGD372bsGs8NqyYjLY1inG5n2"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$nQn78dV0hGHf5wUBe0zOFu8n07ZbWWOKoGasZKRspZxtt.vBRNMIy", () { - var password = "xhQPMmwh5ALzW"; - var encoded = - r"$2b$04$nQn78dV0hGHf5wUBe0zOFu8n07ZbWWOKoGasZKRspZxtt.vBRNMIy"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$cvXudZ5ugTg95W.rOjMITuM1jC0piCl3zF5cmGhzCibHZrNHkmckG", () { - var password = "59je8h5Gj71tg"; - var encoded = - r"$2b$04$cvXudZ5ugTg95W.rOjMITuM1jC0piCl3zF5cmGhzCibHZrNHkmckG"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$YYjtiq4Uh88yUsExO0RNTuEJ.tZlsONac16A8OcLHleWFjVawfGvO", () { - var password = "wT4fHJa2N9WSW"; - var encoded = - r"$2b$04$YYjtiq4Uh88yUsExO0RNTuEJ.tZlsONac16A8OcLHleWFjVawfGvO"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$WLTjgY/pZSyqX/fbMbJzf.qxCeTMQOzgL.CimRjMHtMxd/VGKojMu", () { - var password = "uSgFRnQdOgm4S"; - var encoded = - r"$2b$04$WLTjgY/pZSyqX/fbMbJzf.qxCeTMQOzgL.CimRjMHtMxd/VGKojMu"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$2moPs/x/wnCfeQ5pCheMcuSJQ/KYjOZG780UjA/SiR.KsYWNrC7SG", () { - var password = "tEPtJZXur16Vg"; - var encoded = - r"$2b$04$2moPs/x/wnCfeQ5pCheMcuSJQ/KYjOZG780UjA/SiR.KsYWNrC7SG"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$HrEYC/AQ2HS77G78cQDZQ.r44WGcruKw03KHlnp71yVQEwpsi3xl2", () { - var password = "vvho8C6nlVf9K"; - var encoded = - r"$2b$04$HrEYC/AQ2HS77G78cQDZQ.r44WGcruKw03KHlnp71yVQEwpsi3xl2"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$vVYgSTfB8KVbmhbZE/k3R.ux9A0lJUM4CZwCkHI9fifke2.rTF7MG", () { - var password = "5auCCY9by0Ruf"; - var encoded = - r"$2b$04$vVYgSTfB8KVbmhbZE/k3R.ux9A0lJUM4CZwCkHI9fifke2.rTF7MG"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$JfoNrR8.doieoI8..F.C1OQgwE3uTeuardy6lw0AjALUzOARoyf2m", () { - var password = "GtTkR6qn2QOZW"; - var encoded = - r"$2b$04$JfoNrR8.doieoI8..F.C1OQgwE3uTeuardy6lw0AjALUzOARoyf2m"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$HP3I0PUs7KBEzMBNFw7o3O7f/uxaZU7aaDot1quHMgB2yrwBXsgyy", () { - var password = "zKo8vdFSnjX0f"; - var encoded = - r"$2b$04$HP3I0PUs7KBEzMBNFw7o3O7f/uxaZU7aaDot1quHMgB2yrwBXsgyy"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$xnFVhJsTzsFBTeP3PpgbMeMREb6rdKV9faW54Sx.yg9plf4jY8qT6", () { - var password = "I9VfYlacJiwiK"; - var encoded = - r"$2b$04$xnFVhJsTzsFBTeP3PpgbMeMREb6rdKV9faW54Sx.yg9plf4jY8qT6"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$WQp9.igoLqVr6Qk70mz6xuRxE0RttVXXdukpR9N54x17ecad34ZF6", () { - var password = "VFPO7YXnHQbQO"; - var encoded = - r"$2b$04$WQp9.igoLqVr6Qk70mz6xuRxE0RttVXXdukpR9N54x17ecad34ZF6"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$xgZtlonpAHSU/njOCdKztOPuPFzCNVpB4LGicO4/OGgHv.uKHkwsS", () { - var password = "VDx5BdxfxstYk"; - var encoded = - r"$2b$04$xgZtlonpAHSU/njOCdKztOPuPFzCNVpB4LGicO4/OGgHv.uKHkwsS"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$2Siw3Nv3Q/gTOIPetAyPr.GNj3aO0lb1E5E9UumYGKjP9BYqlNWJe", () { - var password = "dEe6XfVGrrfSH"; - var encoded = - r"$2b$04$2Siw3Nv3Q/gTOIPetAyPr.GNj3aO0lb1E5E9UumYGKjP9BYqlNWJe"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$7/Qj7Kd8BcSahPO4khB8me4ssDJCW3r4OGYqPF87jxtrSyPj5cS5m", () { - var password = "cTT0EAFdwJiLn"; - var encoded = - r"$2b$04$7/Qj7Kd8BcSahPO4khB8me4ssDJCW3r4OGYqPF87jxtrSyPj5cS5m"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$04$VvlCUKbTMjaxaYJ.k5juoecpG/7IzcH1AkmqKi.lIZMVIOLClWAk.", () { - var password = "J8eHUDuxBB520"; - var encoded = - r"$2b$04$VvlCUKbTMjaxaYJ.k5juoecpG/7IzcH1AkmqKi.lIZMVIOLClWAk."; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - - test(r"$2b$10$keO.ZZs22YtygVF6BLfhGOI/JjshJYPp8DZsUtym6mJV2Eha2Hdd.", () { - var password = [ - 125, 62, 179, 254, 241, 139, 160, 230, 40, 162, 76, 122, 113, 195, // - 80, 127, 204, 200, 98, 123, 249, 20, 246, 246, 96, 129, 71, 53, 236, - 29, 135, 16, 191, 167, 225, 125, 73, 55, 32, 150, 223, 99, 242, 191, - 179, 86, 104, 223, 77, 136, 113, 247, 255, 27, 130, 126, 122, 19, 221, - 233, 132, 0, 221, 52 - ]; - var encoded = - r"$2b$10$keO.ZZs22YtygVF6BLfhGOI/JjshJYPp8DZsUtym6mJV2Eha2Hdd."; - var output = bcrypt(password, encoded); - expect(output, equals(encoded)); - }); - }); - - group('big cost', () { - test(r"$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW", () { - const password = r""; - const encoded = - r"$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO", () { - const password = r""; - const encoded = - r"$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V.", () { - const password = r"a"; - const encoded = - r"$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V."; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u", () { - const password = r"a"; - const encoded = - r"$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS", () { - const password = r"a"; - const encoded = - r"$2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm", () { - const password = r"abc"; - const encoded = - r"$2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi", () { - const password = r"abc"; - const encoded = - r"$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q", () { - const password = r"abc"; - const encoded = - r"$2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz.", () { - const password = r"abcdefghijklmnopqrstuvwxyz"; - const encoded = - r"$2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz."; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq", () { - const password = r"abcdefghijklmnopqrstuvwxyz"; - const encoded = - r"$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG", () { - const password = r"abcdefghijklmnopqrstuvwxyz"; - const encoded = - r"$2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW", () { - const password = r"~!@#$%^&*() ~!@#$%^&*()PNBFRD"; - const encoded = - r"$2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS", () { - const password = r"~!@#$%^&*() ~!@#$%^&*()PNBFRD"; - const encoded = - r"$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - test(r"$2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC", () { - const password = r"~!@#$%^&*() ~!@#$%^&*()PNBFRD"; - const encoded = - r"$2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC"; - var output = bcrypt(utf8.encode(password), encoded); - expect(output, equals(encoded)); - }); - }, skip: true); - }); -} diff --git a/hashlib/test/compare/compare_blake2b512_test.dart b/hashlib/test/compare/compare_blake2b512_test.dart new file mode 100644 index 0000000..39f2af8 --- /dev/null +++ b/hashlib/test/compare/compare_blake2b512_test.dart @@ -0,0 +1,109 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +// ignore_for_file: library_annotations + +@Tags(['vm-only']) + +import 'package:hashlib/codecs.dart'; +import 'package:hashlib/hashlib.dart'; +import 'package:hashlib/random.dart'; +import 'package:pointycastle/digests/blake2b.dart' as pc_blake2b; +import 'package:test/test.dart'; + +void main() { + group('blake2b512 comparison', () { + test('with pointycastle', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + final out1 = blake2b512.convert(data).hex(); + final out2 = toHex( + pc_blake2b.Blake2bDigest(digestSize: 64).process(data), + ); + expect(out1, equals(out2), reason: 'size: $i'); + } + }); + + test('with pointycastle with key', () { + final key = randomBytes(16); + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + final out1 = blake2b512.mac.by(key).convert(data).hex(); + final out2 = toHex( + pc_blake2b.Blake2bDigest(digestSize: 64, key: key).process(data), + ); + expect(out1, equals(out2), reason: 'size: $i'); + } + }); + + test('with pointycastle with salt', () { + final salt = randomBytes(16); + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + final out1 = Blake2b(64, salt: salt).convert(data).hex(); + final out2 = toHex( + pc_blake2b.Blake2bDigest(digestSize: 64, salt: salt).process(data), + ); + expect(out1, equals(out2), reason: 'size: $i'); + } + }); + + test('with pointycastle with personalization', () { + final personalization = randomBytes(16); + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + final out1 = Blake2b( + 64, + aad: personalization, + ).convert(data).hex(); + final out2 = toHex( + pc_blake2b.Blake2bDigest( + digestSize: 64, + personalization: personalization, + ).process(data), + ); + expect(out1, equals(out2), reason: 'size: $i'); + } + }); + + test('with pointycastle with salt and personalization', () { + final salt = randomBytes(16); + final personalization = randomBytes(16); + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + final out1 = Blake2b( + 64, + salt: salt, + aad: personalization, + ).convert(data).hex(); + final out2 = toHex( + pc_blake2b.Blake2bDigest( + digestSize: 64, + salt: salt, + personalization: personalization, + ).process(data), + ); + expect(out1, equals(out2), reason: 'size: $i'); + } + }); + + test('with pointycastle with key, salt and personalization', () { + final key = randomBytes(16); + final salt = randomBytes(16); + final aad = randomBytes(16); + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + final out1 = Blake2b(64).mac.by(key, salt: salt, aad: aad).hex(data); + final out2 = toHex( + pc_blake2b.Blake2bDigest( + digestSize: 64, + key: key, + salt: salt, + personalization: aad, + ).process(data), + ); + expect(out1, equals(out2), reason: 'size: $i'); + } + }); + }); +} diff --git a/hashlib/test/compare/compare_hmac_test.dart b/hashlib/test/compare/compare_hmac_test.dart new file mode 100644 index 0000000..0467dd0 --- /dev/null +++ b/hashlib/test/compare/compare_hmac_test.dart @@ -0,0 +1,55 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +// ignore_for_file: library_annotations + +@Tags(['vm-only']) + +import 'package:crypto/crypto.dart' as crypto; +import 'package:hashlib/codecs.dart'; +import 'package:hashlib/hashlib.dart'; +import 'package:hashlib/random.dart'; +import 'package:test/test.dart'; + +void main() { + group('HMAC comparison', () { + test('with crypto for MD5', () { + var key = "key"; + var msg = "The quick brown fox jumps over the lazy dog"; + var expected = "80070713463e7749b90c2dc24911e275"; + var actual = toHex( + md5.hmac.byString(key).convert(msg.codeUnits).bytes, + ); + var actual2 = toHex( + crypto.Hmac(crypto.md5, key.codeUnits).convert(msg.codeUnits).bytes, + ); + expect(actual2, expected, reason: "Key: $key | Message: $msg"); + expect(actual, expected, reason: "Key: $key | Message: $msg"); + }); + + test('with crypto', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + final key = randomBytes(i & 0x7F); + expect( + toHex(sha1.hmac.by(key).convert(data).bytes), + toHex(crypto.Hmac(crypto.sha1, key).convert(data).bytes), + reason: 'Key: "${String.fromCharCodes(key)}" [${key.length}]\n' + 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + } + }); + + test('run in parallel', () async { + await Future.wait(List.generate(10, (i) => i).map((i) async { + final data = randomBytes(i); + final key = randomBytes(i & 0x7F); + expect( + toHex(sha384.hmac.by(key).convert(data).bytes), + toHex(crypto.Hmac(crypto.sha384, key).convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + })); + }); + }); +} diff --git a/hashlib/test/compare/compare_keccak_test.dart b/hashlib/test/compare/compare_keccak_test.dart new file mode 100644 index 0000000..51f3090 --- /dev/null +++ b/hashlib/test/compare/compare_keccak_test.dart @@ -0,0 +1,45 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +// ignore_for_file: library_annotations + +@Tags(['vm-only']) + +import 'dart:typed_data'; + +import 'package:hashlib/codecs.dart'; +import 'package:hashlib/hashlib.dart'; +import 'package:hashlib/random.dart'; +import 'package:pointycastle/digests/keccak.dart' as pc_keccak; +import 'package:pointycastle/digests/sha3.dart' as pc_sha3; +import 'package:test/test.dart'; + +void main() { + group('Keccak comparison', () { + test('with keccak256', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + var pc = pc_keccak.KeccakDigest(256); + var other = pc.process(Uint8List.fromList(data)); + expect( + keccak256.convert(data).hex(), + toHex(other), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + } + }); + + test('with sha3', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + var pc = pc_sha3.SHA3Digest(256); + var other = pc.process(Uint8List.fromList(data)); + expect( + sha3_256.convert(data).hex(), + toHex(other), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + } + }); + }); +} diff --git a/hashlib/test/compare/compare_md4_test.dart b/hashlib/test/compare/compare_md4_test.dart new file mode 100644 index 0000000..1db093d --- /dev/null +++ b/hashlib/test/compare/compare_md4_test.dart @@ -0,0 +1,36 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +// ignore_for_file: library_annotations + +@Tags(['vm-only']) + +import 'dart:io'; + +import 'package:hashlib/codecs.dart'; +import 'package:hashlib/hashlib.dart'; +import 'package:hashlib/random.dart'; +import 'package:pointycastle/digests/md4.dart' as pc_md4; +import 'package:test/test.dart'; + +void main() { + group('MD4 comparison', () { + test('with pointy-castle', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + expect( + toHex(md4.convert(data).bytes), + toHex(pc_md4.MD4Digest().process(data)), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + } + }); + + test('for a file sync', () { + var file = File('LICENSE'); + var hash = pc_md4.MD4Digest().process(file.readAsBytesSync()); + var hash2 = md4.fileSync(file); + expect(hash2.hex(), toHex(hash)); + }, tags: 'vm-only'); + }); +} diff --git a/hashlib/test/compare/compare_md5_test.dart b/hashlib/test/compare/compare_md5_test.dart new file mode 100644 index 0000000..1244219 --- /dev/null +++ b/hashlib/test/compare/compare_md5_test.dart @@ -0,0 +1,54 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +// ignore_for_file: library_annotations + +@Tags(['vm-only']) + +import 'dart:io'; + +import 'package:crypto/crypto.dart' as crypto; +import 'package:hashlib/codecs.dart'; +import 'package:hashlib/hashlib.dart'; +import 'package:hashlib/random.dart'; +import 'package:test/test.dart'; + +void main() { + group('MD5 comparison', () { + test('for a file async', () async { + var file = File('LICENSE'); + var hash = await crypto.md5.bind(file.openRead()).first; + var hash2 = await md5.file(file); + expect(hash2.hex(), toHex(hash.bytes)); + }, tags: 'vm-only'); + + test('for a file sync', () async { + var file = File('LICENSE'); + var hash = await crypto.md5.bind(file.openRead()).first; + var hash2 = md5.fileSync(file); + expect(hash2.hex(), toHex(hash.bytes)); + }, tags: 'vm-only'); + + test('with crypto', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + expect( + toHex(md5.convert(data).bytes), + toHex(crypto.md5.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + } + }); + + test('run in parallel', () async { + await Future.wait(List.generate(10, (i) => i).map((i) async { + final data = randomBytes(i); + expect( + toHex(md5.convert(data).bytes), + toHex(crypto.md5.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + })); + }); + }); +} diff --git a/hashlib/test/compare/compare_sha224_test.dart b/hashlib/test/compare/compare_sha224_test.dart new file mode 100644 index 0000000..0366193 --- /dev/null +++ b/hashlib/test/compare/compare_sha224_test.dart @@ -0,0 +1,62 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +// ignore_for_file: library_annotations + +@Tags(['vm-only']) + +import 'package:crypto/crypto.dart' as crypto; +import 'package:hashlib/codecs.dart'; +import 'package:hashlib/hashlib.dart'; +import 'package:hashlib/random.dart'; +import 'package:test/test.dart'; + +void main() { + group('SHA-224 comparison', () { + test('against known implementations', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + expect( + toHex(sha224.convert(data).bytes), + toHex(crypto.sha224.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + } + }); + + test('run in parallel', () async { + await Future.wait(List.generate(10, (i) => i).map((i) async { + final data = randomBytes(i); + expect( + toHex(sha224.convert(data).bytes), + toHex(crypto.sha224.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + })); + }); + + group('SHA-256 comparison', () { + test('against known implementations', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + expect( + toHex(sha256.convert(data).bytes), + toHex(crypto.sha256.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + } + }); + + test('run in parallel', () async { + await Future.wait(List.generate(10, (i) => i).map((i) async { + final data = randomBytes(i); + expect( + toHex(sha256.convert(data).bytes), + toHex(crypto.sha256.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + })); + }); + }); + }); +} diff --git a/hashlib/test/compare/compare_sha384_test.dart b/hashlib/test/compare/compare_sha384_test.dart new file mode 100644 index 0000000..6795cfa --- /dev/null +++ b/hashlib/test/compare/compare_sha384_test.dart @@ -0,0 +1,38 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +// ignore_for_file: library_annotations + +@Tags(['vm-only']) + +import 'package:crypto/crypto.dart' as crypto; +import 'package:hashlib/codecs.dart'; +import 'package:hashlib/hashlib.dart'; +import 'package:hashlib/random.dart'; +import 'package:test/test.dart'; + +void main() { + group('SHA-384 comparison', () { + test('against known implementations', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + expect( + toHex(sha384.convert(data).bytes), + toHex(crypto.sha384.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + } + }); + + test('run in parallel', () async { + await Future.wait(List.generate(10, (i) => i).map((i) async { + final data = randomBytes(i); + expect( + toHex(sha384.convert(data).bytes), + toHex(crypto.sha384.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + })); + }); + }); +} diff --git a/hashlib/test/compare/compare_sha512_224_test.dart b/hashlib/test/compare/compare_sha512_224_test.dart new file mode 100644 index 0000000..98700e2 --- /dev/null +++ b/hashlib/test/compare/compare_sha512_224_test.dart @@ -0,0 +1,38 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +// ignore_for_file: library_annotations + +@Tags(['vm-only']) + +import 'package:crypto/crypto.dart' as crypto; +import 'package:hashlib/codecs.dart'; +import 'package:hashlib/hashlib.dart'; +import 'package:hashlib/random.dart'; +import 'package:test/test.dart'; + +void main() { + group('SHA-512/224 comparison', () { + test('with known implementations', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + expect( + toHex(sha512t224.convert(data).bytes), + toHex(crypto.sha512224.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + } + }); + + test('run in parallel', () async { + await Future.wait(List.generate(10, (i) => i).map((i) async { + final data = randomBytes(i); + expect( + toHex(sha512t224.convert(data).bytes), + toHex(crypto.sha512224.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + })); + }); + }); +} diff --git a/hashlib/test/compare/compare_sha512_256_test.dart b/hashlib/test/compare/compare_sha512_256_test.dart new file mode 100644 index 0000000..3427107 --- /dev/null +++ b/hashlib/test/compare/compare_sha512_256_test.dart @@ -0,0 +1,38 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +// ignore_for_file: library_annotations + +@Tags(['vm-only']) + +import 'package:crypto/crypto.dart' as crypto; +import 'package:hashlib/codecs.dart'; +import 'package:hashlib/hashlib.dart'; +import 'package:hashlib/random.dart'; +import 'package:test/test.dart'; + +void main() { + group('SHA-512/256 comparison', () { + test('with known implementations', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + expect( + toHex(sha512t256.convert(data).bytes), + toHex(crypto.sha512256.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + } + }); + + test('run in parallel', () async { + await Future.wait(List.generate(10, (i) => i).map((i) async { + final data = randomBytes(i); + expect( + toHex(sha512t256.convert(data).bytes), + toHex(crypto.sha512256.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + })); + }); + }); +} diff --git a/hashlib/test/compare/compare_sha512_test.dart b/hashlib/test/compare/compare_sha512_test.dart new file mode 100644 index 0000000..7efc7cd --- /dev/null +++ b/hashlib/test/compare/compare_sha512_test.dart @@ -0,0 +1,38 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +// ignore_for_file: library_annotations + +@Tags(['vm-only']) + +import 'package:crypto/crypto.dart' as crypto; +import 'package:hashlib/codecs.dart'; +import 'package:hashlib/hashlib.dart'; +import 'package:hashlib/random.dart'; +import 'package:test/test.dart'; + +void main() { + group('SHA-512 comparison', () { + test('with known implementations', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + expect( + toHex(sha512.convert(data).bytes), + toHex(crypto.sha512.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + } + }); + + test('run in parallel', () async { + await Future.wait(List.generate(10, (i) => i).map((i) async { + final data = randomBytes(i); + expect( + toHex(sha512.convert(data).bytes), + toHex(crypto.sha512.convert(data).bytes), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + })); + }); + }); +} diff --git a/hashlib/test/compare/compare_sm3_test.dart b/hashlib/test/compare/compare_sm3_test.dart new file mode 100644 index 0000000..8aa76d9 --- /dev/null +++ b/hashlib/test/compare/compare_sm3_test.dart @@ -0,0 +1,36 @@ +// Copyright (c) 2023, Sudipto Chandra +// All rights reserved. Check LICENSE file for details. + +// ignore_for_file: library_annotations + +@Tags(['vm-only']) + +import 'dart:io'; + +import 'package:hashlib/codecs.dart'; +import 'package:hashlib/hashlib.dart'; +import 'package:hashlib/random.dart'; +import 'package:pointycastle/digests/sm3.dart' as pc_sm3; +import 'package:test/test.dart'; + +void main() { + group('SM3 comparison', () { + test('with pointy-castle', () { + for (int i = 0; i < 100; ++i) { + final data = randomBytes(i); + expect( + sm3.convert(data).hex(), + toHex(pc_sm3.SM3Digest().process(data)), + reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', + ); + } + }); + + test('for a file sync', () { + var file = File('LICENSE'); + var hash = pc_sm3.SM3Digest().process(file.readAsBytesSync()); + var hash2 = sm3.fileSync(file); + expect(hash2.hex(), toHex(hash)); + }, tags: 'vm-only'); + }); +} diff --git a/hashlib/test/compare_test.dart b/hashlib/test/compare_test.dart deleted file mode 100644 index 133942e..0000000 --- a/hashlib/test/compare_test.dart +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright (c) 2023, Sudipto Chandra -// All rights reserved. Check LICENSE file for details. - -// ignore_for_file: library_annotations - -@Tags(['vm-only']) - -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:crypto/crypto.dart' as crypto; -import 'package:hashlib/codecs.dart'; -import 'package:hashlib/hashlib.dart'; -import 'package:hashlib/random.dart'; -import 'package:pointycastle/digests/blake2b.dart' as pc_blake2b; -import 'package:pointycastle/digests/keccak.dart' as pc_keccak; -import 'package:pointycastle/digests/md4.dart' as pc_md4; -import 'package:pointycastle/digests/sha3.dart' as pc_sha3; -import 'package:pointycastle/digests/sm3.dart' as pc_sm3; -import 'package:test/test.dart'; - -void main() { - group('blake2b512 comparison', () { - test('with pointycastle', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - final out1 = blake2b512.convert(data).hex(); - final out2 = toHex( - pc_blake2b.Blake2bDigest(digestSize: 64).process(data), - ); - expect(out1, equals(out2), reason: 'size: $i'); - } - }); - - test('with pointycastle with key', () { - final key = randomBytes(16); - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - final out1 = blake2b512.mac.by(key).convert(data).hex(); - final out2 = toHex( - pc_blake2b.Blake2bDigest(digestSize: 64, key: key).process(data), - ); - expect(out1, equals(out2), reason: 'size: $i'); - } - }); - - test('with pointycastle with salt', () { - final salt = randomBytes(16); - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - final out1 = Blake2b(64, salt: salt).convert(data).hex(); - final out2 = toHex( - pc_blake2b.Blake2bDigest(digestSize: 64, salt: salt).process(data), - ); - expect(out1, equals(out2), reason: 'size: $i'); - } - }); - - test('with pointycastle with personalization', () { - final personalization = randomBytes(16); - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - final out1 = Blake2b( - 64, - aad: personalization, - ).convert(data).hex(); - final out2 = toHex( - pc_blake2b.Blake2bDigest( - digestSize: 64, - personalization: personalization, - ).process(data), - ); - expect(out1, equals(out2), reason: 'size: $i'); - } - }); - - test('with pointycastle with salt and personalization', () { - final salt = randomBytes(16); - final personalization = randomBytes(16); - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - final out1 = Blake2b( - 64, - salt: salt, - aad: personalization, - ).convert(data).hex(); - final out2 = toHex( - pc_blake2b.Blake2bDigest( - digestSize: 64, - salt: salt, - personalization: personalization, - ).process(data), - ); - expect(out1, equals(out2), reason: 'size: $i'); - } - }); - - test('with pointycastle with key, salt and personalization', () { - final key = randomBytes(16); - final salt = randomBytes(16); - final aad = randomBytes(16); - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - final out1 = Blake2b(64).mac.by(key, salt: salt, aad: aad).hex(data); - final out2 = toHex( - pc_blake2b.Blake2bDigest( - digestSize: 64, - key: key, - salt: salt, - personalization: aad, - ).process(data), - ); - expect(out1, equals(out2), reason: 'size: $i'); - } - }); - }); - - group('HMAC comparison', () { - test('with crypto for MD5', () { - var key = "key"; - var msg = "The quick brown fox jumps over the lazy dog"; - var expected = "80070713463e7749b90c2dc24911e275"; - var actual = toHex( - md5.hmac.byString(key).convert(msg.codeUnits).bytes, - ); - var actual2 = toHex( - crypto.Hmac(crypto.md5, key.codeUnits).convert(msg.codeUnits).bytes, - ); - expect(actual2, expected, reason: "Key: $key | Message: $msg"); - expect(actual, expected, reason: "Key: $key | Message: $msg"); - }); - - test('with crypto', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - final key = randomBytes(i & 0x7F); - expect( - toHex(sha1.hmac.by(key).convert(data).bytes), - toHex(crypto.Hmac(crypto.sha1, key).convert(data).bytes), - reason: 'Key: "${String.fromCharCodes(key)}" [${key.length}]\n' - 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - - test('run in parallel', () async { - await Future.wait(List.generate(10, (i) => i).map((i) async { - final data = randomBytes(i); - final key = randomBytes(i & 0x7F); - expect( - toHex(sha384.hmac.by(key).convert(data).bytes), - toHex(crypto.Hmac(crypto.sha384, key).convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - })); - }); - }); - - group('Keccak comparison', () { - test('with keccak256', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - var pc = pc_keccak.KeccakDigest(256); - var other = pc.process(Uint8List.fromList(data)); - expect( - keccak256.convert(data).hex(), - toHex(other), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - - test('with sha3', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - var pc = pc_sha3.SHA3Digest(256); - var other = pc.process(Uint8List.fromList(data)); - expect( - sha3_256.convert(data).hex(), - toHex(other), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - }); - - group('MD5 comparison', () { - test('for a file async', () async { - var file = File('LICENSE'); - var hash = await crypto.md5.bind(file.openRead()).first; - var hash2 = await md5.file(file); - expect(hash2.hex(), toHex(hash.bytes)); - }, tags: 'vm-only'); - - test('for a file sync', () async { - var file = File('LICENSE'); - var hash = await crypto.md5.bind(file.openRead()).first; - var hash2 = md5.fileSync(file); - expect(hash2.hex(), toHex(hash.bytes)); - }, tags: 'vm-only'); - - test('with crypto', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - expect( - toHex(md5.convert(data).bytes), - toHex(crypto.md5.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - - test('run in parallel', () async { - await Future.wait(List.generate(10, (i) => i).map((i) async { - final data = randomBytes(i); - expect( - toHex(md5.convert(data).bytes), - toHex(crypto.md5.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - })); - }); - }); - - group('MD4 comparison', () { - test('with pointy-castle', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - expect( - toHex(md4.convert(data).bytes), - toHex(pc_md4.MD4Digest().process(data)), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - - test('for a file sync', () { - var file = File('LICENSE'); - var hash = pc_md4.MD4Digest().process(file.readAsBytesSync()); - var hash2 = md4.fileSync(file); - expect(hash2.hex(), toHex(hash)); - }, tags: 'vm-only'); - }); - - group('SM3 comparison', () { - test('with pointy-castle', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - expect( - sm3.convert(data).hex(), - toHex(pc_sm3.SM3Digest().process(data)), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - - test('for a file sync', () { - var file = File('LICENSE'); - var hash = pc_sm3.SM3Digest().process(file.readAsBytesSync()); - var hash2 = sm3.fileSync(file); - expect(hash2.hex(), toHex(hash)); - }, tags: 'vm-only'); - }); - - group('SHA1 comparison', () { - test('against known implementations', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - expect( - toHex(sha1.convert(data).bytes), - toHex(crypto.sha1.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - - test('run in parallel', () async { - await Future.wait(List.generate(10, (i) => i).map((i) async { - final data = randomBytes(i); - expect( - toHex(sha1.convert(data).bytes), - toHex(crypto.sha1.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - })); - }); - }); - - group('SHA-224 comparison', () { - test('against known implementations', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - expect( - toHex(sha224.convert(data).bytes), - toHex(crypto.sha224.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - - test('run in parallel', () async { - await Future.wait(List.generate(10, (i) => i).map((i) async { - final data = randomBytes(i); - expect( - toHex(sha224.convert(data).bytes), - toHex(crypto.sha224.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - })); - }); - - group('SHA-256 comparison', () { - test('against known implementations', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - expect( - toHex(sha256.convert(data).bytes), - toHex(crypto.sha256.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - - test('run in parallel', () async { - await Future.wait(List.generate(10, (i) => i).map((i) async { - final data = randomBytes(i); - expect( - toHex(sha256.convert(data).bytes), - toHex(crypto.sha256.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - })); - }); - }); - }); - - group('SHA-384 comparison', () { - test('against known implementations', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - expect( - toHex(sha384.convert(data).bytes), - toHex(crypto.sha384.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - - test('run in parallel', () async { - await Future.wait(List.generate(10, (i) => i).map((i) async { - final data = randomBytes(i); - expect( - toHex(sha384.convert(data).bytes), - toHex(crypto.sha384.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - })); - }); - }); - - group('SHA-512/224 comparison', () { - test('with known implementations', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - expect( - toHex(sha512t224.convert(data).bytes), - toHex(crypto.sha512224.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - - test('run in parallel', () async { - await Future.wait(List.generate(10, (i) => i).map((i) async { - final data = randomBytes(i); - expect( - toHex(sha512t224.convert(data).bytes), - toHex(crypto.sha512224.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - })); - }); - }); - - group('SHA-512/256 comparison', () { - test('with known implementations', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - expect( - toHex(sha512t256.convert(data).bytes), - toHex(crypto.sha512256.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - - test('run in parallel', () async { - await Future.wait(List.generate(10, (i) => i).map((i) async { - final data = randomBytes(i); - expect( - toHex(sha512t256.convert(data).bytes), - toHex(crypto.sha512256.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - })); - }); - }); - - group('SHA-512 comparison', () { - test('with known implementations', () { - for (int i = 0; i < 100; ++i) { - final data = randomBytes(i); - expect( - toHex(sha512.convert(data).bytes), - toHex(crypto.sha512.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - } - }); - - test('run in parallel', () async { - await Future.wait(List.generate(10, (i) => i).map((i) async { - final data = randomBytes(i); - expect( - toHex(sha512.convert(data).bytes), - toHex(crypto.sha512.convert(data).bytes), - reason: 'Message: "${String.fromCharCodes(data)}" [${data.length}]', - ); - })); - }); - }); -} diff --git a/hashlib/test/scrypt_test.dart b/hashlib/test/scrypt_test.dart index 6c18dca..19bb863 100644 --- a/hashlib/test/scrypt_test.dart +++ b/hashlib/test/scrypt_test.dart @@ -146,7 +146,7 @@ void main() { 'f4fd0a0cb3bf9c9dc04e3f177936249ac87d619ed41b6b05d2d6dfe95d32153338b' 'c03c4b68fd46e13c9c0e7f7946ee6856cf068f1702e2fbd98'; expect(hash.hex(), matcher); - }); + }, skip: true); test("with security", () { var hash = scrypt( diff --git a/hashlib/test/sha224_test.dart b/hashlib/test/sha224_test.dart index ffa3cf0..007a474 100644 --- a/hashlib/test/sha224_test.dart +++ b/hashlib/test/sha224_test.dart @@ -28,8 +28,8 @@ final tests = { "e0afca6342847c80827fdc511f0004e53239d3c2f82f67ddd8185bef", List.filled(511, "a").join(): "6eb1c24577241c0871ec3ab020786f59cecb2edb6acef2d483051d6a", - List.filled(1000000, "a").join(): - "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67", + // List.filled(1000000, "a").join(): + // "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67", }; void main() { diff --git a/hashlib/test/sha256_test.dart b/hashlib/test/sha256_test.dart index 82094c2..692ca58 100644 --- a/hashlib/test/sha256_test.dart +++ b/hashlib/test/sha256_test.dart @@ -28,8 +28,8 @@ final tests = { "02425c0f5b0dabf3d2b9115f3f7723a02ad8bcfb1534a0d231614fd42b8188f6", List.filled(511, "a").join(): "058fc5084b6355a06099bfef3de8e360344046dc5a47026de47470b9aabb5bfd", - List.filled(1000000, "a").join(): - "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0", + // List.filled(1000000, "a").join(): + // "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0", }; void main() { diff --git a/hashlib/test/sha384_test.dart b/hashlib/test/sha384_test.dart index 88614f3..da0979d 100644 --- a/hashlib/test/sha384_test.dart +++ b/hashlib/test/sha384_test.dart @@ -34,9 +34,9 @@ final tests = { List.filled(511, "a").join(): "db100a1eed3842c61d73064b62543cd4531dafa8bfecf6f27d" "cfdebbaf60ea14563ea1b486e4f6b9a14fcb0dac05c5f2", - List.filled(1000000, "a").join(): - "9d0e1809716474cb086e834e310a4a1ced149e9c00f2485279" - "72cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985", + // List.filled(1000000, "a").join(): + // "9d0e1809716474cb086e834e310a4a1ced149e9c00f2485279" + // "72cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985", }; void main() { diff --git a/hashlib/test/sha512_224_test.dart b/hashlib/test/sha512_224_test.dart index a290861..e6778ae 100644 --- a/hashlib/test/sha512_224_test.dart +++ b/hashlib/test/sha512_224_test.dart @@ -16,6 +16,8 @@ final tests = { "944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37", "The quick brown fox jumps over the lazy cog": "2b9d6565a7e40f780ba8ab7c8dcf41e3ed3b77997f4c55aa987eede5", + List.filled(112, "a").join(): + "79b41fef2a0439d2705724a67615f7bcbcd2bf5664a7774b80818eb6", List.filled(512, "a").join(): "057bab73fa47ac3e597a34d02c1e285e2d5d8a2e90c9079f549b4af6", List.filled(128, "a").join(): @@ -24,10 +26,8 @@ final tests = { "502ec9656e1e0b96f9a2699c04cec265edc690b729c45037c6b37a00", List.filled(511, "a").join(): "bd0452a57045c857de05b1c1d94fb49624b00ceaf0ec4c0d4d656a89", - List.filled(1000000, "a").join(): - "37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287", - List.filled(112, "a").join(): - "79b41fef2a0439d2705724a67615f7bcbcd2bf5664a7774b80818eb6", + // List.filled(1000000, "a").join(): + // "37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287", }; void main() { diff --git a/hashlib/test/sha512_256_test.dart b/hashlib/test/sha512_256_test.dart index b120689..9c2978b 100644 --- a/hashlib/test/sha512_256_test.dart +++ b/hashlib/test/sha512_256_test.dart @@ -16,6 +16,8 @@ final tests = { "dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d", "The quick brown fox jumps over the lazy cog": "cc8d255a7f2f38fd50388fd1f65ea7910835c5c1e73da46fba01ea50d5dd76fb", + List.filled(112, "a").join(): + "9216b5303edb66504570bee90e48ea5beaa5e9fe9f760bbd3e0460559fc005f6", List.filled(512, "a").join(): "092b65b92e80ccf4c66683684fb02da4567160534abede190e9b2edef6156839", List.filled(128, "a").join(): @@ -24,10 +26,8 @@ final tests = { "a59cf33e5ad3e70d4962adbb833d021eafa48f85dd9788f84fca4cf762c5f1c7", List.filled(511, "a").join(): "7e627ccc0719192627fcf9f3987d3da9a61f261a09580371e1ea4622b8ccfcc8", - List.filled(1000000, "a").join(): - "9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21", - List.filled(112, "a").join(): - "9216b5303edb66504570bee90e48ea5beaa5e9fe9f760bbd3e0460559fc005f6", + // List.filled(1000000, "a").join(): + // "9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21", }; void main() { diff --git a/hashlib/test/sha512_test.dart b/hashlib/test/sha512_test.dart index eb73529..e3fd083 100644 --- a/hashlib/test/sha512_test.dart +++ b/hashlib/test/sha512_test.dart @@ -22,6 +22,9 @@ final tests = { "The quick brown fox jumps over the lazy cog": "3eeee1d0e11733ef152a6c29503b3ae20c4f1f3cda4cb26f1bc1a41f91c7fe4a" "b3bd86494049e201c4bd5155f31ecb7a3c8606843c4cc8dfcab7da11c8ae5045", + List.filled(112, "a").join(): + "c01d080efd492776a1c43bd23dd99d0a2e626d481e16782e75d54c2503b5dc32" + "bd05f0f1ba33e568b88fd2d970929b719ecbb152f58f130a407c8830604b70ca", List.filled(512, "a").join(): "0210d27bcbe05c2156627c5f136ade1338ab98e06a4591a00b0bcaa61662a593" "1d0b3bd41a67b5c140627923f5f6307669eb508d8db38b2a8cd41aebd783394b", @@ -34,12 +37,9 @@ final tests = { List.filled(511, "a").join(): "fe32a1f497ce532d041889133436c7086ea40410af5728a6b958aa4a169de44e" "3884311461188be5f65e79b9a53d010d8347ac20118e4e05df787a17ba71204b", - List.filled(1000000, "a").join(): - "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb" - "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b", - List.filled(112, "a").join(): - "c01d080efd492776a1c43bd23dd99d0a2e626d481e16782e75d54c2503b5dc32" - "bd05f0f1ba33e568b88fd2d970929b719ecbb152f58f130a407c8830604b70ca", + // List.filled(1000000, "a").join(): + // "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb" + // "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b", }; void main() { diff --git a/hashlib/test/sm3_test.dart b/hashlib/test/sm3_test.dart index 8c401cc..749e013 100644 --- a/hashlib/test/sm3_test.dart +++ b/hashlib/test/sm3_test.dart @@ -34,8 +34,8 @@ final tests = { "97baef04b5211a439b17eb067ad904e52b12058d7510669ad29b63b9d4609479", List.filled(511, "a").join(): "5f4141700026fec7880a6d1d5f34dcc9253dea2df32928f71bc93860d675b38c", - List.filled(1000000, "a").join(): - "c8aaf89429554029e231941a2acc0ad61ff2a5acd8fadd25847a3a732b3b02c3", + // List.filled(1000000, "a").join(): + // "c8aaf89429554029e231941a2acc0ad61ff2a5acd8fadd25847a3a732b3b02c3", }; void main() { diff --git a/no_screenshot/android/build.gradle b/no_screenshot/android/build.gradle index b1c7bc7..80b139c 100644 --- a/no_screenshot/android/build.gradle +++ b/no_screenshot/android/build.gradle @@ -2,14 +2,14 @@ group 'com.flutterplaza.no_screenshot' version '1.0-SNAPSHOT' buildscript { - ext.kotlin_version = '1.6.10' + ext.kotlin_version = '2.1.0' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.1.3' + classpath 'com.android.tools.build:gradle:8.6.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' android { namespace "com.flutterplaza.no_screenshot" - compileSdkVersion 31 + compileSdk 36 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 diff --git a/no_screenshot/pubspec.yaml b/no_screenshot/pubspec.yaml index 23a142f..26f4e5a 100644 --- a/no_screenshot/pubspec.yaml +++ b/no_screenshot/pubspec.yaml @@ -1,8 +1,8 @@ name: no_screenshot description: Flutter plugin to enable, disable, toggle or stream screenshot activities in your application. -version: 0.3.2-beta.3 +version: 0.3.2 homepage: https://flutterplaza.com -repository: https://github.com/FlutterPlaza/no_screenshot/releases/tag/v0.3.2-beta.3 +repository: https://github.com/FlutterPlaza/no_screenshot/releases/tag/v0.3.2 environment: sdk: '>=3.0.0 <4.0.0' @@ -16,7 +16,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^4.0.0 + flutter_lints: ">=4.0.0 <6.0.0" flutter_driver: sdk: flutter