Skip to content

Commit

Permalink
Adds support for PBKDF2Security
Browse files Browse the repository at this point in the history
  • Loading branch information
dipu-bd committed Sep 8, 2024
1 parent b9dfe4f commit 1af6f44
Show file tree
Hide file tree
Showing 23 changed files with 320 additions and 218 deletions.
15 changes: 8 additions & 7 deletions BENCHMARK.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,14 @@ With 10B message (100000 iterations):

Key derivator algorithm benchmarks on different security parameters:

| Algorithms | test | little | moderate | good | strong |
| ---------- | -------- | -------- | --------- | ---------- | ----------- |
| scrypt | 0.056 ms | 1.495 ms | 27.024 ms | 88.235 ms | 2945.416 ms |
| bcrypt | 0.226 ms | 2.124 ms | 17.19 ms | 270.562 ms | 2159.172 ms |
| argon2i | 0.334 ms | 2.548 ms | 16.994 ms | 213.406 ms | 2556.027 ms |
| argon2d | 0.265 ms | 2.475 ms | 17.222 ms | 211.376 ms | 2528.972 ms |
| argon2id | 0.276 ms | 2.549 ms | 19.534 ms | 213.577 ms | 2547.892 ms |
| Algorithms | little | moderate | good | strong |
| ---------- | -------- | --------- | ---------- | ----------- |
| scrypt | 1.589 ms | 16.688 ms | 91.663 ms | 2937.545 ms |
| bcrypt | 2.24 ms | 17.077 ms | 273.729 ms | 2155.139 ms |
| pbkdf2 | 0.849 ms | 17.091 ms | 283.537 ms | 3419.39 ms |
| argon2i | 3.914 ms | 16.474 ms | 215.783 ms | 2598.387 ms |
| argon2d | 2.981 ms | 16.98 ms | 207.425 ms | 2563.844 ms |
| argon2id | 2.311 ms | 16.491 ms | 205.25 ms | 2576.335 ms |

> All benchmarks are done on _AMD Ryzen 7 5800X_ processor and _3200MHz_ RAM using compiled _exe_
>
Expand Down
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ void main() {
print('Keccak-512 => ${keccak512.string(text)}');
print('SHAKE-128 => ${shake128.of(20).string(text)}');
print('SHAKE-256 => ${shake256.of(20).string(text)}');
print('BLAKE-2s/256 => ${blake2s256.string(text)}');
print('BLAKE-2b/512 => ${blake2b512.string(text)}');
print('BLAKE2s-256 => ${blake2s256.string(text)}');
print('BLAKE2b-512 => ${blake2b512.string(text)}');
print('SM3] => ${sm3.string(text)}');
print('');
Expand All @@ -160,16 +160,16 @@ void main() {
print('HMAC/SHA1 => ${sha1.hmac.byString(text)}');
print('HMAC/SHA256 => ${sha256.hmac.byString(key).string(text)}');
print('HMAC/SHA3-256 => ${HMAC(sha3_256).by(pw).string(text)}');
print("HMAC/BLAKE-2b/256 => ${blake2b512.hmac.by(pw).string(text)}");
print("HMAC/BLAKE2b-256 => ${blake2b512.hmac.by(pw).string(text)}");
print("BLAKE-2b-MAC/256 => ${blake2b256.mac.by(pw).string(text)}");
print("BLAKE-2b-MAC/224 => ${Blake2b(28).mac.by(pw).string(text)}");
print('');
// Examples of PBKDF2 key derivation
print("SHA256/HMAC/PBKDF2 => ${pbkdf2(pw, iv, 100).hex()}");
print("SHA1/HMAC/PBKDF2 => ${sha1.pbkdf2(iv, 100).hex(pw)}");
print("BLAKE-2b/256/HMAC/PBKDF2 => ${blake2b256.pbkdf2(iv, 100).hex(pw)}");
print("BLAKE-2b/256/MAC/PBKDF2 => ${blake2b256.mac.pbkdf2(iv, 100).hex(pw)}");
print("BLAKE2b-256/HMAC/PBKDF2 => ${blake2b256.pbkdf2(iv, 100).hex(pw)}");
print("BLAKE2b-256/MAC/PBKDF2 => ${blake2b256.mac.pbkdf2(iv, 100).hex(pw)}");
print('');
// Examples of OTP generation
Expand Down Expand Up @@ -303,13 +303,14 @@ With 10B message (100000 iterations):

Key derivator algorithm benchmarks on different security parameters:

| Algorithms | test | little | moderate | good | strong |
| ---------- | -------- | -------- | --------- | ---------- | ----------- |
| scrypt | 0.056 ms | 1.495 ms | 27.024 ms | 88.235 ms | 2945.416 ms |
| bcrypt | 0.226 ms | 2.124 ms | 17.19 ms | 270.562 ms | 2159.172 ms |
| argon2i | 0.334 ms | 2.548 ms | 16.994 ms | 213.406 ms | 2556.027 ms |
| argon2d | 0.265 ms | 2.475 ms | 17.222 ms | 211.376 ms | 2528.972 ms |
| argon2id | 0.276 ms | 2.549 ms | 19.534 ms | 213.577 ms | 2547.892 ms |
| Algorithms | little | moderate | good | strong |
| ---------- | -------- | --------- | ---------- | ----------- |
| scrypt | 1.589 ms | 16.688 ms | 91.663 ms | 2937.545 ms |
| bcrypt | 2.24 ms | 17.077 ms | 273.729 ms | 2155.139 ms |
| pbkdf2 | 0.849 ms | 17.091 ms | 283.537 ms | 3419.39 ms |
| argon2i | 3.914 ms | 16.474 ms | 215.783 ms | 2598.387 ms |
| argon2d | 2.981 ms | 16.98 ms | 207.425 ms | 2563.844 ms |
| argon2id | 2.311 ms | 16.491 ms | 205.25 ms | 2576.335 ms |

> All benchmarks are done on _AMD Ryzen 7 5800X_ processor and _3200MHz_ RAM using compiled _exe_
>
Expand Down
87 changes: 52 additions & 35 deletions benchmark/benchmark.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import 'hmac_md5.dart' as md5_hmac;
import 'hmac_sha1.dart' as sha1_hmac;
import 'hmac_sha256.dart' as sha256_hmac;
import 'md4.dart' as md4;
import 'pbkdf2.dart' as pbkdf2;
import 'md5.dart' as md5;
import 'poly1305.dart' as poly1305;
import 'ripemd128.dart' as ripemd128;
Expand Down Expand Up @@ -234,51 +235,67 @@ void measureHashFunctions() {
void measureKeyDerivation() {
dump('Key derivator algorithm benchmarks on different security parameters:');
dump('');
var argon2Levels = [
Argon2Security.test,
Argon2Security.little,
Argon2Security.moderate,
Argon2Security.good,
Argon2Security.strong,
];
var scryptLevels = [
ScryptSecurity.test,
ScryptSecurity.little,
ScryptSecurity.moderate,
ScryptSecurity.good,
ScryptSecurity.strong,
];
var bcryptLevels = [
BcryptSecurity.test,
BcryptSecurity.little,
BcryptSecurity.moderate,
BcryptSecurity.good,
BcryptSecurity.strong,
];
var argon2Levels = {
'little': Argon2Security.little,
'moderate': Argon2Security.moderate,
'good': Argon2Security.good,
'strong': Argon2Security.strong,
};
var scryptLevels = {
'little': ScryptSecurity.little,
'moderate': ScryptSecurity.moderate,
'good': ScryptSecurity.good,
'strong': ScryptSecurity.strong,
};
var bcryptLevels = {
'little': BcryptSecurity.little,
'moderate': BcryptSecurity.moderate,
'good': BcryptSecurity.good,
'strong': BcryptSecurity.strong,
};
var pbkdf2Levels = {
'little': PBKDF2Security.little,
'moderate': PBKDF2Security.moderate,
'good': PBKDF2Security.good,
'strong': PBKDF2Security.strong,
};
var algorithms = {
'scrypt': scryptLevels.map((e) => scrypt.HashlibBenchmark(e)),
'bcrypt': bcryptLevels.map((e) => bcrypt.HashlibBenchmark(e)),
'argon2i': argon2Levels.map((e) => argon2.HashlibArgon2iBenchmark(e)),
'argon2d': argon2Levels.map((e) => argon2.HashlibArgon2dBenchmark(e)),
'argon2id': argon2Levels.map((e) => argon2.HashlibArgon2idBenchmark(e)),
'scrypt':
scryptLevels.map((k, s) => MapEntry(k, scrypt.HashlibBenchmark(s))),
'bcrypt':
bcryptLevels.map((k, s) => MapEntry(k, bcrypt.HashlibBenchmark(s))),
'pbkdf2':
pbkdf2Levels.map((k, s) => MapEntry(k, pbkdf2.HashlibBenchmark(s))),
'argon2i': argon2Levels
.map((k, s) => MapEntry(k, argon2.HashlibArgon2iBenchmark(s))),
'argon2d': argon2Levels
.map((k, s) => MapEntry(k, argon2.HashlibArgon2dBenchmark(s))),
'argon2id': argon2Levels
.map((k, s) => MapEntry(k, argon2.HashlibArgon2idBenchmark(s))),
};

var names = {
...argon2Levels.map((e) => e.name),
...scryptLevels.map((e) => e.name),
...bcryptLevels.map((e) => e.name),
...argon2Levels.keys,
...scryptLevels.keys,
...bcryptLevels.keys,
}.toList();
var separator = names.map((e) => ('-' * (e.length + 2)));
dump('| Algorithms | ${argon2Levels.map((e) => e.name).join(' | ')} |');

dump('| Algorithms | ${names.join(' | ')} |');
dump('|------------|${separator.join('|')}|');
for (var entry in algorithms.entries) {
var algorithm = entry.key;
var items = entry.value;
var message = '| $algorithm |';
for (var item in items) {
var runtime = item.measure();
message += ' ${runtime / 1000} ms |';
var instances = entry.value;
var message = '| $algorithm ';
for (var name in names) {
message += ' | ';
var item = instances[name];
if (item != null) {
var runtime = item.measure();
message += '${runtime / 1000} ms';
}
}
message += '|';
dump(message);
}
dump('');
Expand Down
87 changes: 47 additions & 40 deletions benchmark/pbkdf2.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import 'dart:math';
import 'dart:typed_data';

import 'package:hashlib/hashlib.dart' as hashlib;
import 'package:hashlib/hashlib.dart';
import 'package:pointycastle/export.dart' show Pbkdf2Parameters;
import 'package:pointycastle/pointycastle.dart' as pc;

Expand All @@ -14,58 +14,65 @@ Random random = Random();

final salt = Uint8List.fromList(List.generate(16, (i) => random.nextInt(256)));

class HashlibBenchmark extends Benchmark {
HashlibBenchmark(int size, int iter) : super('hashlib', size, iter);
class HashlibBenchmark extends KDFBenchmarkBase {
final PBKDF2Security security;

@override
void run() {
hashlib.sha256.hmac.pbkdf2(salt, iter, 64).convert(input);
}
HashlibBenchmark(this.security) : super('hashlib');

@override
void exercise() {
run();
void run() {
final salt = Uint8List.fromList("some salt".codeUnits);
final pass = Uint8List.fromList("some password".codeUnits);
PBKDF2.fromSecurity(security, salt: salt, keyLength: 64).convert(pass);
}
}

class PointyCastleBenchmark extends Benchmark {
Uint8List _input = Uint8List(0);
PointyCastleBenchmark(int size, int iter) : super('PointyCastle', size, iter);
class PointyCastleBenchmark extends KDFBenchmarkBase {
final PBKDF2Security security;

@override
void setup() {
super.setup();
_input = Uint8List.fromList(input);
}
PointyCastleBenchmark(this.security) : super('hashlib');

@override
void run() {
final salt = Uint8List.fromList("some salt".codeUnits);
final pass = Uint8List.fromList("some password".codeUnits);
var pbkdf2 = pc.KeyDerivator('SHA-256/HMAC/PBKDF2');
pbkdf2.init(Pbkdf2Parameters(salt, security.c, 64));
var out = Uint8List(64);
var d = pc.KeyDerivator('SHA-256/HMAC/PBKDF2');
d.init(Pbkdf2Parameters(salt, iter, 64));
d.deriveKey(_input, 0, out, 0);
}

@override
void exercise() {
run();
pbkdf2.deriveKey(pass, 0, out, 0);
}
}

void main() {
print('----- PBKDF2-HMAC(SHA256) -----');
final conditions = [
[32, 100000],
[32, 1000],
[32, 10],
];
for (var condition in conditions) {
int size = condition[0];
int iter = condition[1];
print('---- size: ${formatSize(size)} | iterations: $iter ----');
HashlibBenchmark(size, iter).measureDiff([
PointyCastleBenchmark(size, iter),
]);
print('');
}
double runtime;
print('--------- Hashlib/PBKDF2 ----------');
runtime = HashlibBenchmark(PBKDF2Security.test).measure();
print('hashlib/pbkdf2[test]: ${runtime / 1000} ms');
runtime = HashlibBenchmark(PBKDF2Security.little).measure();
print('hashlib/pbkdf2[little]: ${runtime / 1000} ms');
runtime = HashlibBenchmark(PBKDF2Security.moderate).measure();
print('hashlib/pbkdf2[moderate]: ${runtime / 1000} ms');
runtime = HashlibBenchmark(PBKDF2Security.good).measure();
print('hashlib/pbkdf2[good]: ${runtime / 1000} ms');
runtime = HashlibBenchmark(PBKDF2Security.strong).measure();
print('hashlib/pbkdf2[strong]: ${runtime / 1000} ms');
runtime = HashlibBenchmark(PBKDF2Security.owasp).measure();
print('hashlib/pbkdf2[owasp1]: ${runtime / 1000} ms');
runtime = HashlibBenchmark(PBKDF2Security.owasp2).measure();
print('hashlib/pbkdf2[owasp2]: ${runtime / 1000} ms');
runtime = HashlibBenchmark(PBKDF2Security.owasp3).measure();
print('hashlib/pbkdf2[owasp3]: ${runtime / 1000} ms');
print('');
print('--------- PointyCastle/PBKDF2 ----------');
runtime = PointyCastleBenchmark(PBKDF2Security.test).measure();
print('pc/pbkdf2[test]: ${runtime / 1000} ms');
runtime = PointyCastleBenchmark(PBKDF2Security.little).measure();
print('pc/pbkdf2[little]: ${runtime / 1000} ms');
runtime = PointyCastleBenchmark(PBKDF2Security.moderate).measure();
print('pc/pbkdf2[moderate]: ${runtime / 1000} ms');
runtime = PointyCastleBenchmark(PBKDF2Security.good).measure();
print('pc/pbkdf2[good]: ${runtime / 1000} ms');
runtime = PointyCastleBenchmark(PBKDF2Security.strong).measure();
print('pc/pbkdf2[strong]: ${runtime / 1000} ms');
print('');
}
36 changes: 14 additions & 22 deletions benchmark/scrypt.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import 'dart:math';
import 'dart:typed_data';

import 'package:hashlib/hashlib.dart';
import 'package:pointycastle/export.dart';
import 'package:pointycastle/key_derivators/scrypt.dart' as pc;
import 'package:pointycastle/export.dart' show ScryptParameters;

import '_base.dart';

Expand All @@ -19,12 +19,13 @@ class HashlibBenchmark extends KDFBenchmarkBase {

@override
void run() {
scrypt(
'long password'.codeUnits,
'secret salt'.codeUnits,
security: security,
dklen: 64,
);
final salt = Uint8List.fromList('secret salt'.codeUnits);
final pass = Uint8List.fromList('long password'.codeUnits);
Scrypt.fromSecurity(
security,
salt: salt,
derivedKeyLength: 64,
).convert(pass);
}
}

Expand All @@ -35,21 +36,12 @@ class PointyCastleBenchmark extends KDFBenchmarkBase {

@override
void run() {
var scrypt = pc.Scrypt();
scrypt.init(ScryptParameters(
security.N,
security.r,
security.p,
64,
Uint8List.fromList('secret salt'.codeUnits),
));
var out = Uint8List(64);
scrypt.deriveKey(
Uint8List.fromList('long password'.codeUnits),
0,
out,
0,
);
final salt = Uint8List.fromList('secret salt'.codeUnits);
final pass = Uint8List.fromList('long password'.codeUnits);
final scrypt = pc.Scrypt();
scrypt.init(ScryptParameters(security.N, security.r, security.p, 64, salt));
final out = Uint8List(64);
scrypt.deriveKey(pass, 0, out, 0);
}
}

Expand Down
14 changes: 7 additions & 7 deletions example/hashlib_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ void main() {
print('Keccak-512 => ${keccak512.string(text)}');
print('SHAKE-128 => ${shake128.of(20).string(text)}');
print('SHAKE-256 => ${shake256.of(20).string(text)}');
print('BLAKE-2s/256 => ${blake2s256.string(text)}');
print('BLAKE-2b/512 => ${blake2b512.string(text)}');
print('BLAKE2s-256 => ${blake2s256.string(text)}');
print('BLAKE2b-512 => ${blake2b512.string(text)}');
print('SM3] => ${sm3.string(text)}');
print('');

Expand All @@ -52,16 +52,16 @@ void main() {
print('HMAC/SHA1 => ${sha1.hmac.byString(text)}');
print('HMAC/SHA256 => ${sha256.hmac.byString(key).string(text)}');
print('HMAC/SHA3-256 => ${HMAC(sha3_256).by(pw).string(text)}');
print("HMAC/BLAKE-2b/256 => ${blake2b512.hmac.by(pw).string(text)}");
print("HMAC/BLAKE2b-256 => ${blake2b512.hmac.by(pw).string(text)}");
print("BLAKE-2b-MAC/256 => ${blake2b256.mac.by(pw).string(text)}");
print("BLAKE-2b-MAC/224 => ${Blake2b(28).mac.by(pw).string(text)}");
print('');

// Examples of PBKDF2 key derivation
print("SHA256/HMAC/PBKDF2 => ${pbkdf2(pw, iv, 100).hex()}");
print("SHA1/HMAC/PBKDF2 => ${sha1.pbkdf2(iv, 100).hex(pw)}");
print("BLAKE-2b/256/HMAC/PBKDF2 => ${blake2b256.pbkdf2(iv, 100).hex(pw)}");
print("BLAKE-2b/256/MAC/PBKDF2 => ${blake2b256.mac.pbkdf2(iv, 100).hex(pw)}");
print("SHA256/HMAC/PBKDF2 => ${pbkdf2(pw, iv).hex()}");
print("BLAKE2b-256/HMAC/PBKDF2 => ${blake2b256.pbkdf2(iv).hex(pw)}");
print("BLAKE2b-256/MAC/PBKDF2 => ${blake2b256.mac.pbkdf2(iv).hex(pw)}");
print("SHA1/HMAC/PBKDF2 => ${sha1.pbkdf2(iv, iterations: 100).hex(pw)}");
print('');

// Examples of OTP generation
Expand Down
Loading

0 comments on commit 1af6f44

Please sign in to comment.