You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
3.3 KiB
107 lines
3.3 KiB
// The recipes of the interoperability of stage 7b, Dart to Go: sealed
|
|
// locators with their envelopes, author key files and Ed25519 signatures,
|
|
// which this library writes with SeededRandomSource. tool/
|
|
// seal_interop_dart_samples.dart writes their files, tool/
|
|
// seal_interop_go_verdicts.go opens them with Go and writes test/vectors/
|
|
// seal_interop.json, and seal_interop_test.dart writes them again and
|
|
// compares them with what Go read. It reads no file.
|
|
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:datekeys/src/authorkey.dart';
|
|
import 'package:datekeys/src/bytes.dart';
|
|
import 'package:datekeys/src/locator.dart';
|
|
import 'package:datekeys/src/locator_seal.dart';
|
|
import 'package:datekeys/src/profile.dart';
|
|
import 'package:datekeys/src/sha256.dart';
|
|
|
|
import 'age_support.dart' show pattern;
|
|
import 'random_support.dart';
|
|
|
|
export 'random_support.dart';
|
|
|
|
/// The recipes, in their order.
|
|
List<Json> interopRecipes() => [
|
|
for (final (round, n, addresses) in [
|
|
(1000, 0, 1),
|
|
(1001, 100, 2),
|
|
(1004, 70000, 8),
|
|
(2000, 5000, 3),
|
|
])
|
|
{
|
|
'kind': 'locator',
|
|
'name': 'a locator of round $round, a .dkc of $n bytes',
|
|
'seed': 'interop locator $round',
|
|
'round': round,
|
|
'dkc_length': n,
|
|
'addresses': [
|
|
for (var i = 0; i < addresses; i++)
|
|
{'uri': 'https://example.com/$round/$i', 'offset': i * 1000},
|
|
],
|
|
},
|
|
for (final (i, pass) in [(0, ''), (1, 'una contraseña larga'), (2, 'p')])
|
|
{
|
|
'kind': 'key',
|
|
'name': pass.isEmpty ? 'a plain key file' : 'a key file for "$pass"',
|
|
'seed': 'interop key $i',
|
|
'passphrase': pass,
|
|
},
|
|
for (final n in [0, 1, 32, 64, 99, 100, 1000, 70000])
|
|
{
|
|
'kind': 'signature',
|
|
'name': 'a signature of $n bytes',
|
|
'seed': 'interop signature $n',
|
|
'message_length': n,
|
|
},
|
|
];
|
|
|
|
/// The files of a recipe, by the suffix of their name, and what Go must
|
|
/// find in them.
|
|
Map<String, Uint8List> interopFiles(Json r) {
|
|
final random = seeded(r['seed']! as String);
|
|
switch (r['kind']) {
|
|
case 'locator':
|
|
final dkc = pattern(r['dkc_length']! as int);
|
|
final e = newEnvelope(dkc, random: random);
|
|
final loc = e.locator.withAddresses([
|
|
for (final a in listOf(r['addresses']))
|
|
LocatorAddress(a['uri']! as String, a['offset']! as int),
|
|
]);
|
|
final sealed = sealLocator(
|
|
quicknet(),
|
|
r['round']! as int,
|
|
loc,
|
|
random: random,
|
|
);
|
|
return {
|
|
'sealed': sealed,
|
|
'rest': e.rest,
|
|
'plaintext': loc.marshal(),
|
|
'dkc': dkc,
|
|
};
|
|
case 'key':
|
|
final key = AuthorKey.generate(random);
|
|
final pass = r['passphrase']! as String;
|
|
return {
|
|
'file': pass.isEmpty
|
|
? marshalAuthorKey(key)
|
|
: encryptAuthorKey(key, pass, random: random),
|
|
'secret': utf8Bytes(key.secret),
|
|
'public': utf8Bytes(key.publicString),
|
|
};
|
|
default:
|
|
final key = AuthorKey.generate(random);
|
|
final msg = pattern(r['message_length']! as int);
|
|
return {
|
|
'signature': key.sign(msg),
|
|
'public_key': key.publicKey,
|
|
'seed': utf8Bytes(key.secret),
|
|
};
|
|
}
|
|
}
|
|
|
|
/// The SHA-256 of each file, as the vectors write them.
|
|
Json interopDigests(Map<String, Uint8List> files) => {
|
|
for (final e in files.entries) e.key: toHex(sha256(e.value)),
|
|
};
|