diff --git a/test/age_interop_support.dart b/test/age_interop_support.dart new file mode 100644 index 0000000..47ce896 --- /dev/null +++ b/test/age_interop_support.dart @@ -0,0 +1,222 @@ +// The samples of the interoperability of the age writer: age files that +// this library writes with SeededRandomSource, from recipes, for Go to open +// (tool/age_interop_dart_samples.dart writes them, and +// tool/age_interop_go_verdicts.go opens them with filippo.io/age and the +// identities of agewrap and writes test/vectors/age_interop.json). Each +// recipe names its seed, its recipients, its plaintext (the pattern of its +// length, or another age file, as INNER_ACCESS_AGE inside OUTER_TIME_AGE), +// the pieces in which the plaintext arrives, and the identities that open +// it. They read no file. + +import 'dart:typed_data'; + +import 'package:datekeys/datekeys.dart'; +import 'package:datekeys/src/age.dart'; +import 'package:datekeys/src/age_writer.dart'; +import 'package:datekeys/src/agewrap.dart'; +import 'package:datekeys/src/recipient.dart'; +import 'package:datekeys/src/sha256.dart'; + +import 'age_writer_support.dart'; + +String _x(String label) => X25519Recipient.of(labelIdentity(label)).toString(); + +String _secret(String label) => labelIdentity(label).toString(); + +String _raw(String label) => toHex(labelIdentity(label).secretKey); + +/// The recipes of the samples, in the form of age_interop.json. +List interopSamples() { + final sixteen = [for (var i = 0; i < 16; i++) 'interop slot $i']; + Json access(List labels, int slots) => { + 'access': [for (final l in labels) _raw(l)], + 'slots': slots, + }; + return [ + for (final n in [0, 1, 65535, 65536, 65537, 131072, 3 << 20 | 1]) + { + 'name': 'x25519, $n bytes', + 'seed': 'interop x25519 $n', + 'recipients': [ + {'x25519': _x('interop one')}, + ], + 'length': n, + 'node': n <= 131072, + 'openers': [ + {'x25519': _secret('interop one')}, + {'payload': _raw('interop one')}, + {'x25519': _secret('interop stranger')}, + {'payload': _raw('interop stranger')}, + ], + }, + { + 'name': 'x25519, 200000 bytes in pieces', + 'seed': 'interop pieces', + 'recipients': [ + {'x25519': _x('interop one')}, + ], + 'length': 200000, + 'pieces': [1, 7, 65535, 65537, 1000, 3], + 'node': true, + 'openers': [ + {'x25519': _secret('interop one')}, + ], + }, + { + 'name': 'x25519, three recipients', + 'seed': 'interop three', + 'recipients': [ + for (final l in ['interop a', 'interop b', 'interop c']) + {'x25519': _x(l)}, + ], + 'length': 1000, + 'node': true, + 'openers': [ + for (final l in ['interop a', 'interop b', 'interop c']) + {'x25519': _secret(l)}, + access(['interop b'], 0), + access(['interop a', 'interop stranger'], 0), + {'payload': _raw('interop a')}, + access(['interop a'], 16), + ], + }, + { + 'name': 'x25519, sixteen recipients', + 'seed': 'interop sixteen', + 'recipients': [ + for (final l in sixteen) {'x25519': _x(l)}, + ], + 'length': 103, + 'node': true, + 'openers': [ + access([sixteen[0]], 16), + access([sixteen[7]], 16), + access([sixteen[15]], 16), + access([sixteen[3], sixteen[9]], 16), + access(['interop stranger'], 16), + access([sixteen[5]], 0), + ], + }, + { + 'name': 'tlock, round 1000', + 'seed': 'interop tlock', + 'recipients': [ + {'tlock': 1000}, + ], + 'length': 103, + 'node': true, + 'openers': [ + {'tlock': 1000, 'release': 1000}, + {'tlock': 1001, 'release': 1001}, + ], + }, + { + 'name': 'tlock over sixteen x25519, as SEALED_CONTROL', + 'seed': 'interop sealed control', + 'recipients': [ + {'tlock': 1000}, + ], + 'inner': { + 'seed': 'interop inner access', + 'recipients': [ + for (final l in sixteen) {'x25519': _x(l)}, + ], + 'length': 103, + }, + 'node': false, + 'openers': [ + { + 'tlock': 1000, + 'release': 1000, + 'then': access([sixteen[11]], 16), + }, + { + 'tlock': 1000, + 'release': 1000, + 'then': access(['interop stranger'], 16), + }, + ], + }, + for (final wf in [10, 16]) + { + 'name': 'scrypt, work factor $wf', + 'seed': 'interop scrypt $wf', + 'recipients': [ + {'scrypt': 'una contraseña larga de prueba', 'work_factor': wf}, + ], + 'length': 120, + 'node': wf <= 10, + 'openers': [ + {'scrypt': 'una contraseña larga de prueba', 'max_work_factor': 16}, + {'scrypt': 'otra contraseña', 'max_work_factor': 16}, + { + 'scrypt': 'una contraseña larga de prueba', + 'max_work_factor': wf - 1, + }, + ], + }, + ]; +} + +/// The file of [sample], as this library writes it from its recipe. +Uint8List writeSample(Json sample) { + final rs = [for (final r in listOf(sample['recipients'])) recipientOf(r)]; + final inner = sample['inner'] as Json?; + final plain = inner == null + ? pattern(sample['length']! as int) + : writeSample(inner); + final source = seeded(sample['seed']! as String); + final pieces = sample['pieces'] as List?; + if (pieces == null) return ageEncrypt(plain, rs, random: source); + return encryptInPieces(plain, rs, source, pieces.cast()); +} + +/// The plaintext that [sample] holds in the end: the pattern of its length, +/// in its inner file when it has one. +Uint8List finalPlaintext(Json sample) { + final inner = sample['inner'] as Json?; + return pattern((inner ?? sample)['length']! as int); +} + +/// What this library makes of [file] with [opener], in the form of the +/// verdicts of Go: the SHA-256 and the length of the plaintext, or the text +/// of the error. +Json openWith(Uint8List file, Json opener) { + try { + final plain = _open(file, opener); + return { + 'plaintext_length': plain.length, + 'plaintext_sha256': toHex(sha256(plain)), + }; + } on AgeException catch (e) { + return {'error': e.message}; + } on DateKeysException catch (e) { + return {'error': e.message}; + } +} + +Uint8List _open(Uint8List file, Json o) { + final AgeIdentity id; + if (o['x25519'] case final String s) { + id = X25519Identity.parse(s); + } else if (o['payload'] case final String raw) { + id = PayloadIdentity(fromHex(raw)); + } else if (o['access'] case final List ids) { + id = AccessIdentity(o['slots']! as int, [ + for (final r in ids.cast()) X25519Identity(fromHex(r)), + ]); + } else if (o['scrypt'] case final String pass) { + id = ScryptIdentity(pass, maxWorkFactor: o['max_work_factor']! as int); + } else { + final round = o['tlock']! as int; + final release = o['release']! as int; + id = TimeIdentity( + quicknet(), + round, + Release(release, fromHex(releases[release]!)), + ); + } + final plain = ageDecrypt(file, [id]); + final then = o['then'] as Json?; + return then == null ? plain : _open(plain, then); +} diff --git a/test/age_interop_test.dart b/test/age_interop_test.dart new file mode 100644 index 0000000..9f9febe --- /dev/null +++ b/test/age_interop_test.dart @@ -0,0 +1,101 @@ +// 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']); + }); + } +} diff --git a/test/age_writer_vm_test.dart b/test/age_writer_vm_test.dart index 9a9c583..c23a5cb 100644 --- a/test/age_writer_vm_test.dart +++ b/test/age_writer_vm_test.dart @@ -1,6 +1,8 @@ -// The vectors of the age writer against their file: the Dart constant that -// the tests compiled to JavaScript read is test/vectors/age_writer.json -// byte for byte, as tool/age_writer_go_vectors.go writes both. +// The vectors of the age writer against their files: the Dart constants +// that the tests compiled to JavaScript read are test/vectors/ +// age_writer.json and age_interop.json byte for byte, as +// tool/age_writer_go_vectors.go and tool/age_interop_go_verdicts.go write +// them. @TestOn('vm') library; @@ -8,6 +10,7 @@ import 'dart:io'; import 'package:test/test.dart'; +import 'vectors/age_interop.g.dart'; import 'vectors/age_writer.g.dart'; void main() { @@ -15,4 +18,9 @@ void main() { final file = File('test/vectors/age_writer.json').readAsStringSync(); expect(ageWriterJson, file); }); + + test('age_interop.g.dart holds age_interop.json', () { + final file = File('test/vectors/age_interop.json').readAsStringSync(); + expect(ageInteropJson, file); + }); } diff --git a/test/vectors/age_interop.g.dart b/test/vectors/age_interop.g.dart new file mode 100644 index 0000000..a179108 --- /dev/null +++ b/test/vectors/age_interop.g.dart @@ -0,0 +1,923 @@ +// Generated by tool/age_interop_go_verdicts.go from age_interop.json, for +// the tests that also run compiled to JavaScript, where no file can be +// read. Do not edit. + +/// The text of test/vectors/age_interop.json. +const ageInteropJson = r''' +{ + "description": "Age files that datekeys-dart writes with SeededRandomSource from the recipes of test/age_interop_support.dart, opened by filippo.io/age v1.3.2 and agewrap (tool/age_interop_go_verdicts.go): the length and the SHA-256 of each file, the file when small, the length of its header, its stanzas, the stanza rules of agewrap on them, and the verdict of Go with each opener, the length and the SHA-256 of the plaintext or the text of the error. The plaintext of n bytes has (31·i + 7) mod 256 as byte i. A sample marked node false is left out compiled to JavaScript.", + "go": "go1.26.8", + "samples": [ + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e205832353531392030527832757934394866634955587254497575396f554b65434d6b4265472b337a456465366a476d4f316b0a422b345633417363762f366d4b5a7042786a6f73314d51457370584b567847722f6d6c394c7331414d70510a2d2d2d203758564e36332b5a58387569424331574861736131365969377773374b6c7449516753734b466e2b6a7a550a4a2cadadd212d7592451141f53c4f49226b3efbd1b7e52a62ff725bb6cbaa87f", + "file_length": 200, + "file_sha256": "131e8047bf7084b2910809eb07459f902a0f365852577ca7cd1aea79d9802248", + "header_length": 168, + "length": 0, + "name": "x25519, 0 bytes", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 0", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 0, + "plaintext_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "plaintext_length": 0, + "plaintext_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20583235353139206d33483436423637554a4c546a502f64693254524c4d373367396f63547870694f5a53683442634b4b6a590a69744b6e354c4f417a756e374a524a724c6465476c354353757a6c6c6e614d717139552b6d6b2b327069770a2d2d2d2079794768717850677835623553467251722b39467362676a6974433958324d2b3663564f6856666e5761490aea2e95595f98cb5076cf15c144c3da271d6b9cb151fb8da19e06d79d0b1276eb8c", + "file_length": 201, + "file_sha256": "71d356daf8376a1fdfa0a0c9f55bce42e231c3755c5552364919fbe81cfc2724", + "header_length": 168, + "length": 1, + "name": "x25519, 1 bytes", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 1", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 1, + "plaintext_sha256": "ca358758f6d27e6cf45272937977a748fd88391db679ceda7dc7bf1f005ee879" + }, + { + "plaintext_length": 1, + "plaintext_sha256": "ca358758f6d27e6cf45272937977a748fd88391db679ceda7dc7bf1f005ee879" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file_length": 65735, + "file_sha256": "96f6986395b072f8473bf6fd8834dc4210ca219d714a4db890ff53a046fa4c0b", + "header_length": 168, + "length": 65535, + "name": "x25519, 65535 bytes", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 65535", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 65535, + "plaintext_sha256": "91d0a03af0efeeb5568bbdcf2bd7fe1c9d932c4d22db3643c7586c1bd1afbeb1" + }, + { + "plaintext_length": 65535, + "plaintext_sha256": "91d0a03af0efeeb5568bbdcf2bd7fe1c9d932c4d22db3643c7586c1bd1afbeb1" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file_length": 65736, + "file_sha256": "16a504de46caa5293bd8d99a7ac20bf9bfe7646487f02486025f981a492b7a30", + "header_length": 168, + "length": 65536, + "name": "x25519, 65536 bytes", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 65536", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 65536, + "plaintext_sha256": "ef4636928161808e87035fa51983821677527ccd9661991c5d0126a778b2268a" + }, + { + "plaintext_length": 65536, + "plaintext_sha256": "ef4636928161808e87035fa51983821677527ccd9661991c5d0126a778b2268a" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file_length": 65753, + "file_sha256": "87cd1b28bdc0733f7c85ac8709bb7ce0f99edbbe8a0b9365fb1dc9f31a4631d4", + "header_length": 168, + "length": 65537, + "name": "x25519, 65537 bytes", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 65537", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 65537, + "plaintext_sha256": "74f3260f4a9adaf7271c910ba2d111dbae7a176afb487e1b7f655897eadf1093" + }, + { + "plaintext_length": 65537, + "plaintext_sha256": "74f3260f4a9adaf7271c910ba2d111dbae7a176afb487e1b7f655897eadf1093" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file_length": 131288, + "file_sha256": "9b85f99fe79b22da7c501f855b32650349c9dd1369dee7444fc9b4297df86df2", + "header_length": 168, + "length": 131072, + "name": "x25519, 131072 bytes", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 131072", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 131072, + "plaintext_sha256": "2af5d3dffc8442daccee445639ed726c2148eb693ee20407214076bc65c14fc3" + }, + { + "plaintext_length": 131072, + "plaintext_sha256": "2af5d3dffc8442daccee445639ed726c2148eb693ee20407214076bc65c14fc3" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file_length": 3146697, + "file_sha256": "1836d66ed0c70d4d592df2b8742705de84fd3a944786906750d5ab0c89c7703e", + "header_length": 168, + "length": 3145729, + "name": "x25519, 3145729 bytes", + "node": false, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 3145729", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 3145729, + "plaintext_sha256": "b53d83970dbc592f40694bb16415061e4e9e54594cc88e6450174724dead0eb8" + }, + { + "plaintext_length": 3145729, + "plaintext_sha256": "b53d83970dbc592f40694bb16415061e4e9e54594cc88e6450174724dead0eb8" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file_length": 200248, + "file_sha256": "4531ed548e805848902c9de9ff45d01a30d95d5ca5cf473a70c3fbb88cd83336", + "header_length": 168, + "length": 200000, + "name": "x25519, 200000 bytes in pieces", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + } + ], + "pieces": [ + 1, + 7, + 65535, + 65537, + 1000, + 3 + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop pieces", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 200000, + "plaintext_sha256": "8f9d1bf454d63cd9fc6edbe8f3f2331cc1f9b195c7ec90533717bf243ae966c7" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e2058323535313920794b6645792f414d5a3541644a7157335439597445425039494370306b425845456450736e3132344851340a5a48526c514a32574944613473626556556f716f755365396d45795956372f52345359412b6b7a337a6b340a2d3e20583235353139206172315037466f5a645a6649796d4f796e6b4f68326c6173356731724d5349554b65385154612f2b6443490a4f6f52336537514d58476b43725434334f4d2b766331793779664d6d73454774506e54712b6553475850490a2d3e205832353531392076724335614a363966645544394e7a4a6841494359374d376e4b5962376c616639356741447649795379630a6d63385147626d4648763341346a41496949335263514c414f67542b3870624a4550616e376268453237670a2d2d2d2046704469415658436a4f4f2b4c65544b643653676c332f417066414a744f684976507267754c6e6e6a72590a5c8bb961c627861a3dcf07155d657746a5283bdc1b4970cbaaff98d785939867938dff293e5c24d939c144e3468935b5d819614e7a9b4da15a429fa2fda916dd62f3917f87cb75176bdcca0e5c08b8a03a9175e55e9806abc664bd38faad1aebc960154215948d6139f24a2ed15a66c26b4e279617ca5d891e2cfeb44e70a297e43587857a0bf3ec6520f1c89328380dbeec3c4b44c8e4e8ce3044fb8b899e19f60fcac1c6c7b45ca0d9eb2d844e3d258231b7e9d9d65ef37fb3caa1ab6b08a7ae3eca5bc23422964ad6bb13a146142b31c94f69b06004872fe455a727c2aa1d6b05a2419291f29cdb15bfb16b45b3b2642d4cb61b48e3e0f122f4d3e343570541bf02c361d255ef5deffb81fcb3d857ee06b967c5b45e1a27eab21742a4e6bd060580ed9075262471923b474f72d8d4fad0c7a6fb71a1f70ec41201471fcb5dc704646fa53093ef9d8acc391ea1fd63105a570ad5fd006c3d7cec705b8be6bd4d29b20d471a8645870a94dee925ae96d6ebe20ae0df7f4f162dfcd69e3ed52bdd825e16c65720acfe35df0531d1f1f0b9ab4b72e40df22f60d432b9d62792ae5504b6d58df522d6b15fb670b6abf417006d3d7c00a0cde21af61e5e7e5cfe9f4eb8cc4f5ba4bfc940b4ed70757fd631d50d10e3bd6d5824857c018ce0e383542d9dfed5f88b2eae492bbdc94a4227e545a64c5f60e5320a24fd067203f590acefe4b6d282993c3131937293f69d531e28596fb662d1c1824f8cc3b7c952c1c02a06980db290bc6a24aff92a66e2690a39dfc387e33c290b686fff9a83cab8163b6f7fdd49c9c98bb62cc1cad065c4df2eb58a6de892c6ec04eca362ea8445ef0cf2bec4e34d6417907323dfc589459d8b62e995b1ecc41da50800a8c188430096ee839ebaa786f120fc11b0cf548012d38c413b1841c7a3aacefedb7933703ca5d62d665c69b91a247f157a08a38117c664d3ec3ed281d4671828936425e2379195ceccb1a1ae6bafaa6f6e80865c181410d7c40e7154e82bdbcf1cb85ef4c1fa2b44fe4e8e544f00f1c74d96497b320bb314923ff661e8a7c2184f2b293df4a7f645b036ef255faf80b22fc02e23fcd5913d7d4602ec2e7e36080e5a827822c1ca081bd232fc9bd6df14e4d0e82b5d571d4f7676cba54e7a563da887700c2c6264eec15ba7c4648502e894cf0d88182a079027f34e5e9f11cd5263e4119a582c536fa8a30ee10e6f81f2bcc60086c689d5bf176e19ed3f3401b4dbf80b8e753f974c38aa5e4d511dfd4ec1f2e125c27a6b5f363a0c3e2dbf441029fbaa2c80fb8eb3a9c42613ac13430b537b6509fe84ad7fc2d060771f467273b05f77915d4ce6f3847197530d3e2eb3201f9ec37278473ea3d8017833a399ea1b15ea57e4480c67c71c677611152840539b2d70ee454d8d03d118394dfb5ffd4cb4f4cfcd8c513cdf8d1e3f26", + "file_length": 1396, + "file_sha256": "afcc5f2461540dd3a77121465fcf474e428dda215302c3809c9d031fad191e42", + "header_length": 364, + "length": 1000, + "name": "x25519, three recipients", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-17SU4WVNPGVFF5VNKTNFVJY4UZW4LV63J3AEHLZRXLFXJT4SDXQDQ9W0T40" + }, + { + "x25519": "AGE-SECRET-KEY-1JSZD3A64TTDCF6L8AVDYN534PU0PN3K57TK7Y3LHU2NX8WPMAH7S6065FV" + }, + { + "x25519": "AGE-SECRET-KEY-1TC67TXSV09XKQWK4LAEYCMQPH00WE8J5DCPG8FY3ZC7CWT97XPJSJ2F2E9" + }, + { + "access": [ + "9404d8f7555adb84ebe7eb1a49d2350f1e19c6d4f2ede247f7e2a663b83bedfd" + ], + "slots": 0 + }, + { + "access": [ + "f43957326143129a32765cd2c912bc13abf66a328f737f8866fa4d25d60d301a", + "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + ], + "slots": 0 + }, + { + "payload": "f43957326143129a32765cd2c912bc13abf66a328f737f8866fa4d25d60d301a" + }, + { + "access": [ + "f43957326143129a32765cd2c912bc13abf66a328f737f8866fa4d25d60d301a" + ], + "slots": 16 + } + ], + "recipients": [ + { + "x25519": "age1xgx98k05lcdhx8y634jmzz6xvsdr7fvq2ge3x5dl72sz0rkjpg8qfjsaz9" + }, + { + "x25519": "age1vyfuvu7gnd3l02gnnezlv56xwag762j74dtpf9wcty2md4ynre2qdkx0a5" + }, + { + "x25519": "age1dgdhy7gef3v44j8tfvlhfywmnp3aumhsy9yh9dg5we5a87vgpeksw23422" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 3 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "agewrap: PAYLOAD_AGE has 3 stanzas, want exactly one X25519 stanza: ERR_POLICY_STRUCTURE_MISMATCH", + "time_1000": "agewrap: OUTER_TIME_AGE has 3 stanzas, want exactly one tlock stanza: ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop three", + "stanzas": [ + "X25519", + "X25519", + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 1000, + "plaintext_sha256": "5097e7d587352f5097062ae679f37bda5802d9f875aba14c8cb4d1a188ada179" + }, + { + "plaintext_length": 1000, + "plaintext_sha256": "5097e7d587352f5097062ae679f37bda5802d9f875aba14c8cb4d1a188ada179" + }, + { + "plaintext_length": 1000, + "plaintext_sha256": "5097e7d587352f5097062ae679f37bda5802d9f875aba14c8cb4d1a188ada179" + }, + { + "plaintext_length": 1000, + "plaintext_sha256": "5097e7d587352f5097062ae679f37bda5802d9f875aba14c8cb4d1a188ada179" + }, + { + "plaintext_length": 1000, + "plaintext_sha256": "5097e7d587352f5097062ae679f37bda5802d9f875aba14c8cb4d1a188ada179" + }, + { + "error": "agewrap: PAYLOAD_AGE has 3 stanzas, want exactly one X25519 stanza: ERR_POLICY_STRUCTURE_MISMATCH" + }, + { + "error": "agewrap: INNER_ACCESS_AGE has 3 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e2058323535313920336644484c744e413075673859444a562b33577668514f3275507243687074772f796741687a366941774d0a506e55686169547638624e5378596e54724a4f3164393056674c382b436270376e4951444c3548425234450a2d3e2058323535313920644e6c7052677773444d674a756a764b6c485870645a6177394a48456b523165715a4e4c36596e564a6b770a5479492f597075354e4e6f6f476351315a33696973322b4b4f6649756e4451574863413339346f68566e6f0a2d3e20583235353139206259483959616d45554c3069664f546e5765683952666d766968393073712b66456c674b585168484446410a744d7846613464627852324a383577774d392b47687744453334784a4e4f716b696f3234787562366f59490a2d3e20583235353139207a4f5230685278524374464a305471356b504d6d6c6b73777176654652486e6c47786c79426870363631630a6e45337434592f78362b325767354c753147467778663850775432524c564c374235517a6e4a766f776e490a2d3e205832353531392071766779734d5648334b6f6574336556716d666b6253326163586b387741385165667642484c4c487051410a69694a5274647237646b5253464d7335674e6a486b565569744c624e6b4e564f684d616664324271427a730a2d3e20583235353139204f6a542b567663656d612f4571596a6838526333722f73415071616d525a71574c3833684a652b486b58670a41456769687a42505649567035444d6a4e4976444d4b46725132753765476f375a674c4b4c3671414441380a2d3e2058323535313920766c6d56474341395672456d333975564b757858506845636162672b587a6b5036363968687277326178510a453253533259745967474a384c4f67766a353378614e616579586375697a6f2f74704a39517241377a74490a2d3e20583235353139205a7859717351726b486e303367344a674376507a70543165464274424a2f637256383566515459744254490a64646b426a706c35592b4e654e6b71755358715a70307143766172704a543933707970304f4476324751670a2d3e205832353531392077746c6c763561594470477254727a4a2f55375039553863794a65716c37755a36397631417434763833590a6d347969456c385639785055397442414f576b494b6470736a545a696743652b337254482b6a4c704246340a2d3e205832353531392054353070795a6d43513572442b35332f555376794e4a7944385177666e69307046666a466f4157745968490a49493963334b7245644332386d492f30376e5234766a6951667a337072474279784d3742417471636d4f590a2d3e2058323535313920417047446e4a5233554c4b4c4b463634566e4a763575776441716a722f43627a37446d2b5935796c3052490a463156676269495745534a48387a7867596644317a616c544b7964366c4d6e6f564f54484f5675645a35630a2d3e20583235353139204f6236366f4670626a5576577756644270765945625577307571617136774a32764867774b494a697833510a4a496f5a7471434777664e4f58306158773470723347344472534554664a504b44426c54676736383157670a2d3e2058323535313920744d326c65694a57625537724350327438437764645543334c5a50704d7131704e77692f616c5067466a300a30634b7438325137317a486134516c58496c694b45433373324b4a6d754d694e2b325144473645466f73340a2d3e205832353531392044426c415551707a304a74725558766f6a58344f61335462794c6b6167662b463235714f336d36756542450a4762487a764363746f6257736c70333051737847686c6630784b672f6e2f654e5a5842436e6a644e6943770a2d3e2058323535313920454a33476d686c6f68673650755451764141514d517a2b365a6d4a4f71374947545935456f797a722b7a670a524c53746d4f6979376e71534c5831495878715265443449744a516261484b557551464f6e4c30746354670a2d3e20583235353139204974346f75316a36623931663272714c734131666255476436493056386c33476e4537494448445138424d0a57566c4c496c524c76344a48697a52724f3473575a30784b56736d59376939554648727950792f6d436a4d0a2d2d2d204339484a5a666f62384565776a6953556c344d4b376a5a444b39466b633766364634524c656c6a6738596b0a998472d7fc8e120743f48cf909c7c7765b3bf3d3265538bf65e8f539065803fa34125e4fe0895aabfa466a097a458de45049886934b0b1ff6b95dbc0658689699900133c2b755c89ae89ca576d96a2350a6768bed41a5e2d5eefcc24303422f79ff1fbf4bbb4cdcff1a2cca04dd811a58eef1be052c36cc2d64c9560beb12161c8aeabeb7708d5", + "file_length": 1773, + "file_sha256": "5ee91eba65a63edf157688ab5af32c2882a185c3967029278b871c2627e6926f", + "header_length": 1638, + "length": 103, + "name": "x25519, sixteen recipients", + "node": true, + "openers": [ + { + "access": [ + "9340c7b0566c04006baae959b02a535f298002eeeaf94c54856420beb507a6e5" + ], + "slots": 16 + }, + { + "access": [ + "fcf748ddef5bfa61e818da9c317484c3ef930935cdb1fd185b2d8b2eb082bba1" + ], + "slots": 16 + }, + { + "access": [ + "88b74501dd09d3f257a407ccfe6925f69b2ebf0add1f571af9560dd5520e27d8" + ], + "slots": 16 + }, + { + "access": [ + "380fd8b766b317ec6c228b7e3ed0cd663b6231e8691e5751807d9a9d420a31ab", + "0b3fc33a00d3ac0f1755ac7c93cd8eca9ea61e9a6cbee0240c5973dedbe9f681" + ], + "slots": 16 + }, + { + "access": [ + "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + ], + "slots": 16 + }, + { + "access": [ + "a0e1e5a4a48cd94a50ecf785a3a2f2804a6eecc719830e8822d6c40b33111bdc" + ], + "slots": 0 + } + ], + "recipients": [ + { + "x25519": "age1g6k265aru5r9m5d5svq5n7fesuglp59srk20tae6snwkw8mmdg7sg5exr5" + }, + { + "x25519": "age1v62lgqhqnm89f2ej97squ4q6ny9785lzw4hxyxlk6hlds9n99pssu0rypn" + }, + { + "x25519": "age1ndwvt5tj7x02m399afx8ujwvmzzj3rxpgrvaam9veczfydvvxf2srz8u5r" + }, + { + "x25519": "age1t4s23nhehjqzf3kk72pgq39n3m0uu39y4zv6x0nqam7em9cg2smsdq0ng5" + }, + { + "x25519": "age1dfqtgsyf259qm827xe2a3rdczzae27pkr87ywd8jcsk0mhzwashsnjcvrc" + }, + { + "x25519": "age1zz2p5yrkkgnfh6pqcktlnuauvs3gkttw9xjm8szlary53756uamsj7485u" + }, + { + "x25519": "age129pr99cslrpuzq64qgqze29pjweymsrcf5e0tqdmwp6nmwu0yqpsr3rz96" + }, + { + "x25519": "age1tgt08kc0fxvfhhdxdw8vg7522yt4t6pd6velzucg5pznu7a2fgaq2p39gv" + }, + { + "x25519": "age1n8c3z78uy2kxdgtn4d802wqkgy2rc9r6z30xtgc4xrtcsaky64esrwc5ty" + }, + { + "x25519": "age1ht3jpydx4duyuugapcjc0mfnzmpw5fjk3hy5t7u7xvm2xj849ahs06swce" + }, + { + "x25519": "age13xs8n7fueqpxhrfpvyy2sv55hm779cznvl6f754e73jxjkx94ygs4fwvep" + }, + { + "x25519": "age1qhn4dev8umj9lhfwf3yy0nhv2h8qhlvrzhd7klrtm9k3fe9pe3vsvglekg" + }, + { + "x25519": "age1dd5c9vl9lmfkm9z78ha40whqv3s6zvundckdjyzwhpvuu90ale6q0j40p3" + }, + { + "x25519": "age1wlk70qxapj948unec08zftyw95mexp9qt9gv3525gnzshk2mpyusdkkms4" + }, + { + "x25519": "age1kkgnqlar4zs5lmrau6l9ejr4fq0kptv9q9hejgmnhx68hk4hpg8smajzqn" + }, + { + "x25519": "age19qy2ahwgstj6ql2r527kw9xg47wzcftlv5r37xpshzlk9vpeveeqxgc3ds" + } + ], + "rules": { + "access_0": "ok", + "access_16": "ok", + "payload": "agewrap: PAYLOAD_AGE has 16 stanzas, want exactly one X25519 stanza: ERR_POLICY_STRUCTURE_MISMATCH", + "time_1000": "agewrap: OUTER_TIME_AGE has 16 stanzas, want exactly one tlock stanza: ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop sixteen", + "stanzas": [ + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + }, + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + }, + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + }, + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + }, + { + "error": "agewrap: no supplied identity is a recipient of INNER_ACCESS_AGE: ERR_ACCESS_INVALID" + }, + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20746c6f636b203130303020353264623962613730653063633066366561663738303364643037343437613166353437373733356664336636363137393262613934363030633834653937310a7552476e7a726532464852735774727936305741664c47504267312b4748344d4348352f575938416f2f6f75452b3553794862632b3052386d5533696c544d4a0a44734855677345622f314d30442b5963426f442f47634a674d684b386f34582b51413541566b7a2f6e74422b705574442b4461553434376d76496361362b33750a33735544622b3636744336486b42496c67624a614f4e5a6c5353704e45474679734d5a3453435063755a510a2d2d2d205a6f6f3458424e61675575466479795063426b6d36674b6a74774f444265686a4250306454626b52717a380af1614f1418fda4861875f20349a9a95b817f166ebfb21ca6097ff0772ef2598f62885e55f11727fa25ec57221d813fe2d812df78e98d6dbf1fab18872d1ae8af14ac91531b324286fa1d6f1037e751aae4437bd4ff36226ef466cff162eb062bda6a55206b711dadcaf9791014a667e922e9df8cdb69c422e67778f0fee63d65c52c634cd04147", + "file_length": 458, + "file_sha256": "da18fefdad2ea4ef077396d9aa7d9ced0aa8aafebbb5a1535a2c3c71449920b0", + "header_length": 323, + "length": 103, + "name": "tlock, round 1000", + "node": true, + "openers": [ + { + "release": 1000, + "tlock": 1000 + }, + { + "release": 1001, + "tlock": 1001 + } + ], + "recipients": [ + { + "tlock": 1000 + } + ], + "rules": { + "access_0": "agewrap: INNER_ACCESS_AGE stanza 0 has type \"tlock\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "agewrap: PAYLOAD_AGE stanza type \"tlock\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "time_1000": "ok" + }, + "seed": "interop tlock", + "stanzas": [ + "tlock" + ], + "verdicts": [ + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + }, + { + "error": "agewrap: tlock stanza round \"1000\", DateKey round 1001: ERR_ROUND_MISMATCH" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20746c6f636b203130303020353264623962613730653063633066366561663738303364643037343437613166353437373733356664336636363137393262613934363030633834653937310a6d645332715a415a4266655635504841396f726d4451526953587646526e767864666562486a414b6c58334a31585167737077323879614c4768447750696e6a0a4130776d4f39534347715665427147326c71306a4c316e2f6d652f704b7432735177307a367048554f6d3767315655563070636137354551637748584c7254660a566c4d6b37314a486d36704e747649395334554878364b4d50576455314355322f497269726f70546d78770a2d2d2d204d4d334a444c526171324e6a6c4251536375376d6e7044306c41556c52307a425a64324d536b47666e484d0a88e68f7146e86076f5c0b2781d0a12a98c53b7501f2b96d7ab213cfb71fb59c0386ef681dad33e9c2462e8d1d9c31d21c2e4b15069afb7efc83d96fbf409bc4be53a42da83ba6d08f99fe8d6caf19e502ff135f11d17a4e941b821e7aee358598e307b90246c105fcb8f0aae3502fda86bf83dccd3d5b38c0b9ad5cbaf439cc5aa78e705b95b451a675c34ce16a319ae555a6e403861269b8fe085002034d8aafabdc88c63f941db7a3c2ab8ff29e40e9c150cee264d1170af5ae5733dffa82578ad2b4626d422ff958eb6fadd9ddb8597bec3b329a730f22d04f2ecd64bc3f015378412343ab3b9e74f8cde7d66e7164c575b0192d3b895170495f75a17c01798752081ca121689488346063285c10589b04af0fabf826db66e29db6097b8d75583b1c1cb8fc6e0fdde10dc1ed93968b99b9f7834044a726b90b6c855d8ee8e59bb7bfb512a5769f2f91eb1104cbdaaddb9638fe40d8de72c7067ce8df05e95e4a63480b8bcbd0d4046cf1fbf59db9dfe48d08dea4e30bc9668baec4932cb7c2a2cd9593b72519c33e6f3663100733e1ff3f6e7706753f89814a7d46d4cfd18bb9ec0279f89c133daaf81638ee442b88f9724c70541248a630db52f1ae1cb039b855462593c89d12628c04f48146b5b0ac8149348b6bd09693be16fb5e27cede953ef1c3a32711fc49c63d8d9645fa5cc4d893ce87dfe23b7d8f7a80cb1f2a6724400789d4607c3e04879b00731fd3ef315cd8de0d0962ef09218dc93c7fa3d17fe1d05f8a0e65a1d5ec59b6959e55ff39a2256bdf86276de6e5d231bd4f24d481616e860ccacf606a18c2319446bac08d5815f77de49f537ac6def4aaba0f4053c3b5ecd31c0966a3304fbe50f39a512950cb739f9543259fa93fccc47413e9d6d8380e3daf13ffa7249b82934473701c09810d823cd19b99d44fb8d5f4d292f2a0624ebf9a5d26dd93f3a0f792fa92256cde02c3e25898b5581b41a72cc759f9f519c8316b875ebbd9883fa7c7691fb2a7216d863f89e972c98cb361d9f86846162e7961dbb34fce9ae957615582d33ec3a34541b2cecb13eb822a20f112cc803c6fbcbd0262580cab3d807f57aa2532ddb5b65fb4b3cb9bd57e2e1aa07d02720978c2ee8d1e51d077762bf68604164b95510ffc68b71150fdc386933fe88494a165c41551e3c03110d670e9d270f0558516b9b9cab5d8a40547571d3b9f14005b761001042ce9271dcdd59eb6ee965d3b488d73ddefdfb692be8bc80cef5cb2b30e39b7484db085e4701655e1107862902487b1d0fe53f18b3bcf8f5968f8c137987240e97ffcaaa72095bcb200103314a1cb9ebf238be4834133c1a1363c0e10846695d7815ec93252db02786e7d7e181b73598d5b5cb684fcfcf0098c852b2f1a952a2b4e3bde647f306e5452552178b4e58046cad1a115c125860e87f90793065f2c6515f6829f3a942ce25dd834e52ba350ff21ca1b97df28d6ea9950b3d894d9b3a8556b335e4cd1dcde77ee5551ef0ce104a776c7dbe4b8bd14351d0e3705c99d3474b8fcaa3501d897899c7a0415c7f5c936ed8752e0b3c77253677294c7ee2bc6c1a5b0e13c783890136385fad0a937f5694c60722391cd3d3b87270218438b82a1edea66c66d54dcc7be52ac327acfa2053ed928ec1914ec1b5ecf92d66db4e56fbe82d6ac4a6949efaf8144d8bfaa9813d42d2265de56b941e57b91cbdd790a4a79cf7964c2c5e28c1be4b11d179e6d15cf1594b8ea559a58348bfcc5e17500bb6fcf7b729527c32e8f2e57269d59f25d7220e44b10bca9158e44887d37e78634298f63262d2bfe9d2d068f39f6e062f219f19487edcbcac32d2bcc07fd549eab8c4e066ff61ffc78a8720ca6545ad2e2c5a08412c2127bfd4cf07834bcf1c56c4e4c4ccd0bf24b955b45f45dcb7a8971457b2d5750db6a4a556d11f146d0988483216ba1ebd051036f63b75afa3b66b915fbad8099f4f6c8a9e95915e0518da4c97bd4e5c6291cab4353b3682e01562d2ea9a3f55d623a8d5ba5c2ce6d0dedac74093e66e2910e6f61005085a2063142ad603e42a721d714607366c162bac3743915148a54333e33ffb1624d870717bede8096d37c46765bbb5fe070a92e5c14f37e55a839021390f24b15ebdd9ca98c850942bbae579a0fe67fd8c48bc491b0bdc410ec5e95447d3b11061260be2749df385b6f2fa7b7f562130520fccfa1d5e691429eec58608ac7123e2b57cd7b8492066e57b0633dd371c52245bd01acc90be129dfe07bbb3ea553ef1d71e8db4bad57a06844e5e5d2eab49e8496369c615e32d849f52c3c6890d5ccdae17771e19fefe3cf23b34e4ab33013f8f78b00c660348e25757bf8404eff2269864a60927c57a6b0950af91bdcc43774c50eb4d4db1584d305ba64625a1d7792f91c5858a499dfbdffd5428a0d655a321e4a96de8ac5603b4fe83d3d8fd21236896ec52a2ec3c7356785967b08e811ffcb2070a1bd847fc681f9b2a3b306eba1d2631b7eb490ee96cbcb9516c535b763203ad261460e61dc222", + "file_length": 2128, + "file_sha256": "f56fa000d865aebcc5600abfa41ec02c793273f533257057c9300ef553fafc74", + "header_length": 323, + "inner": { + "length": 103, + "recipients": [ + { + "x25519": "age1g6k265aru5r9m5d5svq5n7fesuglp59srk20tae6snwkw8mmdg7sg5exr5" + }, + { + "x25519": "age1v62lgqhqnm89f2ej97squ4q6ny9785lzw4hxyxlk6hlds9n99pssu0rypn" + }, + { + "x25519": "age1ndwvt5tj7x02m399afx8ujwvmzzj3rxpgrvaam9veczfydvvxf2srz8u5r" + }, + { + "x25519": "age1t4s23nhehjqzf3kk72pgq39n3m0uu39y4zv6x0nqam7em9cg2smsdq0ng5" + }, + { + "x25519": "age1dfqtgsyf259qm827xe2a3rdczzae27pkr87ywd8jcsk0mhzwashsnjcvrc" + }, + { + "x25519": "age1zz2p5yrkkgnfh6pqcktlnuauvs3gkttw9xjm8szlary53756uamsj7485u" + }, + { + "x25519": "age129pr99cslrpuzq64qgqze29pjweymsrcf5e0tqdmwp6nmwu0yqpsr3rz96" + }, + { + "x25519": "age1tgt08kc0fxvfhhdxdw8vg7522yt4t6pd6velzucg5pznu7a2fgaq2p39gv" + }, + { + "x25519": "age1n8c3z78uy2kxdgtn4d802wqkgy2rc9r6z30xtgc4xrtcsaky64esrwc5ty" + }, + { + "x25519": "age1ht3jpydx4duyuugapcjc0mfnzmpw5fjk3hy5t7u7xvm2xj849ahs06swce" + }, + { + "x25519": "age13xs8n7fueqpxhrfpvyy2sv55hm779cznvl6f754e73jxjkx94ygs4fwvep" + }, + { + "x25519": "age1qhn4dev8umj9lhfwf3yy0nhv2h8qhlvrzhd7klrtm9k3fe9pe3vsvglekg" + }, + { + "x25519": "age1dd5c9vl9lmfkm9z78ha40whqv3s6zvundckdjyzwhpvuu90ale6q0j40p3" + }, + { + "x25519": "age1wlk70qxapj948unec08zftyw95mexp9qt9gv3525gnzshk2mpyusdkkms4" + }, + { + "x25519": "age1kkgnqlar4zs5lmrau6l9ejr4fq0kptv9q9hejgmnhx68hk4hpg8smajzqn" + }, + { + "x25519": "age19qy2ahwgstj6ql2r527kw9xg47wzcftlv5r37xpshzlk9vpeveeqxgc3ds" + } + ], + "seed": "interop inner access" + }, + "name": "tlock over sixteen x25519, as SEALED_CONTROL", + "node": false, + "openers": [ + { + "release": 1000, + "then": { + "access": [ + "64673b44a140059fd41682b28cf75edfe8a803a6e41f3a3d45771b899061b3bc" + ], + "slots": 16 + }, + "tlock": 1000 + }, + { + "release": 1000, + "then": { + "access": [ + "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + ], + "slots": 16 + }, + "tlock": 1000 + } + ], + "recipients": [ + { + "tlock": 1000 + } + ], + "rules": { + "access_0": "agewrap: INNER_ACCESS_AGE stanza 0 has type \"tlock\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "agewrap: PAYLOAD_AGE stanza type \"tlock\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "time_1000": "ok" + }, + "seed": "interop sealed control", + "stanzas": [ + "tlock" + ], + "verdicts": [ + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + }, + { + "error": "agewrap: no supplied identity is a recipient of INNER_ACCESS_AGE: ERR_ACCESS_INVALID" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20736372797074204b726e6732617434643171707678785a42646b6c2b772031300a5a574f48326f707862446b6c3268732b46426b4371584a676e51775752397638663063307366347930796f0a2d2d2d203464726851484b4f5173615543584b524a6a6b765472393067366931315a736e7458434863616172787a380a05dcbb328a3ed8355dafb0e446d87f41bc456c2a8c99f2ef36a193f66ee4ae1e705fe174ce52a5936cea5d58339c9eae6bbb96f89f3352e3057a125c179cd6a40aebc07c8c627ebc08119182254fcf792fc037d5338d0f982e3f3372c31b366b368630db66917374ecc04fe366c80dade412d36451ea119cdef54a2d3901f65b0a34c94fa2918ab7ad5250a09bf589e93802933d666e83b2", + "file_length": 302, + "file_sha256": "9ffca1211ea37615c181c6b7298617e23bb533aedb131a7b466a252b18b322ab", + "header_length": 150, + "length": 120, + "name": "scrypt, work factor 10", + "node": true, + "openers": [ + { + "max_work_factor": 16, + "scrypt": "una contraseña larga de prueba" + }, + { + "max_work_factor": 16, + "scrypt": "otra contraseña" + }, + { + "max_work_factor": 9, + "scrypt": "una contraseña larga de prueba" + } + ], + "recipients": [ + { + "scrypt": "una contraseña larga de prueba", + "work_factor": 10 + } + ], + "rules": { + "access_0": "agewrap: INNER_ACCESS_AGE stanza 0 has type \"scrypt\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "agewrap: PAYLOAD_AGE stanza type \"scrypt\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"scrypt\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop scrypt 10", + "stanzas": [ + "scrypt" + ], + "verdicts": [ + { + "plaintext_length": 120, + "plaintext_sha256": "1f80156a804cb7862ad113e8200e9d74499723e7c7854d5f48776d3148e09656" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block: incorrect passphrase" + }, + { + "error": "scrypt work factor too large: 10" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20736372797074203976774b4450536a49317074504767722b50767a69772031360a594c4f64613736526c41566353766952504b5a673741557a49526372546c6f6379343364412b644b69736b0a2d2d2d20444b4f4e796b3675396872394b675670714676776e724c477562712b3776715564423941744136643144730a01218d5cc02a7644cc99fb77b4db3452d776d7f02aabe72e869babed30ce3a7a55d8763a84a1be19205b889aa67bf8ba21f43d14bdb259825092c8709307819423a45edf0b5f94bf2615fef492e7878dfe3ac50cd1600c3b1b3d78a68b4e2e0ce2a5aa0c60b1bac7407c1a39f5486e7f7203206965e5d3caa56ccff4401e97d705109c813816cf9e34eefa983f503812180bfa536023dc5e", + "file_length": 302, + "file_sha256": "946428b8ab69986b9d35109c84e5892fed73271ea3de4144197b3a5cae6340ae", + "header_length": 150, + "length": 120, + "name": "scrypt, work factor 16", + "node": false, + "openers": [ + { + "max_work_factor": 16, + "scrypt": "una contraseña larga de prueba" + }, + { + "max_work_factor": 16, + "scrypt": "otra contraseña" + }, + { + "max_work_factor": 15, + "scrypt": "una contraseña larga de prueba" + } + ], + "recipients": [ + { + "scrypt": "una contraseña larga de prueba", + "work_factor": 16 + } + ], + "rules": { + "access_0": "agewrap: INNER_ACCESS_AGE stanza 0 has type \"scrypt\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "agewrap: PAYLOAD_AGE stanza type \"scrypt\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"scrypt\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop scrypt 16", + "stanzas": [ + "scrypt" + ], + "verdicts": [ + { + "plaintext_length": 120, + "plaintext_sha256": "1f80156a804cb7862ad113e8200e9d74499723e7c7854d5f48776d3148e09656" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block: incorrect passphrase" + }, + { + "error": "scrypt work factor too large: 16" + } + ] + } + ], + "source": "c531e936fa8188a4aab01575607cc85d4f5d4fa4" +} +'''; diff --git a/test/vectors/age_interop.json b/test/vectors/age_interop.json new file mode 100644 index 0000000..63e9e4f --- /dev/null +++ b/test/vectors/age_interop.json @@ -0,0 +1,916 @@ +{ + "description": "Age files that datekeys-dart writes with SeededRandomSource from the recipes of test/age_interop_support.dart, opened by filippo.io/age v1.3.2 and agewrap (tool/age_interop_go_verdicts.go): the length and the SHA-256 of each file, the file when small, the length of its header, its stanzas, the stanza rules of agewrap on them, and the verdict of Go with each opener, the length and the SHA-256 of the plaintext or the text of the error. The plaintext of n bytes has (31·i + 7) mod 256 as byte i. A sample marked node false is left out compiled to JavaScript.", + "go": "go1.26.8", + "samples": [ + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e205832353531392030527832757934394866634955587254497575396f554b65434d6b4265472b337a456465366a476d4f316b0a422b345633417363762f366d4b5a7042786a6f73314d51457370584b567847722f6d6c394c7331414d70510a2d2d2d203758564e36332b5a58387569424331574861736131365969377773374b6c7449516753734b466e2b6a7a550a4a2cadadd212d7592451141f53c4f49226b3efbd1b7e52a62ff725bb6cbaa87f", + "file_length": 200, + "file_sha256": "131e8047bf7084b2910809eb07459f902a0f365852577ca7cd1aea79d9802248", + "header_length": 168, + "length": 0, + "name": "x25519, 0 bytes", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 0", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 0, + "plaintext_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "plaintext_length": 0, + "plaintext_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20583235353139206d33483436423637554a4c546a502f64693254524c4d373367396f63547870694f5a53683442634b4b6a590a69744b6e354c4f417a756e374a524a724c6465476c354353757a6c6c6e614d717139552b6d6b2b327069770a2d2d2d2079794768717850677835623553467251722b39467362676a6974433958324d2b3663564f6856666e5761490aea2e95595f98cb5076cf15c144c3da271d6b9cb151fb8da19e06d79d0b1276eb8c", + "file_length": 201, + "file_sha256": "71d356daf8376a1fdfa0a0c9f55bce42e231c3755c5552364919fbe81cfc2724", + "header_length": 168, + "length": 1, + "name": "x25519, 1 bytes", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 1", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 1, + "plaintext_sha256": "ca358758f6d27e6cf45272937977a748fd88391db679ceda7dc7bf1f005ee879" + }, + { + "plaintext_length": 1, + "plaintext_sha256": "ca358758f6d27e6cf45272937977a748fd88391db679ceda7dc7bf1f005ee879" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file_length": 65735, + "file_sha256": "96f6986395b072f8473bf6fd8834dc4210ca219d714a4db890ff53a046fa4c0b", + "header_length": 168, + "length": 65535, + "name": "x25519, 65535 bytes", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 65535", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 65535, + "plaintext_sha256": "91d0a03af0efeeb5568bbdcf2bd7fe1c9d932c4d22db3643c7586c1bd1afbeb1" + }, + { + "plaintext_length": 65535, + "plaintext_sha256": "91d0a03af0efeeb5568bbdcf2bd7fe1c9d932c4d22db3643c7586c1bd1afbeb1" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file_length": 65736, + "file_sha256": "16a504de46caa5293bd8d99a7ac20bf9bfe7646487f02486025f981a492b7a30", + "header_length": 168, + "length": 65536, + "name": "x25519, 65536 bytes", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 65536", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 65536, + "plaintext_sha256": "ef4636928161808e87035fa51983821677527ccd9661991c5d0126a778b2268a" + }, + { + "plaintext_length": 65536, + "plaintext_sha256": "ef4636928161808e87035fa51983821677527ccd9661991c5d0126a778b2268a" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file_length": 65753, + "file_sha256": "87cd1b28bdc0733f7c85ac8709bb7ce0f99edbbe8a0b9365fb1dc9f31a4631d4", + "header_length": 168, + "length": 65537, + "name": "x25519, 65537 bytes", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 65537", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 65537, + "plaintext_sha256": "74f3260f4a9adaf7271c910ba2d111dbae7a176afb487e1b7f655897eadf1093" + }, + { + "plaintext_length": 65537, + "plaintext_sha256": "74f3260f4a9adaf7271c910ba2d111dbae7a176afb487e1b7f655897eadf1093" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file_length": 131288, + "file_sha256": "9b85f99fe79b22da7c501f855b32650349c9dd1369dee7444fc9b4297df86df2", + "header_length": 168, + "length": 131072, + "name": "x25519, 131072 bytes", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 131072", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 131072, + "plaintext_sha256": "2af5d3dffc8442daccee445639ed726c2148eb693ee20407214076bc65c14fc3" + }, + { + "plaintext_length": 131072, + "plaintext_sha256": "2af5d3dffc8442daccee445639ed726c2148eb693ee20407214076bc65c14fc3" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file_length": 3146697, + "file_sha256": "1836d66ed0c70d4d592df2b8742705de84fd3a944786906750d5ab0c89c7703e", + "header_length": 168, + "length": 3145729, + "name": "x25519, 3145729 bytes", + "node": false, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + }, + { + "payload": "fa7e874109e9afdb6e43827fe088d9e7f0c93796799247d8b6d2893c669785af" + }, + { + "x25519": "AGE-SECRET-KEY-1ZVG0U3FK3XJDL5WJL0Q6MLAQ98U4J4DYJ5CXZ97Z3N3YHXVHYN4QGSCL96" + }, + { + "payload": "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + } + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop x25519 3145729", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 3145729, + "plaintext_sha256": "b53d83970dbc592f40694bb16415061e4e9e54594cc88e6450174724dead0eb8" + }, + { + "plaintext_length": 3145729, + "plaintext_sha256": "b53d83970dbc592f40694bb16415061e4e9e54594cc88e6450174724dead0eb8" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block" + }, + { + "error": "agewrap: PAYLOAD_AGE is not encrypted to this control's R_PAYLOAD: ERR_INTEGRITY" + } + ] + }, + { + "file_length": 200248, + "file_sha256": "4531ed548e805848902c9de9ff45d01a30d95d5ca5cf473a70c3fbb88cd83336", + "header_length": 168, + "length": 200000, + "name": "x25519, 200000 bytes in pieces", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-1LFLGWSGFAXHAKMJRSFL7PZXEULCVJDUK0XFY0K9K62YNCE5HSKHSNWUP5A" + } + ], + "pieces": [ + 1, + 7, + 65535, + 65537, + 1000, + 3 + ], + "recipients": [ + { + "x25519": "age175clzdk73v0mzqunzc23aecpz67xj5a7drqgxyep7czh7wuln5us49dyyx" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "ok", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"X25519\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop pieces", + "stanzas": [ + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 200000, + "plaintext_sha256": "8f9d1bf454d63cd9fc6edbe8f3f2331cc1f9b195c7ec90533717bf243ae966c7" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e2058323535313920794b6645792f414d5a3541644a7157335439597445425039494370306b425845456450736e3132344851340a5a48526c514a32574944613473626556556f716f755365396d45795956372f52345359412b6b7a337a6b340a2d3e20583235353139206172315037466f5a645a6649796d4f796e6b4f68326c6173356731724d5349554b65385154612f2b6443490a4f6f52336537514d58476b43725434334f4d2b766331793779664d6d73454774506e54712b6553475850490a2d3e205832353531392076724335614a363966645544394e7a4a6841494359374d376e4b5962376c616639356741447649795379630a6d63385147626d4648763341346a41496949335263514c414f67542b3870624a4550616e376268453237670a2d2d2d2046704469415658436a4f4f2b4c65544b643653676c332f417066414a744f684976507267754c6e6e6a72590a5c8bb961c627861a3dcf07155d657746a5283bdc1b4970cbaaff98d785939867938dff293e5c24d939c144e3468935b5d819614e7a9b4da15a429fa2fda916dd62f3917f87cb75176bdcca0e5c08b8a03a9175e55e9806abc664bd38faad1aebc960154215948d6139f24a2ed15a66c26b4e279617ca5d891e2cfeb44e70a297e43587857a0bf3ec6520f1c89328380dbeec3c4b44c8e4e8ce3044fb8b899e19f60fcac1c6c7b45ca0d9eb2d844e3d258231b7e9d9d65ef37fb3caa1ab6b08a7ae3eca5bc23422964ad6bb13a146142b31c94f69b06004872fe455a727c2aa1d6b05a2419291f29cdb15bfb16b45b3b2642d4cb61b48e3e0f122f4d3e343570541bf02c361d255ef5deffb81fcb3d857ee06b967c5b45e1a27eab21742a4e6bd060580ed9075262471923b474f72d8d4fad0c7a6fb71a1f70ec41201471fcb5dc704646fa53093ef9d8acc391ea1fd63105a570ad5fd006c3d7cec705b8be6bd4d29b20d471a8645870a94dee925ae96d6ebe20ae0df7f4f162dfcd69e3ed52bdd825e16c65720acfe35df0531d1f1f0b9ab4b72e40df22f60d432b9d62792ae5504b6d58df522d6b15fb670b6abf417006d3d7c00a0cde21af61e5e7e5cfe9f4eb8cc4f5ba4bfc940b4ed70757fd631d50d10e3bd6d5824857c018ce0e383542d9dfed5f88b2eae492bbdc94a4227e545a64c5f60e5320a24fd067203f590acefe4b6d282993c3131937293f69d531e28596fb662d1c1824f8cc3b7c952c1c02a06980db290bc6a24aff92a66e2690a39dfc387e33c290b686fff9a83cab8163b6f7fdd49c9c98bb62cc1cad065c4df2eb58a6de892c6ec04eca362ea8445ef0cf2bec4e34d6417907323dfc589459d8b62e995b1ecc41da50800a8c188430096ee839ebaa786f120fc11b0cf548012d38c413b1841c7a3aacefedb7933703ca5d62d665c69b91a247f157a08a38117c664d3ec3ed281d4671828936425e2379195ceccb1a1ae6bafaa6f6e80865c181410d7c40e7154e82bdbcf1cb85ef4c1fa2b44fe4e8e544f00f1c74d96497b320bb314923ff661e8a7c2184f2b293df4a7f645b036ef255faf80b22fc02e23fcd5913d7d4602ec2e7e36080e5a827822c1ca081bd232fc9bd6df14e4d0e82b5d571d4f7676cba54e7a563da887700c2c6264eec15ba7c4648502e894cf0d88182a079027f34e5e9f11cd5263e4119a582c536fa8a30ee10e6f81f2bcc60086c689d5bf176e19ed3f3401b4dbf80b8e753f974c38aa5e4d511dfd4ec1f2e125c27a6b5f363a0c3e2dbf441029fbaa2c80fb8eb3a9c42613ac13430b537b6509fe84ad7fc2d060771f467273b05f77915d4ce6f3847197530d3e2eb3201f9ec37278473ea3d8017833a399ea1b15ea57e4480c67c71c677611152840539b2d70ee454d8d03d118394dfb5ffd4cb4f4cfcd8c513cdf8d1e3f26", + "file_length": 1396, + "file_sha256": "afcc5f2461540dd3a77121465fcf474e428dda215302c3809c9d031fad191e42", + "header_length": 364, + "length": 1000, + "name": "x25519, three recipients", + "node": true, + "openers": [ + { + "x25519": "AGE-SECRET-KEY-17SU4WVNPGVFF5VNKTNFVJY4UZW4LV63J3AEHLZRXLFXJT4SDXQDQ9W0T40" + }, + { + "x25519": "AGE-SECRET-KEY-1JSZD3A64TTDCF6L8AVDYN534PU0PN3K57TK7Y3LHU2NX8WPMAH7S6065FV" + }, + { + "x25519": "AGE-SECRET-KEY-1TC67TXSV09XKQWK4LAEYCMQPH00WE8J5DCPG8FY3ZC7CWT97XPJSJ2F2E9" + }, + { + "access": [ + "9404d8f7555adb84ebe7eb1a49d2350f1e19c6d4f2ede247f7e2a663b83bedfd" + ], + "slots": 0 + }, + { + "access": [ + "f43957326143129a32765cd2c912bc13abf66a328f737f8866fa4d25d60d301a", + "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + ], + "slots": 0 + }, + { + "payload": "f43957326143129a32765cd2c912bc13abf66a328f737f8866fa4d25d60d301a" + }, + { + "access": [ + "f43957326143129a32765cd2c912bc13abf66a328f737f8866fa4d25d60d301a" + ], + "slots": 16 + } + ], + "recipients": [ + { + "x25519": "age1xgx98k05lcdhx8y634jmzz6xvsdr7fvq2ge3x5dl72sz0rkjpg8qfjsaz9" + }, + { + "x25519": "age1vyfuvu7gnd3l02gnnezlv56xwag762j74dtpf9wcty2md4ynre2qdkx0a5" + }, + { + "x25519": "age1dgdhy7gef3v44j8tfvlhfywmnp3aumhsy9yh9dg5we5a87vgpeksw23422" + } + ], + "rules": { + "access_0": "ok", + "access_16": "agewrap: INNER_ACCESS_AGE has 3 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "agewrap: PAYLOAD_AGE has 3 stanzas, want exactly one X25519 stanza: ERR_POLICY_STRUCTURE_MISMATCH", + "time_1000": "agewrap: OUTER_TIME_AGE has 3 stanzas, want exactly one tlock stanza: ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop three", + "stanzas": [ + "X25519", + "X25519", + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 1000, + "plaintext_sha256": "5097e7d587352f5097062ae679f37bda5802d9f875aba14c8cb4d1a188ada179" + }, + { + "plaintext_length": 1000, + "plaintext_sha256": "5097e7d587352f5097062ae679f37bda5802d9f875aba14c8cb4d1a188ada179" + }, + { + "plaintext_length": 1000, + "plaintext_sha256": "5097e7d587352f5097062ae679f37bda5802d9f875aba14c8cb4d1a188ada179" + }, + { + "plaintext_length": 1000, + "plaintext_sha256": "5097e7d587352f5097062ae679f37bda5802d9f875aba14c8cb4d1a188ada179" + }, + { + "plaintext_length": 1000, + "plaintext_sha256": "5097e7d587352f5097062ae679f37bda5802d9f875aba14c8cb4d1a188ada179" + }, + { + "error": "agewrap: PAYLOAD_AGE has 3 stanzas, want exactly one X25519 stanza: ERR_POLICY_STRUCTURE_MISMATCH" + }, + { + "error": "agewrap: INNER_ACCESS_AGE has 3 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e2058323535313920336644484c744e413075673859444a562b33577668514f3275507243687074772f796741687a366941774d0a506e55686169547638624e5378596e54724a4f3164393056674c382b436270376e4951444c3548425234450a2d3e2058323535313920644e6c7052677773444d674a756a764b6c485870645a6177394a48456b523165715a4e4c36596e564a6b770a5479492f597075354e4e6f6f476351315a33696973322b4b4f6649756e4451574863413339346f68566e6f0a2d3e20583235353139206259483959616d45554c3069664f546e5765683952666d766968393073712b66456c674b585168484446410a744d7846613464627852324a383577774d392b47687744453334784a4e4f716b696f3234787562366f59490a2d3e20583235353139207a4f5230685278524374464a305471356b504d6d6c6b73777176654652486e6c47786c79426870363631630a6e45337434592f78362b325767354c753147467778663850775432524c564c374235517a6e4a766f776e490a2d3e205832353531392071766779734d5648334b6f6574336556716d666b6253326163586b387741385165667642484c4c487051410a69694a5274647237646b5253464d7335674e6a486b565569744c624e6b4e564f684d616664324271427a730a2d3e20583235353139204f6a542b567663656d612f4571596a6838526333722f73415071616d525a71574c3833684a652b486b58670a41456769687a42505649567035444d6a4e4976444d4b46725132753765476f375a674c4b4c3671414441380a2d3e2058323535313920766c6d56474341395672456d333975564b757858506845636162672b587a6b5036363968687277326178510a453253533259745967474a384c4f67766a353378614e616579586375697a6f2f74704a39517241377a74490a2d3e20583235353139205a7859717351726b486e303367344a674376507a70543165464274424a2f637256383566515459744254490a64646b426a706c35592b4e654e6b71755358715a70307143766172704a543933707970304f4476324751670a2d3e205832353531392077746c6c763561594470477254727a4a2f55375039553863794a65716c37755a36397631417434763833590a6d347969456c385639785055397442414f576b494b6470736a545a696743652b337254482b6a4c704246340a2d3e205832353531392054353070795a6d43513572442b35332f555376794e4a7944385177666e69307046666a466f4157745968490a49493963334b7245644332386d492f30376e5234766a6951667a337072474279784d3742417471636d4f590a2d3e2058323535313920417047446e4a5233554c4b4c4b463634566e4a763575776441716a722f43627a37446d2b5935796c3052490a463156676269495745534a48387a7867596644317a616c544b7964366c4d6e6f564f54484f5675645a35630a2d3e20583235353139204f6236366f4670626a5576577756644270765945625577307571617136774a32764867774b494a697833510a4a496f5a7471434777664e4f58306158773470723347344472534554664a504b44426c54676736383157670a2d3e2058323535313920744d326c65694a57625537724350327438437764645543334c5a50704d7131704e77692f616c5067466a300a30634b7438325137317a486134516c58496c694b45433373324b4a6d754d694e2b325144473645466f73340a2d3e205832353531392044426c415551707a304a74725558766f6a58344f61335462794c6b6167662b463235714f336d36756542450a4762487a764363746f6257736c70333051737847686c6630784b672f6e2f654e5a5842436e6a644e6943770a2d3e2058323535313920454a33476d686c6f68673650755451764141514d517a2b365a6d4a4f71374947545935456f797a722b7a670a524c53746d4f6979376e71534c5831495878715265443449744a516261484b557551464f6e4c30746354670a2d3e20583235353139204974346f75316a36623931663272714c734131666255476436493056386c33476e4537494448445138424d0a57566c4c496c524c76344a48697a52724f3473575a30784b56736d59376939554648727950792f6d436a4d0a2d2d2d204339484a5a666f62384565776a6953556c344d4b376a5a444b39466b633766364634524c656c6a6738596b0a998472d7fc8e120743f48cf909c7c7765b3bf3d3265538bf65e8f539065803fa34125e4fe0895aabfa466a097a458de45049886934b0b1ff6b95dbc0658689699900133c2b755c89ae89ca576d96a2350a6768bed41a5e2d5eefcc24303422f79ff1fbf4bbb4cdcff1a2cca04dd811a58eef1be052c36cc2d64c9560beb12161c8aeabeb7708d5", + "file_length": 1773, + "file_sha256": "5ee91eba65a63edf157688ab5af32c2882a185c3967029278b871c2627e6926f", + "header_length": 1638, + "length": 103, + "name": "x25519, sixteen recipients", + "node": true, + "openers": [ + { + "access": [ + "9340c7b0566c04006baae959b02a535f298002eeeaf94c54856420beb507a6e5" + ], + "slots": 16 + }, + { + "access": [ + "fcf748ddef5bfa61e818da9c317484c3ef930935cdb1fd185b2d8b2eb082bba1" + ], + "slots": 16 + }, + { + "access": [ + "88b74501dd09d3f257a407ccfe6925f69b2ebf0add1f571af9560dd5520e27d8" + ], + "slots": 16 + }, + { + "access": [ + "380fd8b766b317ec6c228b7e3ed0cd663b6231e8691e5751807d9a9d420a31ab", + "0b3fc33a00d3ac0f1755ac7c93cd8eca9ea61e9a6cbee0240c5973dedbe9f681" + ], + "slots": 16 + }, + { + "access": [ + "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + ], + "slots": 16 + }, + { + "access": [ + "a0e1e5a4a48cd94a50ecf785a3a2f2804a6eecc719830e8822d6c40b33111bdc" + ], + "slots": 0 + } + ], + "recipients": [ + { + "x25519": "age1g6k265aru5r9m5d5svq5n7fesuglp59srk20tae6snwkw8mmdg7sg5exr5" + }, + { + "x25519": "age1v62lgqhqnm89f2ej97squ4q6ny9785lzw4hxyxlk6hlds9n99pssu0rypn" + }, + { + "x25519": "age1ndwvt5tj7x02m399afx8ujwvmzzj3rxpgrvaam9veczfydvvxf2srz8u5r" + }, + { + "x25519": "age1t4s23nhehjqzf3kk72pgq39n3m0uu39y4zv6x0nqam7em9cg2smsdq0ng5" + }, + { + "x25519": "age1dfqtgsyf259qm827xe2a3rdczzae27pkr87ywd8jcsk0mhzwashsnjcvrc" + }, + { + "x25519": "age1zz2p5yrkkgnfh6pqcktlnuauvs3gkttw9xjm8szlary53756uamsj7485u" + }, + { + "x25519": "age129pr99cslrpuzq64qgqze29pjweymsrcf5e0tqdmwp6nmwu0yqpsr3rz96" + }, + { + "x25519": "age1tgt08kc0fxvfhhdxdw8vg7522yt4t6pd6velzucg5pznu7a2fgaq2p39gv" + }, + { + "x25519": "age1n8c3z78uy2kxdgtn4d802wqkgy2rc9r6z30xtgc4xrtcsaky64esrwc5ty" + }, + { + "x25519": "age1ht3jpydx4duyuugapcjc0mfnzmpw5fjk3hy5t7u7xvm2xj849ahs06swce" + }, + { + "x25519": "age13xs8n7fueqpxhrfpvyy2sv55hm779cznvl6f754e73jxjkx94ygs4fwvep" + }, + { + "x25519": "age1qhn4dev8umj9lhfwf3yy0nhv2h8qhlvrzhd7klrtm9k3fe9pe3vsvglekg" + }, + { + "x25519": "age1dd5c9vl9lmfkm9z78ha40whqv3s6zvundckdjyzwhpvuu90ale6q0j40p3" + }, + { + "x25519": "age1wlk70qxapj948unec08zftyw95mexp9qt9gv3525gnzshk2mpyusdkkms4" + }, + { + "x25519": "age1kkgnqlar4zs5lmrau6l9ejr4fq0kptv9q9hejgmnhx68hk4hpg8smajzqn" + }, + { + "x25519": "age19qy2ahwgstj6ql2r527kw9xg47wzcftlv5r37xpshzlk9vpeveeqxgc3ds" + } + ], + "rules": { + "access_0": "ok", + "access_16": "ok", + "payload": "agewrap: PAYLOAD_AGE has 16 stanzas, want exactly one X25519 stanza: ERR_POLICY_STRUCTURE_MISMATCH", + "time_1000": "agewrap: OUTER_TIME_AGE has 16 stanzas, want exactly one tlock stanza: ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop sixteen", + "stanzas": [ + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519", + "X25519" + ], + "verdicts": [ + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + }, + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + }, + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + }, + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + }, + { + "error": "agewrap: no supplied identity is a recipient of INNER_ACCESS_AGE: ERR_ACCESS_INVALID" + }, + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20746c6f636b203130303020353264623962613730653063633066366561663738303364643037343437613166353437373733356664336636363137393262613934363030633834653937310a7552476e7a726532464852735774727936305741664c47504267312b4748344d4348352f575938416f2f6f75452b3553794862632b3052386d5533696c544d4a0a44734855677345622f314d30442b5963426f442f47634a674d684b386f34582b51413541566b7a2f6e74422b705574442b4461553434376d76496361362b33750a33735544622b3636744336486b42496c67624a614f4e5a6c5353704e45474679734d5a3453435063755a510a2d2d2d205a6f6f3458424e61675575466479795063426b6d36674b6a74774f444265686a4250306454626b52717a380af1614f1418fda4861875f20349a9a95b817f166ebfb21ca6097ff0772ef2598f62885e55f11727fa25ec57221d813fe2d812df78e98d6dbf1fab18872d1ae8af14ac91531b324286fa1d6f1037e751aae4437bd4ff36226ef466cff162eb062bda6a55206b711dadcaf9791014a667e922e9df8cdb69c422e67778f0fee63d65c52c634cd04147", + "file_length": 458, + "file_sha256": "da18fefdad2ea4ef077396d9aa7d9ced0aa8aafebbb5a1535a2c3c71449920b0", + "header_length": 323, + "length": 103, + "name": "tlock, round 1000", + "node": true, + "openers": [ + { + "release": 1000, + "tlock": 1000 + }, + { + "release": 1001, + "tlock": 1001 + } + ], + "recipients": [ + { + "tlock": 1000 + } + ], + "rules": { + "access_0": "agewrap: INNER_ACCESS_AGE stanza 0 has type \"tlock\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "agewrap: PAYLOAD_AGE stanza type \"tlock\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "time_1000": "ok" + }, + "seed": "interop tlock", + "stanzas": [ + "tlock" + ], + "verdicts": [ + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + }, + { + "error": "agewrap: tlock stanza round \"1000\", DateKey round 1001: ERR_ROUND_MISMATCH" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20746c6f636b203130303020353264623962613730653063633066366561663738303364643037343437613166353437373733356664336636363137393262613934363030633834653937310a6d645332715a415a4266655635504841396f726d4451526953587646526e767864666562486a414b6c58334a31585167737077323879614c4768447750696e6a0a4130776d4f39534347715665427147326c71306a4c316e2f6d652f704b7432735177307a367048554f6d3767315655563070636137354551637748584c7254660a566c4d6b37314a486d36704e747649395334554878364b4d50576455314355322f497269726f70546d78770a2d2d2d204d4d334a444c526171324e6a6c4251536375376d6e7044306c41556c52307a425a64324d536b47666e484d0a88e68f7146e86076f5c0b2781d0a12a98c53b7501f2b96d7ab213cfb71fb59c0386ef681dad33e9c2462e8d1d9c31d21c2e4b15069afb7efc83d96fbf409bc4be53a42da83ba6d08f99fe8d6caf19e502ff135f11d17a4e941b821e7aee358598e307b90246c105fcb8f0aae3502fda86bf83dccd3d5b38c0b9ad5cbaf439cc5aa78e705b95b451a675c34ce16a319ae555a6e403861269b8fe085002034d8aafabdc88c63f941db7a3c2ab8ff29e40e9c150cee264d1170af5ae5733dffa82578ad2b4626d422ff958eb6fadd9ddb8597bec3b329a730f22d04f2ecd64bc3f015378412343ab3b9e74f8cde7d66e7164c575b0192d3b895170495f75a17c01798752081ca121689488346063285c10589b04af0fabf826db66e29db6097b8d75583b1c1cb8fc6e0fdde10dc1ed93968b99b9f7834044a726b90b6c855d8ee8e59bb7bfb512a5769f2f91eb1104cbdaaddb9638fe40d8de72c7067ce8df05e95e4a63480b8bcbd0d4046cf1fbf59db9dfe48d08dea4e30bc9668baec4932cb7c2a2cd9593b72519c33e6f3663100733e1ff3f6e7706753f89814a7d46d4cfd18bb9ec0279f89c133daaf81638ee442b88f9724c70541248a630db52f1ae1cb039b855462593c89d12628c04f48146b5b0ac8149348b6bd09693be16fb5e27cede953ef1c3a32711fc49c63d8d9645fa5cc4d893ce87dfe23b7d8f7a80cb1f2a6724400789d4607c3e04879b00731fd3ef315cd8de0d0962ef09218dc93c7fa3d17fe1d05f8a0e65a1d5ec59b6959e55ff39a2256bdf86276de6e5d231bd4f24d481616e860ccacf606a18c2319446bac08d5815f77de49f537ac6def4aaba0f4053c3b5ecd31c0966a3304fbe50f39a512950cb739f9543259fa93fccc47413e9d6d8380e3daf13ffa7249b82934473701c09810d823cd19b99d44fb8d5f4d292f2a0624ebf9a5d26dd93f3a0f792fa92256cde02c3e25898b5581b41a72cc759f9f519c8316b875ebbd9883fa7c7691fb2a7216d863f89e972c98cb361d9f86846162e7961dbb34fce9ae957615582d33ec3a34541b2cecb13eb822a20f112cc803c6fbcbd0262580cab3d807f57aa2532ddb5b65fb4b3cb9bd57e2e1aa07d02720978c2ee8d1e51d077762bf68604164b95510ffc68b71150fdc386933fe88494a165c41551e3c03110d670e9d270f0558516b9b9cab5d8a40547571d3b9f14005b761001042ce9271dcdd59eb6ee965d3b488d73ddefdfb692be8bc80cef5cb2b30e39b7484db085e4701655e1107862902487b1d0fe53f18b3bcf8f5968f8c137987240e97ffcaaa72095bcb200103314a1cb9ebf238be4834133c1a1363c0e10846695d7815ec93252db02786e7d7e181b73598d5b5cb684fcfcf0098c852b2f1a952a2b4e3bde647f306e5452552178b4e58046cad1a115c125860e87f90793065f2c6515f6829f3a942ce25dd834e52ba350ff21ca1b97df28d6ea9950b3d894d9b3a8556b335e4cd1dcde77ee5551ef0ce104a776c7dbe4b8bd14351d0e3705c99d3474b8fcaa3501d897899c7a0415c7f5c936ed8752e0b3c77253677294c7ee2bc6c1a5b0e13c783890136385fad0a937f5694c60722391cd3d3b87270218438b82a1edea66c66d54dcc7be52ac327acfa2053ed928ec1914ec1b5ecf92d66db4e56fbe82d6ac4a6949efaf8144d8bfaa9813d42d2265de56b941e57b91cbdd790a4a79cf7964c2c5e28c1be4b11d179e6d15cf1594b8ea559a58348bfcc5e17500bb6fcf7b729527c32e8f2e57269d59f25d7220e44b10bca9158e44887d37e78634298f63262d2bfe9d2d068f39f6e062f219f19487edcbcac32d2bcc07fd549eab8c4e066ff61ffc78a8720ca6545ad2e2c5a08412c2127bfd4cf07834bcf1c56c4e4c4ccd0bf24b955b45f45dcb7a8971457b2d5750db6a4a556d11f146d0988483216ba1ebd051036f63b75afa3b66b915fbad8099f4f6c8a9e95915e0518da4c97bd4e5c6291cab4353b3682e01562d2ea9a3f55d623a8d5ba5c2ce6d0dedac74093e66e2910e6f61005085a2063142ad603e42a721d714607366c162bac3743915148a54333e33ffb1624d870717bede8096d37c46765bbb5fe070a92e5c14f37e55a839021390f24b15ebdd9ca98c850942bbae579a0fe67fd8c48bc491b0bdc410ec5e95447d3b11061260be2749df385b6f2fa7b7f562130520fccfa1d5e691429eec58608ac7123e2b57cd7b8492066e57b0633dd371c52245bd01acc90be129dfe07bbb3ea553ef1d71e8db4bad57a06844e5e5d2eab49e8496369c615e32d849f52c3c6890d5ccdae17771e19fefe3cf23b34e4ab33013f8f78b00c660348e25757bf8404eff2269864a60927c57a6b0950af91bdcc43774c50eb4d4db1584d305ba64625a1d7792f91c5858a499dfbdffd5428a0d655a321e4a96de8ac5603b4fe83d3d8fd21236896ec52a2ec3c7356785967b08e811ffcb2070a1bd847fc681f9b2a3b306eba1d2631b7eb490ee96cbcb9516c535b763203ad261460e61dc222", + "file_length": 2128, + "file_sha256": "f56fa000d865aebcc5600abfa41ec02c793273f533257057c9300ef553fafc74", + "header_length": 323, + "inner": { + "length": 103, + "recipients": [ + { + "x25519": "age1g6k265aru5r9m5d5svq5n7fesuglp59srk20tae6snwkw8mmdg7sg5exr5" + }, + { + "x25519": "age1v62lgqhqnm89f2ej97squ4q6ny9785lzw4hxyxlk6hlds9n99pssu0rypn" + }, + { + "x25519": "age1ndwvt5tj7x02m399afx8ujwvmzzj3rxpgrvaam9veczfydvvxf2srz8u5r" + }, + { + "x25519": "age1t4s23nhehjqzf3kk72pgq39n3m0uu39y4zv6x0nqam7em9cg2smsdq0ng5" + }, + { + "x25519": "age1dfqtgsyf259qm827xe2a3rdczzae27pkr87ywd8jcsk0mhzwashsnjcvrc" + }, + { + "x25519": "age1zz2p5yrkkgnfh6pqcktlnuauvs3gkttw9xjm8szlary53756uamsj7485u" + }, + { + "x25519": "age129pr99cslrpuzq64qgqze29pjweymsrcf5e0tqdmwp6nmwu0yqpsr3rz96" + }, + { + "x25519": "age1tgt08kc0fxvfhhdxdw8vg7522yt4t6pd6velzucg5pznu7a2fgaq2p39gv" + }, + { + "x25519": "age1n8c3z78uy2kxdgtn4d802wqkgy2rc9r6z30xtgc4xrtcsaky64esrwc5ty" + }, + { + "x25519": "age1ht3jpydx4duyuugapcjc0mfnzmpw5fjk3hy5t7u7xvm2xj849ahs06swce" + }, + { + "x25519": "age13xs8n7fueqpxhrfpvyy2sv55hm779cznvl6f754e73jxjkx94ygs4fwvep" + }, + { + "x25519": "age1qhn4dev8umj9lhfwf3yy0nhv2h8qhlvrzhd7klrtm9k3fe9pe3vsvglekg" + }, + { + "x25519": "age1dd5c9vl9lmfkm9z78ha40whqv3s6zvundckdjyzwhpvuu90ale6q0j40p3" + }, + { + "x25519": "age1wlk70qxapj948unec08zftyw95mexp9qt9gv3525gnzshk2mpyusdkkms4" + }, + { + "x25519": "age1kkgnqlar4zs5lmrau6l9ejr4fq0kptv9q9hejgmnhx68hk4hpg8smajzqn" + }, + { + "x25519": "age19qy2ahwgstj6ql2r527kw9xg47wzcftlv5r37xpshzlk9vpeveeqxgc3ds" + } + ], + "seed": "interop inner access" + }, + "name": "tlock over sixteen x25519, as SEALED_CONTROL", + "node": false, + "openers": [ + { + "release": 1000, + "then": { + "access": [ + "64673b44a140059fd41682b28cf75edfe8a803a6e41f3a3d45771b899061b3bc" + ], + "slots": 16 + }, + "tlock": 1000 + }, + { + "release": 1000, + "then": { + "access": [ + "1310fe453689a4dfd1d2fbc1adffa029f95955a495306117c28ce24b999724ea" + ], + "slots": 16 + }, + "tlock": 1000 + } + ], + "recipients": [ + { + "tlock": 1000 + } + ], + "rules": { + "access_0": "agewrap: INNER_ACCESS_AGE stanza 0 has type \"tlock\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "agewrap: PAYLOAD_AGE stanza type \"tlock\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "time_1000": "ok" + }, + "seed": "interop sealed control", + "stanzas": [ + "tlock" + ], + "verdicts": [ + { + "plaintext_length": 103, + "plaintext_sha256": "e571c2a147c1eceec5dd8b6aeb1889aae50ea41b623d3026abc665acff5201f9" + }, + { + "error": "agewrap: no supplied identity is a recipient of INNER_ACCESS_AGE: ERR_ACCESS_INVALID" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20736372797074204b726e6732617434643171707678785a42646b6c2b772031300a5a574f48326f707862446b6c3268732b46426b4371584a676e51775752397638663063307366347930796f0a2d2d2d203464726851484b4f5173615543584b524a6a6b765472393067366931315a736e7458434863616172787a380a05dcbb328a3ed8355dafb0e446d87f41bc456c2a8c99f2ef36a193f66ee4ae1e705fe174ce52a5936cea5d58339c9eae6bbb96f89f3352e3057a125c179cd6a40aebc07c8c627ebc08119182254fcf792fc037d5338d0f982e3f3372c31b366b368630db66917374ecc04fe366c80dade412d36451ea119cdef54a2d3901f65b0a34c94fa2918ab7ad5250a09bf589e93802933d666e83b2", + "file_length": 302, + "file_sha256": "9ffca1211ea37615c181c6b7298617e23bb533aedb131a7b466a252b18b322ab", + "header_length": 150, + "length": 120, + "name": "scrypt, work factor 10", + "node": true, + "openers": [ + { + "max_work_factor": 16, + "scrypt": "una contraseña larga de prueba" + }, + { + "max_work_factor": 16, + "scrypt": "otra contraseña" + }, + { + "max_work_factor": 9, + "scrypt": "una contraseña larga de prueba" + } + ], + "recipients": [ + { + "scrypt": "una contraseña larga de prueba", + "work_factor": 10 + } + ], + "rules": { + "access_0": "agewrap: INNER_ACCESS_AGE stanza 0 has type \"scrypt\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "agewrap: PAYLOAD_AGE stanza type \"scrypt\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"scrypt\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop scrypt 10", + "stanzas": [ + "scrypt" + ], + "verdicts": [ + { + "plaintext_length": 120, + "plaintext_sha256": "1f80156a804cb7862ad113e8200e9d74499723e7c7854d5f48776d3148e09656" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block: incorrect passphrase" + }, + { + "error": "scrypt work factor too large: 10" + } + ] + }, + { + "file": "6167652d656e6372797074696f6e2e6f72672f76310a2d3e20736372797074203976774b4450536a49317074504767722b50767a69772031360a594c4f64613736526c41566353766952504b5a673741557a49526372546c6f6379343364412b644b69736b0a2d2d2d20444b4f4e796b3675396872394b675670714676776e724c477562712b3776715564423941744136643144730a01218d5cc02a7644cc99fb77b4db3452d776d7f02aabe72e869babed30ce3a7a55d8763a84a1be19205b889aa67bf8ba21f43d14bdb259825092c8709307819423a45edf0b5f94bf2615fef492e7878dfe3ac50cd1600c3b1b3d78a68b4e2e0ce2a5aa0c60b1bac7407c1a39f5486e7f7203206965e5d3caa56ccff4401e97d705109c813816cf9e34eefa983f503812180bfa536023dc5e", + "file_length": 302, + "file_sha256": "946428b8ab69986b9d35109c84e5892fed73271ea3de4144197b3a5cae6340ae", + "header_length": 150, + "length": 120, + "name": "scrypt, work factor 16", + "node": false, + "openers": [ + { + "max_work_factor": 16, + "scrypt": "una contraseña larga de prueba" + }, + { + "max_work_factor": 16, + "scrypt": "otra contraseña" + }, + { + "max_work_factor": 15, + "scrypt": "una contraseña larga de prueba" + } + ], + "recipients": [ + { + "scrypt": "una contraseña larga de prueba", + "work_factor": 16 + } + ], + "rules": { + "access_0": "agewrap: INNER_ACCESS_AGE stanza 0 has type \"scrypt\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "access_16": "agewrap: INNER_ACCESS_AGE has 1 stanzas, want exactly 16: ERR_POLICY_STRUCTURE_MISMATCH", + "payload": "agewrap: PAYLOAD_AGE stanza type \"scrypt\", want \"X25519\": ERR_POLICY_STRUCTURE_MISMATCH", + "time_1000": "agewrap: OUTER_TIME_AGE stanza type \"scrypt\", want \"tlock\": ERR_POLICY_STRUCTURE_MISMATCH" + }, + "seed": "interop scrypt 16", + "stanzas": [ + "scrypt" + ], + "verdicts": [ + { + "plaintext_length": 120, + "plaintext_sha256": "1f80156a804cb7862ad113e8200e9d74499723e7c7854d5f48776d3148e09656" + }, + { + "error": "identity did not match any of the recipients: incorrect identity for recipient block: incorrect passphrase" + }, + { + "error": "scrypt work factor too large: 16" + } + ] + } + ], + "source": "c531e936fa8188a4aab01575607cc85d4f5d4fa4" +} diff --git a/tool/age_interop_dart_samples.dart b/tool/age_interop_dart_samples.dart new file mode 100644 index 0000000..00dc6bb --- /dev/null +++ b/tool/age_interop_dart_samples.dart @@ -0,0 +1,35 @@ +// Writes the samples of the interoperability of the age writer of +// datekeys-dart, stage 6a: the age files of the recipes of +// test/age_interop_support.dart, which this library writes with +// SeededRandomSource, and samples.json, the recipes with the name of each +// file, into a directory. tool/age_interop_go_verdicts.go then opens them +// with Go and writes test/vectors/age_interop.json; the tests write the +// files again from the recipes and compare them with what Go read. +// +// dart run tool/age_interop_dart_samples.dart +// +// ignore_for_file: avoid_print +import 'dart:convert'; +import 'dart:io'; + +import '../test/age_interop_support.dart'; + +void main(List args) { + if (args.length != 1) { + stderr.writeln('usage: dart run tool/age_interop_dart_samples.dart '); + exit(2); + } + final dir = Directory(args.single)..createSync(recursive: true); + final samples = interopSamples(); + for (var i = 0; i < samples.length; i++) { + final s = samples[i]; + final name = '$i.age'; + File('${dir.path}/$name').writeAsBytesSync(writeSample(s)); + s['file'] = name; + print('${s['name']}: $name'); + } + File('${dir.path}/samples.json').writeAsStringSync( + const JsonEncoder.withIndent(' ').convert({'samples': samples}), + ); + print('wrote ${samples.length} samples to ${dir.path}'); +} diff --git a/tool/age_interop_go_verdicts.go b/tool/age_interop_go_verdicts.go new file mode 100644 index 0000000..803d52d --- /dev/null +++ b/tool/age_interop_go_verdicts.go @@ -0,0 +1,231 @@ +//go:build ignore + +// Opens with Go the age files that the writer of datekeys-dart wrote, stage +// 6a of docs/PLAN_dart.md, and writes test/vectors/age_interop.json and +// age_interop.g.dart: each recipe of tool/age_interop_dart_samples.dart +// with the length and the SHA-256 of its file, the file itself when it is +// small, the length of its header (testkit.HeaderLen), its stanzas, the +// stanza rules of agewrap on them, and the verdict of Go with each of its +// openers: age.Decrypt and the reading of the whole plaintext with +// +// - x25519: age.ParseX25519Identity of the string; +// - payload: agewrap.NewPayloadIdentity of the raw identity; +// - access: agewrap.NewAccessIdentity of the slots and the raw +// identities; +// - scrypt: age.NewScryptIdentity with SetMaxWorkFactor; +// - tlock: agewrap.NewTimeIdentity for Quicknet, the round and the +// published release of another round, 1000 or 1001, those of the +// fixtures; +// +// and, with then, the same for the plaintext it opens, an age file too. A +// verdict is the length and the SHA-256 of the plaintext, or the text of +// the error. +// +// It imports internal/testkit, so it runs in an export of datekeys-go made +// with git archive, without changing the repository, on the branch v0.12 at +// c531e93, after the Dart tool wrote the samples: +// +// commit=$(git -C ../datekeys-go rev-parse v0.12) +// root=$PWD +// tmp=$(mktemp -d) +// dart run tool/age_interop_dart_samples.dart "$tmp/samples" +// git -C ../datekeys-go archive "$commit" | tar -x -C "$tmp" +// cp tool/age_interop_go_verdicts.go "$tmp" +// (cd "$tmp" && go run ./age_interop_go_verdicts.go -source "$commit" \ +// -samples "$tmp/samples" -out "$root/test/vectors") +// rm -rf "$tmp" +package main + +import ( + "bytes" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "flag" + "fmt" + "io" + "log" + "os" + "path/filepath" + "runtime" + + "filippo.io/age" + + "g.activething.com/go/DateKeys/agewrap" + "g.activething.com/go/DateKeys/internal/testkit" + "g.activething.com/go/DateKeys/profile" + "g.activething.com/go/DateKeys/provider" +) + +type obj = map[string]any + +func h(b []byte) string { return hex.EncodeToString(b) } + +func sum(b []byte) string { + s := sha256.Sum256(b) + return h(s[:]) +} + +func check(err error) { + if err != nil { + _, file, line, _ := runtime.Caller(1) + log.Fatalf("%s:%d: %v", filepath.Base(file), line, err) + } +} + +func mustHex(s string) []byte { + b, err := hex.DecodeString(s) + check(err) + return b +} + +func num(v any) int64 { + n, err := v.(json.Number).Int64() + check(err) + return n +} + +// The published Quicknet signatures of rounds 1000 and 1001, as in the +// fixtures. +var releases = map[int64]string{ + 1000: "b44679b9a59af2ec876b1a6b1ad52ea9b1615fc3982b19576350f93447cb1125e342b73a8dd2bacbe47e4b6b63ed5e39", + 1001: "b33bf3667cbd5a82de3a24b4e0e9fe5513cc1a0e840368c6e31f5fcfa79bea03f73896b25883abf2853d10337fb8fa41", +} + +func identityOf(o obj) age.Identity { + switch { + case o["x25519"] != nil: + id, err := age.ParseX25519Identity(o["x25519"].(string)) + check(err) + return id + case o["payload"] != nil: + id, err := agewrap.NewPayloadIdentity(mustHex(o["payload"].(string))) + check(err) + return id + case o["access"] != nil: + var ids []age.Identity + for _, raw := range o["access"].([]any) { + id, err := agewrap.X25519IdentityFromRaw(mustHex(raw.(string))) + check(err) + ids = append(ids, id) + } + a, err := agewrap.NewAccessIdentity(int(num(o["slots"])), ids...) + check(err) + return a + case o["scrypt"] != nil: + s, err := age.NewScryptIdentity(o["scrypt"].(string)) + check(err) + s.SetMaxWorkFactor(int(num(o["max_work_factor"]))) + return s + default: + round, release := num(o["tlock"]), num(o["release"]) + id, err := agewrap.NewTimeIdentity(profile.Quicknet(), uint64(round), provider.Release{Round: uint64(release), Signature: mustHex(releases[release])}) + check(err) + return id + } +} + +func open(file []byte, o obj) ([]byte, error) { + r, err := age.Decrypt(bytes.NewReader(file), identityOf(o)) + if err != nil { + return nil, err + } + plain, err := io.ReadAll(r) + if err != nil { + return nil, err + } + if then, ok := o["then"].(obj); ok { + return open(plain, then) + } + return plain, nil +} + +func ruleText(err error) string { + if err != nil { + return err.Error() + } + return "ok" +} + +func main() { + samplesDir := flag.String("samples", "", "the directory of the samples") + outDir := flag.String("out", "", "where the vectors go") + src := flag.String("source", "", "the commit of datekeys-go") + flag.Parse() + if *samplesDir == "" || *outDir == "" || *src == "" { + log.Fatal("usage: -source -samples -out ") + } + raw, err := os.ReadFile(filepath.Join(*samplesDir, "samples.json")) + check(err) + dec := json.NewDecoder(bytes.NewReader(raw)) + dec.UseNumber() + var in struct { + Samples []obj `json:"samples"` + } + check(dec.Decode(&in)) + q := profile.Quicknet() + var out []obj + for _, s := range in.Samples { + file, err := os.ReadFile(filepath.Join(*samplesDir, s["file"].(string))) + check(err) + delete(s, "file") + n, err := testkit.HeaderLen(file) + check(err) + stanzas, err := agewrap.Stanzas(bytes.NewReader(file)) + check(err) + var types []string + for _, st := range stanzas { + types = append(types, st.Type) + } + s["file_length"] = len(file) + s["file_sha256"] = sum(file) + s["header_length"] = n + s["stanzas"] = types + s["rules"] = obj{ + "payload": ruleText(agewrap.CheckPayloadStanzas(stanzas)), + "access_0": ruleText(agewrap.CheckAccessStanzas(stanzas, 0)), + "access_16": ruleText(agewrap.CheckAccessStanzas(stanzas, agewrap.AccessSlots)), + "time_1000": ruleText(agewrap.CheckTimeStanzas(stanzas, q, 1000)), + } + if len(file) <= 4096 { + s["file"] = h(file) + } + var verdicts []obj + for _, o := range s["openers"].([]any) { + plain, err := open(file, o.(obj)) + if err != nil { + verdicts = append(verdicts, obj{"error": err.Error()}) + continue + } + verdicts = append(verdicts, obj{"plaintext_length": len(plain), "plaintext_sha256": sum(plain)}) + } + s["verdicts"] = verdicts + out = append(out, s) + fmt.Printf("%s: %d bytes\n", s["name"], len(file)) + } + doc := obj{ + "source": *src, + "go": runtime.Version(), + "description": "Age files that datekeys-dart writes with SeededRandomSource from the recipes of test/age_interop_support.dart, opened by filippo.io/age v1.3.2 and agewrap (tool/age_interop_go_verdicts.go): the length and the SHA-256 of each file, the file when small, the length of its header, its stanzas, the stanza rules of agewrap on them, and the verdict of Go with each opener, the length and the SHA-256 of the plaintext or the text of the error. The plaintext of n bytes has (31·i + 7) mod 256 as byte i. A sample marked node false is left out compiled to JavaScript.", + "samples": out, + } + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + enc.SetEscapeHTML(false) + enc.SetIndent("", " ") + check(enc.Encode(doc)) + path := filepath.Join(*outDir, "age_interop.json") + check(os.WriteFile(path, buf.Bytes(), 0o644)) + fmt.Printf("wrote %s, %d bytes\n", path, buf.Len()) + if bytes.Contains(buf.Bytes(), []byte("'''")) { + log.Fatal("the JSON holds three quotes") + } + dart := "// Generated by tool/age_interop_go_verdicts.go from age_interop.json, for\n" + + "// the tests that also run compiled to JavaScript, where no file can be\n" + + "// read. Do not edit.\n\n" + + "/// The text of test/vectors/age_interop.json.\n" + + "const ageInteropJson = r'''\n" + buf.String() + "''';\n" + dpath := filepath.Join(*outDir, "age_interop.g.dart") + check(os.WriteFile(dpath, []byte(dart), 0o644)) + fmt.Printf("wrote %s\n", dpath) +}