Stage 7a: the addresses of a locator and the IP addresses of netip
lib/src/locator.dart starts with the addresses of spec 44.1, a port of
CheckURI and Address.Host of package locator of datekeys-go: the same
checks in the same order and the same texts, on the UTF-8 of the address,
with Go's %q of the first byte that RFC 3986 does not allow. And
checkResolvedIp, the check of the IP that a name resolves to, which a
reader runs on every connection: the classification of publicIP on the 4
or 16 bytes of an address, an IPv4-mapped one not public. Go has no such
function, since its reader does not download.
lib/src/ipaddr.dart, internal, parses IPv4 and IPv6 with the exact
acceptance of netip.ParseAddr, writes them as its String, and classifies
them as publicIP, with the blocks of spec 44.1. It works byte by byte, so
that the 128 bits of IPv6 stay exact on the web, and never uses dart:io.
The tests run the 247 addresses of locator.json and the 2 800 of the
vectors, the 1 700 strings of netip and the 868 byte strings of publicIP,
on the VM and on Node.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 days ago
|
|
|
// Helpers of the tests of the locator (stage 7a): the vectors of
|
Stage 7a: the locator, its opening and the envelope
lib/src/locator.dart gains the rest of package locator of datekeys-go but
Seal and the data of the extension, with the same checks in the same
order and the same texts:
- Locator: unmarshalLocator, the map of spec 44.1 with the length that
Marshal gives and nothing else, and marshal, its form, its addresses and
key 6 up to the least multiple of 4096 that it fills, as padFor and
PlaintextLength; usable, the addresses that a reader uses.
- openLocator, Open of Go: the profile, then age with the tlock identity
of agewrap, and at most 1 MiB of plaintext, as io.LimitReader: the
chunks after it are neither decrypted nor checked.
- The envelope: restIn, openEnvelope with the size and the SHA-256 of the
rest and of the .dkc, hideRest, and splitEnvelope, the part of
NewEnvelope after its age encryption, which needs the writer of age.
A Locator keeps the types of Go: keys and digests of 32 bytes, and no
negative size or offset. Its errors carry no code, as in Go.
The tests run the cases of locator.json, the padding of every base, 482
plaintexts, Marshal at its limits, 118 openings, the files past 1 MiB, the
envelope, the rests and the split; a part also on Node.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 days ago
|
|
|
// tool/locator_go_vectors.go, their edits and their compact addresses, and
|
|
|
|
|
// what a reader reads of a locator, as the generator writes it. They read no
|
Stage 7a: the addresses of a locator and the IP addresses of netip
lib/src/locator.dart starts with the addresses of spec 44.1, a port of
CheckURI and Address.Host of package locator of datekeys-go: the same
checks in the same order and the same texts, on the UTF-8 of the address,
with Go's %q of the first byte that RFC 3986 does not allow. And
checkResolvedIp, the check of the IP that a name resolves to, which a
reader runs on every connection: the classification of publicIP on the 4
or 16 bytes of an address, an IPv4-mapped one not public. Go has no such
function, since its reader does not download.
lib/src/ipaddr.dart, internal, parses IPv4 and IPv6 with the exact
acceptance of netip.ParseAddr, writes them as its String, and classifies
them as publicIP, with the blocks of spec 44.1. It works byte by byte, so
that the 128 bits of IPv6 stay exact on the web, and never uses dart:io.
The tests run the 247 addresses of locator.json and the 2 800 of the
vectors, the 1 700 strings of netip and the 868 byte strings of publicIP,
on the VM and on Node.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 days ago
|
|
|
// file, so that the tests that run on Node.js can use them.
|
|
|
|
|
library;
|
|
|
|
|
|
|
|
|
|
import 'dart:convert';
|
Stage 7a: the locator, its opening and the envelope
lib/src/locator.dart gains the rest of package locator of datekeys-go but
Seal and the data of the extension, with the same checks in the same
order and the same texts:
- Locator: unmarshalLocator, the map of spec 44.1 with the length that
Marshal gives and nothing else, and marshal, its form, its addresses and
key 6 up to the least multiple of 4096 that it fills, as padFor and
PlaintextLength; usable, the addresses that a reader uses.
- openLocator, Open of Go: the profile, then age with the tlock identity
of agewrap, and at most 1 MiB of plaintext, as io.LimitReader: the
chunks after it are neither decrypted nor checked.
- The envelope: restIn, openEnvelope with the size and the SHA-256 of the
rest and of the .dkc, hideRest, and splitEnvelope, the part of
NewEnvelope after its age encryption, which needs the writer of age.
A Locator keeps the types of Go: keys and digests of 32 bytes, and no
negative size or offset. Its errors carry no code, as in Go.
The tests run the cases of locator.json, the padding of every base, 482
plaintexts, Marshal at its limits, 118 openings, the files past 1 MiB, the
envelope, the rests and the split; a part also on Node.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 days ago
|
|
|
import 'dart:typed_data';
|
Stage 7a: the addresses of a locator and the IP addresses of netip
lib/src/locator.dart starts with the addresses of spec 44.1, a port of
CheckURI and Address.Host of package locator of datekeys-go: the same
checks in the same order and the same texts, on the UTF-8 of the address,
with Go's %q of the first byte that RFC 3986 does not allow. And
checkResolvedIp, the check of the IP that a name resolves to, which a
reader runs on every connection: the classification of publicIP on the 4
or 16 bytes of an address, an IPv4-mapped one not public. Go has no such
function, since its reader does not download.
lib/src/ipaddr.dart, internal, parses IPv4 and IPv6 with the exact
acceptance of netip.ParseAddr, writes them as its String, and classifies
them as publicIP, with the blocks of spec 44.1. It works byte by byte, so
that the 128 bits of IPv6 stay exact on the web, and never uses dart:io.
The tests run the 247 addresses of locator.json and the 2 800 of the
vectors, the 1 700 strings of netip and the 868 byte strings of publicIP,
on the VM and on Node.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 days ago
|
|
|
|
Stage 7a: the locator, its opening and the envelope
lib/src/locator.dart gains the rest of package locator of datekeys-go but
Seal and the data of the extension, with the same checks in the same
order and the same texts:
- Locator: unmarshalLocator, the map of spec 44.1 with the length that
Marshal gives and nothing else, and marshal, its form, its addresses and
key 6 up to the least multiple of 4096 that it fills, as padFor and
PlaintextLength; usable, the addresses that a reader uses.
- openLocator, Open of Go: the profile, then age with the tlock identity
of agewrap, and at most 1 MiB of plaintext, as io.LimitReader: the
chunks after it are neither decrypted nor checked.
- The envelope: restIn, openEnvelope with the size and the SHA-256 of the
rest and of the .dkc, hideRest, and splitEnvelope, the part of
NewEnvelope after its age encryption, which needs the writer of age.
A Locator keeps the types of Go: keys and digests of 32 bytes, and no
negative size or offset. Its errors carry no code, as in Go.
The tests run the cases of locator.json, the padding of every base, 482
plaintexts, Marshal at its limits, 118 openings, the files past 1 MiB, the
envelope, the rests and the split; a part also on Node.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 days ago
|
|
|
import 'package:datekeys/src/bytes.dart';
|
Stage 7a: the addresses of a locator and the IP addresses of netip
lib/src/locator.dart starts with the addresses of spec 44.1, a port of
CheckURI and Address.Host of package locator of datekeys-go: the same
checks in the same order and the same texts, on the UTF-8 of the address,
with Go's %q of the first byte that RFC 3986 does not allow. And
checkResolvedIp, the check of the IP that a name resolves to, which a
reader runs on every connection: the classification of publicIP on the 4
or 16 bytes of an address, an IPv4-mapped one not public. Go has no such
function, since its reader does not download.
lib/src/ipaddr.dart, internal, parses IPv4 and IPv6 with the exact
acceptance of netip.ParseAddr, writes them as its String, and classifies
them as publicIP, with the blocks of spec 44.1. It works byte by byte, so
that the 128 bits of IPv6 stay exact on the web, and never uses dart:io.
The tests run the 247 addresses of locator.json and the 2 800 of the
vectors, the 1 700 strings of netip and the 868 byte strings of publicIP,
on the VM and on Node.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 days ago
|
|
|
import 'package:datekeys/src/locator.dart';
|
Stage 7a: the locator, its opening and the envelope
lib/src/locator.dart gains the rest of package locator of datekeys-go but
Seal and the data of the extension, with the same checks in the same
order and the same texts:
- Locator: unmarshalLocator, the map of spec 44.1 with the length that
Marshal gives and nothing else, and marshal, its form, its addresses and
key 6 up to the least multiple of 4096 that it fills, as padFor and
PlaintextLength; usable, the addresses that a reader uses.
- openLocator, Open of Go: the profile, then age with the tlock identity
of agewrap, and at most 1 MiB of plaintext, as io.LimitReader: the
chunks after it are neither decrypted nor checked.
- The envelope: restIn, openEnvelope with the size and the SHA-256 of the
rest and of the .dkc, hideRest, and splitEnvelope, the part of
NewEnvelope after its age encryption, which needs the writer of age.
A Locator keeps the types of Go: keys and digests of 32 bytes, and no
negative size or offset. Its errors carry no code, as in Go.
The tests run the cases of locator.json, the padding of every base, 482
plaintexts, Marshal at its limits, 118 openings, the files past 1 MiB, the
envelope, the rests and the split; a part also on Node.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 days ago
|
|
|
import 'package:datekeys/src/profile.dart';
|
|
|
|
|
import 'package:datekeys/src/release.dart';
|
|
|
|
|
import 'package:datekeys/src/sha256.dart';
|
Stage 7a: the addresses of a locator and the IP addresses of netip
lib/src/locator.dart starts with the addresses of spec 44.1, a port of
CheckURI and Address.Host of package locator of datekeys-go: the same
checks in the same order and the same texts, on the UTF-8 of the address,
with Go's %q of the first byte that RFC 3986 does not allow. And
checkResolvedIp, the check of the IP that a name resolves to, which a
reader runs on every connection: the classification of publicIP on the 4
or 16 bytes of an address, an IPv4-mapped one not public. Go has no such
function, since its reader does not download.
lib/src/ipaddr.dart, internal, parses IPv4 and IPv6 with the exact
acceptance of netip.ParseAddr, writes them as its String, and classifies
them as publicIP, with the blocks of spec 44.1. It works byte by byte, so
that the 128 bits of IPv6 stay exact on the web, and never uses dart:io.
The tests run the 247 addresses of locator.json and the 2 800 of the
vectors, the 1 700 strings of netip and the 868 byte strings of publicIP,
on the VM and on Node.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 days ago
|
|
|
|
|
|
|
|
typedef Json = Map<String, Object?>;
|
|
|
|
|
|
|
|
|
|
/// The list [key] of [v], each item a list.
|
|
|
|
|
List<List<Object?>> rows(Json v, String key) => [
|
|
|
|
|
for (final r in v[key]! as List<Object?>) r! as List<Object?>,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
/// The text [i] of the table of [v]: `''` for no error.
|
|
|
|
|
String textOf(Json v, Object? i) =>
|
|
|
|
|
(v['texts']! as List<Object?>)[i! as int]! as String;
|
|
|
|
|
|
Stage 7a: the locator, its opening and the envelope
lib/src/locator.dart gains the rest of package locator of datekeys-go but
Seal and the data of the extension, with the same checks in the same
order and the same texts:
- Locator: unmarshalLocator, the map of spec 44.1 with the length that
Marshal gives and nothing else, and marshal, its form, its addresses and
key 6 up to the least multiple of 4096 that it fills, as padFor and
PlaintextLength; usable, the addresses that a reader uses.
- openLocator, Open of Go: the profile, then age with the tlock identity
of agewrap, and at most 1 MiB of plaintext, as io.LimitReader: the
chunks after it are neither decrypted nor checked.
- The envelope: restIn, openEnvelope with the size and the SHA-256 of the
rest and of the .dkc, hideRest, and splitEnvelope, the part of
NewEnvelope after its age encryption, which needs the writer of age.
A Locator keeps the types of Go: keys and digests of 32 bytes, and no
negative size or offset. Its errors carry no code, as in Go.
The tests run the cases of locator.json, the padding of every base, 482
plaintexts, Marshal at its limits, 118 openings, the files past 1 MiB, the
envelope, the rests and the split; a part also on Node.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 days ago
|
|
|
/// An address as the generator writes it: the string, or [before, byte,
|
|
|
|
|
/// count, after] for one with a run of count copies of a byte.
|
|
|
|
|
String uriOf(Object? x) {
|
|
|
|
|
if (x is String) return x;
|
|
|
|
|
final l = x! as List<Object?>;
|
|
|
|
|
return '${l[0]}${(l[1]! as String) * (l[2]! as int)}${l[3]}';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The edits [edits] of [base] applied in one pass: each [at, delete,
|
|
|
|
|
/// insert] replaces delete bytes at the offset at of the base with the bytes
|
|
|
|
|
/// of the hexadecimal insert, and [at, delete, byte, count] with count
|
|
|
|
|
/// copies of the byte. The offsets are those of the base, in order.
|
|
|
|
|
Uint8List applyLocatorEdits(List<int> base, Object? edits) {
|
|
|
|
|
final out = BytesBuilder(copy: false);
|
|
|
|
|
var pos = 0;
|
|
|
|
|
for (final e in (edits! as List<Object?>).cast<List<Object?>>()) {
|
|
|
|
|
final at = e[0]! as int;
|
|
|
|
|
final delete = e[1]! as int;
|
|
|
|
|
if (at < pos || at + delete > base.length) {
|
|
|
|
|
throw StateError('edit at $at out of order or beyond the base');
|
|
|
|
|
}
|
|
|
|
|
out.add(base.sublist(pos, at));
|
|
|
|
|
final insert = fromHex(e[2]! as String);
|
|
|
|
|
final repeat = e.length > 3 ? e[3]! as int : 1;
|
|
|
|
|
for (var i = 0; i < repeat; i++) {
|
|
|
|
|
out.add(insert);
|
|
|
|
|
}
|
|
|
|
|
pos = at + delete;
|
|
|
|
|
}
|
|
|
|
|
out.add(base.sublist(pos));
|
|
|
|
|
return out.takeBytes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The lower-case hexadecimal SHA-256 of [b].
|
|
|
|
|
String sha256Hex(List<int> b) => toHex(sha256(b));
|
|
|
|
|
|
|
|
|
|
/// What a reader reads of [l], as the generator writes it: [[uri, offset,
|
|
|
|
|
/// host, usable]...], the key, the SHA-256 of the header, the digest of the
|
|
|
|
|
/// rest, its size and capsule_digest, with each address in full.
|
|
|
|
|
List<Object?> summaryOf(Locator l) => [
|
|
|
|
|
[
|
|
|
|
|
for (final a in l.addresses)
|
|
|
|
|
[a.uri, a.offset, a.host, l.usable.contains(a)],
|
|
|
|
|
],
|
|
|
|
|
toHex(l.envelopeKey),
|
|
|
|
|
sha256Hex(l.envelopeHeader),
|
|
|
|
|
toHex(l.restDigest),
|
|
|
|
|
l.restSize,
|
|
|
|
|
toHex(l.capsuleDigest),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
/// The summary [s] of the generator, with each address in full.
|
|
|
|
|
List<Object?> expandSummary(Object? s) {
|
|
|
|
|
final l = s! as List<Object?>;
|
|
|
|
|
return [
|
|
|
|
|
[
|
|
|
|
|
for (final a in (l[0]! as List<Object?>).cast<List<Object?>>())
|
|
|
|
|
[uriOf(a[0]), a[1], uriOf(a[2]), a[3]],
|
|
|
|
|
],
|
|
|
|
|
...l.sublist(1),
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The release of [round] of the vectors [v], public data of drand.
|
|
|
|
|
Release releaseOf(Json v, int round) {
|
|
|
|
|
final r = (v['releases']! as Json)['$round']! as String;
|
|
|
|
|
return Release(round, fromHex(r));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The pinned Quicknet profile, edited as the generator names the edit.
|
|
|
|
|
Profile profileOf(String edit) {
|
|
|
|
|
final p = quicknet();
|
|
|
|
|
switch (edit) {
|
|
|
|
|
case '':
|
|
|
|
|
return p;
|
|
|
|
|
case 'key not on the curve':
|
|
|
|
|
final k = Uint8List.fromList(p.publicKey);
|
|
|
|
|
k[k.length - 1] ^= 1;
|
|
|
|
|
return p.copyWith(publicKey: k);
|
|
|
|
|
case 'key at infinity':
|
|
|
|
|
return p.copyWith(publicKey: [0xc0, ...List.filled(95, 0)]);
|
|
|
|
|
case 'key of another network':
|
|
|
|
|
// The generator of G2, compressed.
|
|
|
|
|
return p.copyWith(
|
|
|
|
|
publicKey: fromHex(
|
|
|
|
|
'93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049'
|
|
|
|
|
'334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051'
|
|
|
|
|
'c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8',
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
case 'chain hash of another network':
|
|
|
|
|
final h = Uint8List.fromList(p.chainHash);
|
|
|
|
|
h[0] ^= 1;
|
|
|
|
|
return p.copyWith(chainHash: h);
|
|
|
|
|
}
|
|
|
|
|
throw ArgumentError(edit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The release that an open case names: a round, or an edit of the release
|
|
|
|
|
/// of the case.
|
|
|
|
|
Release openRelease(Json v, int round, Object? release) {
|
|
|
|
|
if (release is int) return releaseOf(v, release);
|
|
|
|
|
final r = releaseOf(v, round);
|
|
|
|
|
switch (release) {
|
|
|
|
|
case 'flipped':
|
|
|
|
|
final s = Uint8List.fromList(r.signature);
|
|
|
|
|
s[s.length - 1] ^= 1;
|
|
|
|
|
return Release(round, s);
|
|
|
|
|
case 'short':
|
|
|
|
|
return Release(round, r.signature.sublist(0, 47));
|
|
|
|
|
case 'other round':
|
|
|
|
|
return Release(round, releaseOf(v, 1001).signature);
|
|
|
|
|
}
|
|
|
|
|
throw ArgumentError('$release');
|
|
|
|
|
}
|
|
|
|
|
|
Stage 7a: the addresses of a locator and the IP addresses of netip
lib/src/locator.dart starts with the addresses of spec 44.1, a port of
CheckURI and Address.Host of package locator of datekeys-go: the same
checks in the same order and the same texts, on the UTF-8 of the address,
with Go's %q of the first byte that RFC 3986 does not allow. And
checkResolvedIp, the check of the IP that a name resolves to, which a
reader runs on every connection: the classification of publicIP on the 4
or 16 bytes of an address, an IPv4-mapped one not public. Go has no such
function, since its reader does not download.
lib/src/ipaddr.dart, internal, parses IPv4 and IPv6 with the exact
acceptance of netip.ParseAddr, writes them as its String, and classifies
them as publicIP, with the blocks of spec 44.1. It works byte by byte, so
that the 128 bits of IPv6 stay exact on the web, and never uses dart:io.
The tests run the 247 addresses of locator.json and the 2 800 of the
vectors, the 1 700 strings of netip and the 868 byte strings of publicIP,
on the VM and on Node.js.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 days ago
|
|
|
/// The text of the error that [body] throws, `''` when it returns: a
|
|
|
|
|
/// [LocatorException] or a DateKeysException by its message.
|
|
|
|
|
String errorText(void Function() body) {
|
|
|
|
|
try {
|
|
|
|
|
body();
|
|
|
|
|
return '';
|
|
|
|
|
} on LocatorException catch (e) {
|
|
|
|
|
return e.message;
|
|
|
|
|
} on ArgumentError catch (e) {
|
|
|
|
|
// An error of the caller without a normative code, as checkWrite
|
|
|
|
|
// reports an extension out of its place.
|
|
|
|
|
return '${e.message}';
|
|
|
|
|
} on Exception catch (e) {
|
|
|
|
|
return '$e';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The JSON of a constant of test/vectors.
|
|
|
|
|
Json decodeJson(String s) => jsonDecode(s) as Json;
|