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.
dateKeys-dart/test/age_interop_test.dart

102 lines
3.4 KiB

// The age writer against Go, in the other direction: the files that this
// library writes, opened by Go. test/vectors/age_interop.json holds the
// recipes of test/age_interop_support.dart, the files that this library
// wrote from them with SeededRandomSource (their length and SHA-256, and
// their bytes when small) and what filippo.io/age and agewrap made of each
// with each opener (tool/age_interop_go_verdicts.go). Here each file is
// written again from its recipe and must be the one that Go read; Go
// opened it to the plaintext of the recipe, or refused it where the recipe
// expects a refusal; and this library makes the same of it as Go: the same
// plaintext or the same error text, and the same stanza rules. The vectors
// come from a Dart constant, so that this also runs compiled to
// JavaScript, without the expensive samples.
import 'dart:convert';
import 'package:datekeys/datekeys.dart';
import 'package:datekeys/src/age.dart';
import 'package:datekeys/src/agewrap.dart';
import 'package:datekeys/src/sha256.dart';
import 'package:test/test.dart';
import 'age_interop_support.dart';
import 'age_writer_support.dart';
import 'vectors/age_interop.g.dart';
final Json vectors = jsonDecode(ageInteropJson) as Json;
const recipeKeys = [
'name',
'seed',
'recipients',
'inner',
'length',
'pieces',
'node',
'openers',
];
Json recipe(Json s) => {
for (final k in recipeKeys)
if (s.containsKey(k)) k: s[k],
};
String rule(void Function() f) {
try {
f();
return 'ok';
} on DateKeysException catch (e) {
return e.message;
}
}
void main() {
final samples = listOf(vectors['samples']);
test('the recipes are those that the tool writes', () {
expect(jsonDecode(jsonEncode(interopSamples())), samples.map(recipe));
});
for (final s in samples.where((s) => !isWeb || s['node'] != false)) {
test(s['name'], () {
final file = writeSample(s);
expect(file.length, s['file_length']);
expect(toHex(sha256(file)), s['file_sha256']);
if (s['file'] != null) expect(toHex(file), s['file']);
final header = parseAgeHeader(file);
expect(header.length, s['header_length']);
final stanzas = header.stanzas;
expect([for (final st in stanzas) st.type], s['stanzas']);
// Go opened it to the plaintext of the recipe with some opener, and
// this library makes of it what Go made with each.
final plain = toHex(sha256(finalPlaintext(s)));
final openers = listOf(s['openers']);
final verdicts = listOf(s['verdicts']);
expect(verdicts, hasLength(openers.length));
expect(verdicts.where((v) => v['error'] == null), isNotEmpty);
for (var i = 0; i < openers.length; i++) {
final v = verdicts[i];
if (v['error'] == null) expect(v['plaintext_sha256'], plain);
expect(openWith(file, openers[i]), v, reason: 'opener $i');
}
// The stanza rules of agewrap, as Go applied them.
final q = quicknet();
expect({
'payload': rule(() => checkPayloadStanzas(stanzas)),
'access_0': rule(() => checkAccessStanzas(stanzas, 0)),
'access_16': rule(() => checkAccessStanzas(stanzas, accessSlots)),
'time_1000': rule(
() => checkTimeStanzas(
stanzas,
round: 1000,
chainHashHex: q.chainHashHex,
profileId: q.id,
),
),
}, s['rules']);
});
}
}

Powered by TurnKey Linux.