halkyon/packages/halkyon_keys/test/row_ids_test.dart

55 lines
1.9 KiB
Dart
Raw Normal View History

import 'package:halkyon_keys/halkyon_keys.dart';
import 'package:sodium/sodium_sumo.dart';
import 'package:test/test.dart';
Future<void> main() async {
final sodium = await SodiumSumoInit.init();
group('row IDs keyed by the account', () {
final account = AccountKeys.generate(sodium);
final secrets = (
encryption: account.encryption.secretKey.extractBytes(),
signing: account.signing.secretKey.extractBytes(),
);
test('every device of the account names a row alike: its keys, unlocked '
'anew, give the same ID', () {
final elsewhere = AccountKeys.fromSecretKeys(
sodium,
encryptionSecretKey: secrets.encryption,
signingSecretKey: secrets.signing,
);
expect(
keyedRowId(sodium, elsewhere, 'train/day/2026-10-30'),
keyedRowId(sodium, account, 'train/day/2026-10-30'),
);
});
test('another name, or the same name of another account, gives another '
'ID', () {
final other = AccountKeys.generate(sodium);
final id = keyedRowId(sodium, account, 'train/day/2026-10-30');
expect(keyedRowId(sodium, account, 'train/day/2026-10-31'), isNot(id));
expect(keyedRowId(sodium, account, 'train/night/2026-10-30'), isNot(id));
expect(keyedRowId(sodium, other, 'train/day/2026-10-30'), isNot(id));
});
test("the ID is a UUID of version 8, RFC 9562's for IDs of one's own "
'making, and not a name hashed in the open (version 5)', () {
final id = keyedRowId(sodium, account, 'train/day/2026-10-30');
expect(
id,
matches(
RegExp(
'^[0-9a-f]{8}-[0-9a-f]{4}-8[0-9a-f]{3}-[89ab][0-9a-f]{3}-'
r'[0-9a-f]{12}$',
),
),
);
});
test('a row without a name has no ID', () {
expect(() => keyedRowId(sodium, account, ''), throwsArgumentError);
});
});
}