You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dateKeys-dart/test/security_test.dart

404 lines
13 KiB

Stage 5b: the commitments, SECURITY_CBOR and the verdicts of alg 1 author.dart ports what an author signs and a seal seals from signature.go of datekeys-go: payload_commit, control_commit over CONTROL_SIG in each format, head_digest, signers_digest, AUTHOR_MESSAGE with its prefix and its 99 bytes, its code taken byte by byte as Go takes it, SIG_PART and SEAL_SUBJECT. security.dart ports SECURITY_CBOR and EvaluateSecurityIn: the outer map, author-signature and seal with the schema and the limits of Go, their encoders, and an evaluation that never throws. X for an outer map that fails its layer 2 or 3, version 2 among them; F0 to F4 for the signature, with verifyStrict for alg 1 and the key matched against the saved ones by its dkauthor1 string; S0 to S2 for the seal; and a failure inside one part fails that part only, as Go recovers a panic. Without a context it reads as a reader of v0.10. securityContext is newSecurityContext with the head digest, control_commit at zero when CONTROL_SIG cannot be encoded, and holderText the rule of a name of a certificate. The signature of alg 2 and the seal of seal_type 2 belong to the reader of CMS of stage 5c, behind the interface CmsEvaluator: without one their verdict is null, not evaluated, never guessed. verdicts.dart gains the texts of Go at the draft v0.12, Verdicts.lines and sealedAt, Detail, SignerLine and SignerResult, and verdicts that may be evaluated in part. The tests check every case of security_vectors.json, security.json in its context, the commitments, the signature and the seal of each fixture of format 3, and the boundary with a reader of CMS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
// The security area on the VM and compiled to JavaScript: the part of the
// vectors of Go that test/vectors/security_vectors.g.dart holds, which
// tool/security_go_vectors.go writes with package capsule of the reference,
// and what the API does: the boundary with the reader of CMS of alg 2 and
// seal_type 2, an evaluation that never throws, and the context that the
// opening builds.
library;
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
import 'package:datekeys/datekeys.dart';
import 'package:test/test.dart';
import 'open_vectors_support.dart';
import 'security_support.dart';
import 'vectors/security_vectors.g.dart';
final Json _vectors = jsonDecode(securityVectorsJson) as Json;
List<Json> _section(String name) => (_vectors[name]! as List).cast<Json>();
/// A reader of CMS that answers what it is given, and records its calls.
final class FakeCms implements CmsEvaluator {
FakeCms({this.signature, this.seal, this.throws = false});
final CmsSignatureVerdict? Function()? signature;
final CmsSealVerdict Function()? seal;
final bool throws;
final calls = <String>[];
Uint8List? signedWith;
bool? hasSeal;
@override
CmsSignatureVerdict? evaluateSignature(
Uint8List signers,
Uint8List value,
bool hasSeal,
SecurityContext context,
) {
calls.add('signature');
this.hasSeal = hasSeal;
if (throws) throw StateError('broken');
return signature!();
}
@override
CmsSealVerdict evaluateSeal(
Uint8List token,
Uint8List? signature,
SecurityContext context,
) {
calls.add('seal');
signedWith = signature;
if (throws) throw StateError('broken');
return seal!();
}
}
void main() {
test('the part of the vectors is of this spec, from its generator', () {
expect(_vectors['spec'], specVersion);
expect(_vectors['generator'], 'tool/security_go_vectors.go');
expect(_section('evaluate'), hasLength(greaterThan(150)));
});
test('the commitments, as Go builds them', () {
expect(commitmentDifferences(_vectors['commitments']! as Json), isEmpty);
});
test('the encoders, as Go writes them', () {
expect(encodeDifferences(_section('encode')), isEmpty);
expect(encodeSecurity(), hasLength(22));
});
test('every eighth evaluation, with the verdicts and lines of Go', () {
final contexts = contextsOf(_vectors);
final texts = (_vectors['texts']! as List).cast<String>();
final bases = [
for (final b in (_vectors['bases']! as List).cast<String>()) fromHex(b),
];
for (final c in _section('evaluate')) {
final security = securityOf(c, bases);
expect(
evaluateDifferences(c, security, contexts, texts),
isEmpty,
reason: canonical(c),
);
}
});
test('the lines and the earliest seal of every verdict and detail', () {
for (final c in _section('lines')) {
expect(lineDifferences(c), isEmpty, reason: str(c, 'name'));
}
});
test('the name of a certificate, as holderText of Go', () {
final cases = _section('holder');
expect(cases, hasLength(greaterThan(200)));
for (final c in cases) {
expect(
holderText(nameOf(c), fromHex(str(c, 'hash'))),
c['result'],
reason: canonical(c),
);
}
// A hash that is not a SHA-256 is an error of the caller.
expect(() => holderText('Ana', Uint8List(31)), throwsArgumentError);
});
group('the reader of CMS', () {
final context = SecurityContext(
controlCommit: Uint8List(32)..[0] = 1,
headDigest: Uint8List(32)..[0] = 2,
roundTime: parseRfc3339('2030-01-01T00:00:00Z'),
);
final alg2 = encodeAuthorSignature(algCms, [0x80], [1, 2, 3]);
final seal2 = encodeSeal(sealTypeRfc3161, [4, 5, 6]);
final ana = SignerLine(
holder: 'Ana',
issuer: 'CA',
result: SignerResult.valid,
sealHolder: 'TSA',
sealTime: parseRfc3339('2026-09-30T12:00:00.5Z'),
before: true,
);
final tsaTime = parseRfc3339('2026-09-29T10:00:00Z');
Stage 5c: the verdicts of alg 2 and seal_type 2, and the opening gives them securitycms.dart ports evaluateCMS, signerLine and evaluateSeal of signature2.go of Go at the draft v0.12, on the reader of CMS of stage 5a, with the same order of checks: SIGNERS with its profile and at most 16 entries, then the SignedData; each required signer in the order of SIGNERS and each foreign one in the order of the encoding, valid, invalid, absent, not verifiable, without seal, with an invalid seal or out of validity at the time of its seal; F2, F5 and F6 with their detail; and the seal over SEAL_SUBJECT, S1 to S5 with the authority and t. A round time at Go's zero time is no round time, as IsZero, and Verdicts.sealedAt skips a seal at that time, as SealedAt. cmsReader is the default CmsEvaluator of evaluateSecurity, and so of evaluateSecurityInput and the opening: nothing that Go evaluates is left not evaluated; a caller that passes cms: null still gets the parts without CMS alone. encodeSigners and maxSigners are exported, as EncodeSigners and MaxSigners of Go. The tests compare every part with Go: the 135 cases of security_cms.json with the result of each signer, the 24 of security.json, the 56 signatures of alg 2 and 105 seals of seal_type 2 of security_vectors.json, the 755 cases of securitycms_vectors.json with their detail and earliest seal, the fixtures format3_signed_cms and format3_sealed, and their openings in open_cases.json. On Node.js, a part of the vectors and the two fixtures opened in full. 1572 tests on the VM and 332 on Node.js. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
test('is cmsReader by default, and the opening evaluates with it', () {
// SIGNERS empty is F1, and a token that is not DER, S2.
final v = evaluateSecurity(
encodeSecurityWith(signature: alg2, seal: seal2),
context: context,
);
expect(
[v.signature, v.seal, v.evaluated],
[Verdict.signatureUnchecked, Verdict.sealUnreadable, true],
);
expect(v.lines, [
Verdict.signatureUnchecked.text,
Verdict.sealUnreadable.text,
]);
});
Stage 5b: the commitments, SECURITY_CBOR and the verdicts of alg 1 author.dart ports what an author signs and a seal seals from signature.go of datekeys-go: payload_commit, control_commit over CONTROL_SIG in each format, head_digest, signers_digest, AUTHOR_MESSAGE with its prefix and its 99 bytes, its code taken byte by byte as Go takes it, SIG_PART and SEAL_SUBJECT. security.dart ports SECURITY_CBOR and EvaluateSecurityIn: the outer map, author-signature and seal with the schema and the limits of Go, their encoders, and an evaluation that never throws. X for an outer map that fails its layer 2 or 3, version 2 among them; F0 to F4 for the signature, with verifyStrict for alg 1 and the key matched against the saved ones by its dkauthor1 string; S0 to S2 for the seal; and a failure inside one part fails that part only, as Go recovers a panic. Without a context it reads as a reader of v0.10. securityContext is newSecurityContext with the head digest, control_commit at zero when CONTROL_SIG cannot be encoded, and holderText the rule of a name of a certificate. The signature of alg 2 and the seal of seal_type 2 belong to the reader of CMS of stage 5c, behind the interface CmsEvaluator: without one their verdict is null, not evaluated, never guessed. verdicts.dart gains the texts of Go at the draft v0.12, Verdicts.lines and sealedAt, Detail, SignerLine and SignerResult, and verdicts that may be evaluated in part. The tests check every case of security_vectors.json, security.json in its context, the commitments, the signature and the seal of each fixture of format 3, and the boundary with a reader of CMS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
test('without one, alg 2 and seal_type 2 are not evaluated', () {
final v = evaluateSecurity(
encodeSecurityWith(signature: alg2, seal: seal2),
context: context,
Stage 5c: the verdicts of alg 2 and seal_type 2, and the opening gives them securitycms.dart ports evaluateCMS, signerLine and evaluateSeal of signature2.go of Go at the draft v0.12, on the reader of CMS of stage 5a, with the same order of checks: SIGNERS with its profile and at most 16 entries, then the SignedData; each required signer in the order of SIGNERS and each foreign one in the order of the encoding, valid, invalid, absent, not verifiable, without seal, with an invalid seal or out of validity at the time of its seal; F2, F5 and F6 with their detail; and the seal over SEAL_SUBJECT, S1 to S5 with the authority and t. A round time at Go's zero time is no round time, as IsZero, and Verdicts.sealedAt skips a seal at that time, as SealedAt. cmsReader is the default CmsEvaluator of evaluateSecurity, and so of evaluateSecurityInput and the opening: nothing that Go evaluates is left not evaluated; a caller that passes cms: null still gets the parts without CMS alone. encodeSigners and maxSigners are exported, as EncodeSigners and MaxSigners of Go. The tests compare every part with Go: the 135 cases of security_cms.json with the result of each signer, the 24 of security.json, the 56 signatures of alg 2 and 105 seals of seal_type 2 of security_vectors.json, the 755 cases of securitycms_vectors.json with their detail and earliest seal, the fixtures format3_signed_cms and format3_sealed, and their openings in open_cases.json. On Node.js, a part of the vectors and the two fixtures opened in full. 1572 tests on the VM and 332 on Node.js. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
cms: null,
Stage 5b: the commitments, SECURITY_CBOR and the verdicts of alg 1 author.dart ports what an author signs and a seal seals from signature.go of datekeys-go: payload_commit, control_commit over CONTROL_SIG in each format, head_digest, signers_digest, AUTHOR_MESSAGE with its prefix and its 99 bytes, its code taken byte by byte as Go takes it, SIG_PART and SEAL_SUBJECT. security.dart ports SECURITY_CBOR and EvaluateSecurityIn: the outer map, author-signature and seal with the schema and the limits of Go, their encoders, and an evaluation that never throws. X for an outer map that fails its layer 2 or 3, version 2 among them; F0 to F4 for the signature, with verifyStrict for alg 1 and the key matched against the saved ones by its dkauthor1 string; S0 to S2 for the seal; and a failure inside one part fails that part only, as Go recovers a panic. Without a context it reads as a reader of v0.10. securityContext is newSecurityContext with the head digest, control_commit at zero when CONTROL_SIG cannot be encoded, and holderText the rule of a name of a certificate. The signature of alg 2 and the seal of seal_type 2 belong to the reader of CMS of stage 5c, behind the interface CmsEvaluator: without one their verdict is null, not evaluated, never guessed. verdicts.dart gains the texts of Go at the draft v0.12, Verdicts.lines and sealedAt, Detail, SignerLine and SignerResult, and verdicts that may be evaluated in part. The tests check every case of security_vectors.json, security.json in its context, the commitments, the signature and the seal of each fixture of format 3, and the boundary with a reader of CMS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
);
expect(
[v.signature, v.seal, v.evaluated, v.lines],
[null, null, false, isEmpty],
);
final s = evaluateSecurity(
encodeSecurityWith(signature: alg2, seal: encodeSeal(1, [1])),
context: context,
Stage 5c: the verdicts of alg 2 and seal_type 2, and the opening gives them securitycms.dart ports evaluateCMS, signerLine and evaluateSeal of signature2.go of Go at the draft v0.12, on the reader of CMS of stage 5a, with the same order of checks: SIGNERS with its profile and at most 16 entries, then the SignedData; each required signer in the order of SIGNERS and each foreign one in the order of the encoding, valid, invalid, absent, not verifiable, without seal, with an invalid seal or out of validity at the time of its seal; F2, F5 and F6 with their detail; and the seal over SEAL_SUBJECT, S1 to S5 with the authority and t. A round time at Go's zero time is no round time, as IsZero, and Verdicts.sealedAt skips a seal at that time, as SealedAt. cmsReader is the default CmsEvaluator of evaluateSecurity, and so of evaluateSecurityInput and the opening: nothing that Go evaluates is left not evaluated; a caller that passes cms: null still gets the parts without CMS alone. encodeSigners and maxSigners are exported, as EncodeSigners and MaxSigners of Go. The tests compare every part with Go: the 135 cases of security_cms.json with the result of each signer, the 24 of security.json, the 56 signatures of alg 2 and 105 seals of seal_type 2 of security_vectors.json, the 755 cases of securitycms_vectors.json with their detail and earliest seal, the fixtures format3_signed_cms and format3_sealed, and their openings in open_cases.json. On Node.js, a part of the vectors and the two fixtures opened in full. 1572 tests on the VM and 332 on Node.js. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
cms: null,
Stage 5b: the commitments, SECURITY_CBOR and the verdicts of alg 1 author.dart ports what an author signs and a seal seals from signature.go of datekeys-go: payload_commit, control_commit over CONTROL_SIG in each format, head_digest, signers_digest, AUTHOR_MESSAGE with its prefix and its 99 bytes, its code taken byte by byte as Go takes it, SIG_PART and SEAL_SUBJECT. security.dart ports SECURITY_CBOR and EvaluateSecurityIn: the outer map, author-signature and seal with the schema and the limits of Go, their encoders, and an evaluation that never throws. X for an outer map that fails its layer 2 or 3, version 2 among them; F0 to F4 for the signature, with verifyStrict for alg 1 and the key matched against the saved ones by its dkauthor1 string; S0 to S2 for the seal; and a failure inside one part fails that part only, as Go recovers a panic. Without a context it reads as a reader of v0.10. securityContext is newSecurityContext with the head digest, control_commit at zero when CONTROL_SIG cannot be encoded, and holderText the rule of a name of a certificate. The signature of alg 2 and the seal of seal_type 2 belong to the reader of CMS of stage 5c, behind the interface CmsEvaluator: without one their verdict is null, not evaluated, never guessed. verdicts.dart gains the texts of Go at the draft v0.12, Verdicts.lines and sealedAt, Detail, SignerLine and SignerResult, and verdicts that may be evaluated in part. The tests check every case of security_vectors.json, security.json in its context, the commitments, the signature and the seal of each fixture of format 3, and the boundary with a reader of CMS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
);
expect(
[s.signature, s.seal, s.lines],
[
null,
Verdict.sealUnsupported,
[Verdict.sealUnsupported.text],
],
);
final f = evaluateSecurity(
encodeSecurityWith(
signature: encodeAuthorSignature(9, [], []),
seal: seal2,
),
context: context,
Stage 5c: the verdicts of alg 2 and seal_type 2, and the opening gives them securitycms.dart ports evaluateCMS, signerLine and evaluateSeal of signature2.go of Go at the draft v0.12, on the reader of CMS of stage 5a, with the same order of checks: SIGNERS with its profile and at most 16 entries, then the SignedData; each required signer in the order of SIGNERS and each foreign one in the order of the encoding, valid, invalid, absent, not verifiable, without seal, with an invalid seal or out of validity at the time of its seal; F2, F5 and F6 with their detail; and the seal over SEAL_SUBJECT, S1 to S5 with the authority and t. A round time at Go's zero time is no round time, as IsZero, and Verdicts.sealedAt skips a seal at that time, as SealedAt. cmsReader is the default CmsEvaluator of evaluateSecurity, and so of evaluateSecurityInput and the opening: nothing that Go evaluates is left not evaluated; a caller that passes cms: null still gets the parts without CMS alone. encodeSigners and maxSigners are exported, as EncodeSigners and MaxSigners of Go. The tests compare every part with Go: the 135 cases of security_cms.json with the result of each signer, the 24 of security.json, the 56 signatures of alg 2 and 105 seals of seal_type 2 of security_vectors.json, the 755 cases of securitycms_vectors.json with their detail and earliest seal, the fixtures format3_signed_cms and format3_sealed, and their openings in open_cases.json. On Node.js, a part of the vectors and the two fixtures opened in full. 1572 tests on the VM and 332 on Node.js. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
cms: null,
Stage 5b: the commitments, SECURITY_CBOR and the verdicts of alg 1 author.dart ports what an author signs and a seal seals from signature.go of datekeys-go: payload_commit, control_commit over CONTROL_SIG in each format, head_digest, signers_digest, AUTHOR_MESSAGE with its prefix and its 99 bytes, its code taken byte by byte as Go takes it, SIG_PART and SEAL_SUBJECT. security.dart ports SECURITY_CBOR and EvaluateSecurityIn: the outer map, author-signature and seal with the schema and the limits of Go, their encoders, and an evaluation that never throws. X for an outer map that fails its layer 2 or 3, version 2 among them; F0 to F4 for the signature, with verifyStrict for alg 1 and the key matched against the saved ones by its dkauthor1 string; S0 to S2 for the seal; and a failure inside one part fails that part only, as Go recovers a panic. Without a context it reads as a reader of v0.10. securityContext is newSecurityContext with the head digest, control_commit at zero when CONTROL_SIG cannot be encoded, and holderText the rule of a name of a certificate. The signature of alg 2 and the seal of seal_type 2 belong to the reader of CMS of stage 5c, behind the interface CmsEvaluator: without one their verdict is null, not evaluated, never guessed. verdicts.dart gains the texts of Go at the draft v0.12, Verdicts.lines and sealedAt, Detail, SignerLine and SignerResult, and verdicts that may be evaluated in part. The tests check every case of security_vectors.json, security.json in its context, the commitments, the signature and the seal of each fixture of format 3, and the boundary with a reader of CMS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
);
expect(
[f.signature, f.seal, f.lines],
[
Verdict.signatureUnchecked,
null,
[Verdict.signatureUnchecked.text],
],
);
expect('$f', 'Verdicts(F1, not evaluated)');
});
test('without a context it is never asked, as a reader of v0.10', () {
final cms = FakeCms();
final v = evaluateSecurity(
encodeSecurityWith(signature: alg2, seal: seal2),
cms: cms,
);
expect(
[v.signature, v.seal],
[Verdict.signatureUnchecked, Verdict.sealUnsupported],
);
expect(cms.calls, isEmpty);
});
test('gives F2, F5 or F6 with the signers, and the seal with its '
'authority, in one detail', () {
final cms = FakeCms(
signature: () =>
CmsSignatureVerdict(Verdict.signedComplete, Detail(signers: [ana])),
seal: () =>
CmsSealVerdict(Verdict.sealed, holder: 'TSA 2', time: tsaTime),
);
final security = encodeSecurityWith(signature: alg2, seal: seal2);
final v = evaluateSecurity(security, context: context, cms: cms);
expect([v.signature, v.seal], [Verdict.signedComplete, Verdict.sealed]);
expect(cms.calls, ['signature', 'seal']);
expect([cms.hasSeal, cms.signedWith], [true, alg2]);
expect(v.detail!.signers, [ana]);
expect([v.detail!.sealHolder, v.detail!.sealTime], ['TSA 2', tsaTime]);
// The lines are those of these verdicts, which the vectors of Go
// check: those of F6 with its signer, and S4 with its authority.
final merged = Verdicts(
signature: Verdict.signedComplete,
seal: Verdict.sealed,
detail: Detail(signers: [ana], sealHolder: 'TSA 2', sealTime: tsaTime),
);
expect(v.lines, merged.lines);
expect(v.lines, hasLength(4));
expect(v.sealedAt, tsaTime);
// A seal without a signature seals SIG_PART 0x00.
final alone = evaluateSecurity(
encodeSecurityWith(seal: seal2),
context: context,
cms: cms,
);
expect(
[alone.signature, alone.seal, cms.signedWith],
[Verdict.noSignature, Verdict.sealed, null],
);
});
test('null is F1, and S1 to S3 name no authority', () {
final cms = FakeCms(
signature: () => null,
seal: () =>
CmsSealVerdict(Verdict.sealInvalid, holder: 'x', time: tsaTime),
);
final v = evaluateSecurity(
encodeSecurityWith(signature: alg2, seal: seal2),
context: context,
cms: cms,
);
expect(
[v.signature, v.seal, v.detail],
[Verdict.signatureUnchecked, Verdict.sealInvalid, null],
);
});
test('what it throws, or a verdict out of its range, fails its own part '
'only, as a panic in Go', () {
final security = encodeSecurityWith(signature: alg2, seal: seal2);
final broken = evaluateSecurity(
security,
context: context,
cms: FakeCms(throws: true),
);
expect(
[broken.signature, broken.seal, broken.detail],
[Verdict.signatureUnchecked, Verdict.sealUnreadable, null],
);
for (final (sig, seal) in [
(
() => CmsSignatureVerdict(Verdict.signedSaved, Detail()),
() => const CmsSealVerdict(Verdict.noSeal),
),
(
() => CmsSignatureVerdict(Verdict.unreadable, Detail()),
() => const CmsSealVerdict(Verdict.sealed, holder: 'no time'),
),
]) {
final v = evaluateSecurity(
security,
context: context,
cms: FakeCms(signature: sig, seal: seal),
);
expect(
[v.signature, v.seal, v.detail],
[Verdict.signatureUnchecked, Verdict.sealUnreadable, null],
);
}
// The seal fails, and the signers of the signature stay.
final half = evaluateSecurity(
security,
context: context,
cms: FakeCms(
signature: () => CmsSignatureVerdict(
Verdict.signedIncomplete,
Detail(signers: [ana]),
),
seal: () => throw StateError('broken'),
),
);
expect(
[half.signature, half.seal],
[Verdict.signedIncomplete, Verdict.sealUnreadable],
);
expect(
[half.detail!.signers, half.detail!.sealTime],
[
[ana],
null,
],
);
});
});
test('never throws, whatever the area holds', () {
final r = Random(20261005);
final valid = encodeSecurityWith(
signature: encodeAuthorSignature(1, Uint8List(32), Uint8List(64)),
seal: encodeSeal(1, [1]),
);
final context = SecurityContext(
controlCommit: Uint8List(32),
headDigest: Uint8List(32),
);
for (var i = 0; i < 300; i++) {
final b = Uint8List.fromList(valid);
for (var j = 0; j < 1 + r.nextInt(3); j++) {
b[r.nextInt(b.length)] = r.nextInt(256);
}
final cut = Uint8List.sublistView(b, 0, r.nextInt(b.length + 1));
for (final area in [
b,
cut,
Uint8List.fromList(List.generate(r.nextInt(40), (_) => r.nextInt(256))),
]) {
for (final ctx in [null, context]) {
final v = evaluateSecurity(area, context: ctx);
expect(v.evaluated, isTrue);
expect(v.lines, isNotEmpty);
}
}
}
});
test('the context of the opening: control_commit, head_digest, the round '
'time and the keys', () {
final built =
((_vectors['commitments']! as Json)['control_commit']! as List)
.cast<Json>()
.firstWhere((c) => c['decode_format'] == 3 && c['format'] == 3);
final control = decodeControl(
fromHex(str(built, 'control')),
CapsuleFormat.format3,
);
final head = Uint8List.fromList(utf8.encode('a head'));
final keys = {'dkauthor1x': 'Ana'};
final input = SecurityInput(
security: encodeSecurity(),
head: head,
control: control,
format: CapsuleFormat.format3,
roundTime: parseRfc3339('2030-01-01T00:00:00Z'),
authorKeys: keys,
);
final c = securityContext(input);
expect(toHex(c.controlCommit), built['commit']);
expect(c.headDigest, headDigest(head));
expect([c.roundTime, c.authorKeys], [input.roundTime, keys]);
expect(
[
evaluateSecurityInput(input).signature,
evaluateSecurityInput(input).seal,
],
[Verdict.noSignature, Verdict.noSeal],
);
// A control that CONTROL_SIG cannot hold leaves control_commit at zero,
// as in Go.
final odd = securityContext(
SecurityInput(
security: input.security,
head: head,
control: control,
format: CapsuleFormat.format1,
roundTime: input.roundTime,
authorKeys: const {},
),
);
expect(odd.controlCommit, Uint8List(32));
});
test('the texts of the verdicts and of the results', () {
// S0 shows nothing, and the verdicts that name a key, a holder or a
// time have their text in the lines.
for (final v in Verdict.values) {
expect(v.text.isEmpty, {'S0', 'F3', 'F4', 'F6', 'S4'}.contains(v.code));
}
for (final r in SignerResult.values) {
expect(SignerResult.fromCode(r.code), r);
}
expect(SignerResult.fromCode('valida'), isNull);
expect(Verdicts.notEvaluated.lines, isEmpty);
expect(Verdicts.failed(StateError('x')).lines, isEmpty);
});
}

Powered by TurnKey Linux.