432 lines
13 KiB
Dart
432 lines
13 KiB
Dart
// 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}]',
|
|
);
|
|
}));
|
|
});
|
|
});
|
|
}
|