twonly-app-dependencies/hashlib/test/scrypt_test.dart
2026-02-07 23:12:41 +01:00

268 lines
8.2 KiB
Dart

// 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('scrypt test', () {
test("with empty password and empty salt and r=1", () {
var hash = scrypt(
[],
[],
N: 16,
r: 1,
p: 1,
dklen: 64,
);
var matcher =
'77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442'
'fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906';
expect(hash.hex(), matcher);
});
test("with empty password and empty salt and r=2", () {
var hash = scrypt(
[],
[],
N: 16,
r: 2,
p: 1,
dklen: 64,
);
var matcher =
'5517696d05d1df94fb42f067d9fcdb14d9effe8ac37500957e1b6f1d383ea029'
'61accf2409bba1ae87c94c6fc69f9b32393eea0b877eb7803c2f151a888acdb6';
expect(hash.hex(), matcher);
});
test("with empty password and empty salt and p=2", () {
var hash = scrypt(
[],
[],
N: 16,
r: 1,
p: 2,
dklen: 64,
);
var matcher =
'7e0ce022d41610408361d487a4962d0b39f8172397d62e911108b5ad4adb3dc7'
'faf817f593b6b83cc42b040d975d564ce1fdb2c432e7cbe8cdcaa5a0ad6bf647';
expect(hash.hex(), matcher);
});
test("with empty password and 'salt'", () {
var hash = scrypt(
[],
"salt".codeUnits,
N: 16,
r: 1,
p: 1,
dklen: 64,
);
var matcher =
'eec80a460eeaab62fe1630b19497e7ba6a1ff85f50807b9cfe52a9f192e5b60c'
'b73563d28e4cb148ba301a2271de3682b88c4677caa2e061d2d0e29990cd4e09';
expect(hash.hex(), matcher);
});
test("with 'password' and empty salt", () {
var hash = scrypt(
"password".codeUnits,
[],
N: 16,
r: 1,
p: 1,
dklen: 64,
);
var matcher =
'd33c6ec1818daaf728f55afadfeaa558b38efa81305b3521a7f12f4be097e84d'
'184092d2a2e93bf71fd1efe052710f66b956ce45da43aa9099de7406d3a05e2a';
expect(hash.hex(), matcher);
});
test("with empty 'passwd' and 'salt'", () {
var hash = scrypt(
"passwd".codeUnits,
"salt".codeUnits,
N: 16,
r: 1,
p: 1,
dklen: 64,
);
var matcher =
'd1635540c8e908f949eaf651eef261cd38e73e0c5c0fe1673e21d72442edb957'
'7bcaa47ea345a789ec687efd4c21224c7cc9fd892954c40df024bf44d6b8bf2a';
expect(hash.hex(), matcher);
});
test("with a long key length", () {
var hash = scrypt(
"a test key".codeUnits,
"some salt".codeUnits,
N: 16,
r: 8,
p: 2,
dklen: 256,
);
var matcher = '9ddb1ba07f1973893a3f2629c23449b4ab189eef07a3a8b521cd129'
'ee43cb39067ce849085311849736159ec828d09b0f8f423051dddfb85835730eb'
'455af9a27a46f198d301e5f6ad678c0ec7c3559bf390887563e951d1070f1613f'
'8f68eeb565196bf8896a948e183af3e10127e098230e86870c3b6b62f43a7ac9f'
'9078619d93c4dadffb4d198bccd9676eb979102b48ccd6ab6f31ce6f4e1cf420e'
'cfc6f4840fc30eebd6223dfeed1aa95637c6d594386317885e2b2817e6e88b502'
'd7d9896b01877c97791d0e5ca6e7d9982b59a7655710f343713e2bc2259624792'
'795bdc9cef22b805c36d15102b1eda1d62f766b02579ef74fb4488faa91973a2a00';
expect(hash.hex(), matcher);
});
test("with long r and p parameters", () {
var hash = scrypt(
"a test key".codeUnits,
"some salt".codeUnits,
N: 16,
r: 28,
p: 22,
dklen: 128,
);
var matcher = '48a2b70cc60f0608775f6616167492381f1a6673c4422fe76f3197c8'
'45d35844fee961ef7cf5783bb2b5a84883423e766be1224f2435bdc738245a0d025'
'2a3626a73e1548f3807b4a8fe39b779deedf200deb593d078f2e98e989b90030ab3'
'9938bf52fa291683fd8ebaa1abbfedee33a2df7b3cf1b000e5b8634097990c7ce4';
expect(hash.hex(), matcher);
});
test("with random N, r, p", () {
var hash = scrypt(
"a test key".codeUnits,
"some salt".codeUnits,
N: 128,
r: 81,
p: 49,
dklen: 120,
);
var matcher = '183944033aa4a4fc92c783b6d40236220a1985ddbed2e6b29abb5d382'
'aecfac52e992d3eb779f7573c66f563d4365e8dae680ecdb59a017af70ed30f398a'
'f4fd0a0cb3bf9c9dc04e3f177936249ac87d619ed41b6b05d2d6dfe95d32153338b'
'c03c4b68fd46e13c9c0e7f7946ee6856cf068f1702e2fbd98';
expect(hash.hex(), matcher);
}, skip: true);
test("with security", () {
var hash = scrypt(
[],
[],
security: ScryptSecurity.test,
);
var matcher =
'5517696d05d1df94fb42f067d9fcdb14d9effe8ac37500957e1b6f1d383ea029'
'61accf2409bba1ae87c94c6fc69f9b32393eea0b877eb7803c2f151a888acdb6';
expect(hash.hex(), matcher);
});
test("with security overrides", () {
var hash = scrypt(
[],
[],
security: ScryptSecurity.test,
r: 1,
);
var matcher =
'77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442'
'fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906';
expect(hash.hex(), matcher);
});
});
group('Scrypt Factory Tests', () {
test("with security", () {
var hash = Scrypt.fromSecurity(ScryptSecurity.test, salt: []);
var matcher =
'5517696d05d1df94fb42f067d9fcdb14d9effe8ac37500957e1b6f1d383ea029'
'61accf2409bba1ae87c94c6fc69f9b32393eea0b877eb7803c2f151a888acdb6';
expect(hash.convert([]).hex(), matcher);
});
test('throws if cost is less than 1', () {
expect(
() => Scrypt(cost: 0),
throwsA(isA<StateError>().having(
(e) => e.message, 'message', 'The cost must be at least 1')),
);
});
test('throws if cost is greater than 2^24', () {
expect(
() => Scrypt(cost: 0x1000000),
throwsA(isA<StateError>().having(
(e) => e.message, 'message', 'The cost must be less than 2^24')),
);
});
test('throws if cost is not a power of 2', () {
expect(
() => Scrypt(cost: 5),
throwsA(isA<StateError>().having(
(e) => e.message, 'message', 'The cost must be a power of 2')),
);
});
test('throws if derivedKeyLength is less than 1', () {
expect(
() => Scrypt(cost: 2, derivedKeyLength: 0),
throwsA(isA<StateError>().having((e) => e.message, 'message',
'The derivedKeyLength must be at least 1')),
);
});
test('throws if blockSize is less than 1', () {
expect(
() => Scrypt(cost: 2, blockSize: 0),
throwsA(isA<StateError>().having(
(e) => e.message, 'message', 'The blockSize must be at least 1')),
);
});
test('throws if parallelism is less than 1', () {
expect(
() => Scrypt(cost: 2, parallelism: 0),
throwsA(isA<StateError>().having(
(e) => e.message, 'message', 'The parallelism must be at least 1')),
);
});
test('throws if blockSize * parallelism is too big', () {
expect(
() => Scrypt(cost: 2, blockSize: 0x2000000, parallelism: 1),
throwsA(isA<StateError>().having((e) => e.message, 'message',
'The blockSize * parallelism is too big')),
);
});
test('uses provided salt if not null', () {
var salt = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
var scrypt = Scrypt(cost: 2, salt: salt);
expect(scrypt.salt, equals(salt));
});
test('generates a random salt if salt is null', () {
var scrypt = Scrypt(cost: 2);
expect(scrypt.salt.length, 16);
});
test('creates an instance with valid parameters', () {
var salt = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
var scrypt = Scrypt(
cost: 2,
salt: salt,
blockSize: 8,
parallelism: 1,
derivedKeyLength: 64);
expect(scrypt.salt, equals(salt));
expect(scrypt.cost, equals(2));
expect(scrypt.blockSize, equals(8));
expect(scrypt.parallelism, equals(1));
expect(scrypt.derivedKeyLength, equals(64));
});
});
}