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_support.dart

446 lines
15 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>
3 days ago
// Helpers of the tests of the security area against the vectors of Go: the
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>
3 days ago
// verdicts of an area as the vectors record them, compared part by part,
// the signature of alg 2 and the seal of seal_type 2 with the reader of CMS
// of securitycms.dart, as evaluateSecurity does by default. They read no
// file, so that the tests that run on Node.js can use them.
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>
3 days ago
library;
import 'dart:typed_data';
import 'package:datekeys/datekeys.dart';
import 'package:datekeys/src/bech32.dart' show bech32Encode;
import 'package:datekeys/src/bytes.dart' show utf8Bytes;
import 'package:datekeys/src/sha256.dart' show sha256;
import 'open_vectors_support.dart';
import 'tlock_support.dart' show applyEdits;
/// Which parts of [security] the reader of CMS evaluates in a context: a
/// signature of alg 2, and a seal of seal_type 2.
({bool signature, bool seal}) cmsParts(List<int> security) {
final w = decodeSecurity(security);
if (w == null) return (signature: false, seal: false);
final sig = w.signature;
final seal = w.seal;
return (
signature: sig != null && decodeAuthorSignature(sig)?.alg == algCms,
seal: seal != null && decodeSeal(seal)?.sealType == sealTypeRfc3161,
);
}
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>
3 days ago
/// Whether [t] is Go's zero time, which Go writes as no time.
bool isGoZero(Instant t) => t.seconds == -62135596800 && t.nanos == 0;
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>
3 days ago
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>
3 days ago
/// [t] as the vectors of Go write a time: RFC 3339 with its fraction, and
/// null for none or for Go's zero time.
String? timeText(Instant? t) =>
t == null || isGoZero(t) ? null : formatRfc3339Nano(t);
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>
3 days ago
/// The differences between [v] and [want], the verdicts of Go as the vectors
/// record them: signature, seal, lines, and with [keys] author_key,
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>
3 days ago
/// author_label and sealed_at.
List<String> verdictDifferences(Json want, Verdicts v, {bool keys = true}) {
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>
3 days ago
final out = <String>[];
void same(String what, Object? got, Object? expected) {
final g = canonical(got);
final w = canonical(expected);
if (g != w) out.add('$what: got $g, want $w');
}
if (v.error != null) out.add('the evaluator failed: ${v.error}');
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>
3 days ago
same('signature', v.signature?.code, want['signature']);
same('seal', v.seal?.code, want['seal']);
same('lines', v.lines, want['lines']);
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>
3 days ago
if (keys) {
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>
3 days ago
same('sealed_at', timeText(v.sealedAt), want['sealed_at']);
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>
3 days ago
final key = v.authorKey;
same(
'author_key',
key == null ? null : bech32Encode('dkauthor', key),
want['author_key'],
);
same('author_label', v.authorLabel, want['author_label']);
}
return out;
}
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>
3 days ago
/// A signer as the lines section of security_vectors.json and the cases of
/// securitycms_vectors.json write it, as signerJSON of
/// tool/security_go_vectors.go.
Json signerJson(SignerLine s) => {
'holder': s.holder,
'issuer': s.issuer,
'result': s.result.code,
'seal_holder': s.sealHolder,
'before': s.before,
if (timeText(s.sealTime) != null) 'seal_time': timeText(s.sealTime),
};
/// The detail of [v] as tool/security_go_vectors.go writes Go's, null
/// without one.
Json? detailJson(Verdicts v) {
final d = v.detail;
if (d == null) return null;
return {
'signers': [for (final s in d.signers) signerJson(s)],
'foreign': [for (final s in d.foreign) signerJson(s)],
'seal_holder': d.sealHolder,
if (timeText(d.sealTime) != null) 'seal_time': timeText(d.sealTime),
};
}
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>
3 days ago
/// The bytes of [hex] or null.
Uint8List? hexOrNull(Object? hex) =>
hex == null ? null : fromHex(hex as String);
// ---------------------------------------------------------------------------
// The sections of test/vectors/security_vectors.json
/// The contexts of the vectors, by index.
List<SecurityContext> contextsOf(Json f) => [
for (final c in (f['contexts']! as List).cast<Json>())
SecurityContext(
controlCommit: fromHex(str(c, 'control_commit')),
headDigest: fromHex(str(c, 'head_digest')),
roundTime: c['round_time'] == null
? null
: parseRfc3339(str(c, 'round_time')),
authorKeys:
(c['author_keys'] as Map?)?.cast<String, String>() ?? const {},
),
];
/// The bytes of [parts], [hex, repeat] runs.
Uint8List fromParts(List<Object?> parts) => concatBytes([
for (final p in parts.cast<List<Object?>>())
for (var i = 0; i < (p[1]! as int); i++) fromHex(p[0]! as String),
]);
/// The bytes of the field [name] of [c], given as hex or as name_parts.
Uint8List? blobOf(Json c, String name) {
final parts = c['${name}_parts'] as List?;
if (parts != null) return fromParts(parts.cast<Object?>());
return hexOrNull(c[name]);
}
/// SECURITY_CBOR of an evaluation: its hex or parts, or a base of [bases]
/// with its edits, of the area or of the content of its key 2 or 3, which
/// is then written again and checked against the first 8 bytes of the
/// SHA-256 of Go's.
Uint8List securityOf(Json c, List<Uint8List> bases) {
final hex = c['hex'] as String?;
if (hex != null) return fromHex(hex);
final parts = c['parts'] as List?;
if (parts != null) return fromParts(parts.cast<Object?>());
final base = bases[c['base']! as int];
final edits = (c['edits']! as List).cast<Object?>();
final key = c['key'] as int?;
if (key == null) return applyEdits(base, edits);
final w = decodeSecurity(base)!;
final out = encodeSecurityWith(
signature: key == 2 ? applyEdits(w.signature!, edits) : w.signature,
seal: key == 3 ? applyEdits(w.seal!, edits) : w.seal,
);
if (toHex(sha256(out).sublist(0, 8)) != c['sha256']) {
throw StateError('the area of ${canonical(c)} is not the one of Go');
}
return out;
}
/// The differences between the evaluation of the case [c] and Go's: its
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>
3 days ago
/// verdicts, lines and detail, the parts of CMS, and alg and seal_type as
/// read.
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>
3 days ago
List<String> evaluateDifferences(
Json c,
Uint8List security,
List<SecurityContext> contexts,
List<String> texts,
) {
final out = <String>[];
final at = c['context'] as int?;
final context = at == null ? null : contexts[at];
final v = evaluateSecurity(security, context: context);
final goCms = ((c['cms'] as List?) ?? const []).cast<String>();
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>
3 days ago
// The parts that the reader of CMS evaluates, as this library reads the
// area: those of Go, in a context.
final mine = cmsParts(security);
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>
3 days ago
final cms = (
signature: goCms.contains('signature'),
seal: goCms.contains('seal'),
);
if (context != null && mine != cms || context == null && goCms.isNotEmpty) {
out.add('cms: $mine, Go $goCms');
}
final w = decodeSecurity(security);
final sig = w?.signature;
final seal = w?.seal;
final alg = sig == null ? null : decodeAuthorSignature(sig)?.alg;
final sealType = seal == null ? null : decodeSeal(seal)?.sealType;
if (alg != c['alg']) out.add('alg $alg, Go ${c['alg']}');
if (sealType != c['seal_type']) {
out.add('seal_type $sealType, Go ${c['seal_type']}');
}
if ((w == null) != (c['signature'] == 'X')) {
out.add('decodeSecurity gives ${w == null ? 'X' : 'an area'}');
}
final want = {
...c,
'lines': [for (final i in (c['lines']! as List).cast<int>()) texts[i]],
};
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>
3 days ago
out.addAll(verdictDifferences(want, v));
// Go's detail, the signers of alg 2 and the authority of a valid seal,
// which the generator writes whenever Go has one.
if (canonical(detailJson(v)) != canonical(c['detail'])) {
out.add('detail ${canonical(detailJson(v))}');
}
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>
3 days ago
return out;
}
/// The verdicts of a case of lines, as Go built them.
Verdicts verdictsOf(Json c) {
final d = c['detail'] as Json?;
SignerLine signer(Json s) => SignerLine(
holder: str(s, 'holder'),
issuer: str(s, 'issuer'),
result: SignerResult.fromCode(str(s, 'result'))!,
sealHolder: str(s, 'seal_holder'),
sealTime: s['seal_time'] == null ? null : parseRfc3339(str(s, 'seal_time')),
before: s['before']! as bool,
);
return Verdicts(
signature: Verdict.fromCode(str(c, 'signature')),
seal: Verdict.fromCode(str(c, 'seal')),
authorKey: fromHex(str(c, 'author_key')),
authorLabel: str(c, 'author_label'),
detail: d == null
? null
: Detail(
signers: [
for (final s in (d['signers']! as List).cast<Json>()) signer(s),
],
foreign: [
for (final s in (d['foreign']! as List).cast<Json>()) signer(s),
],
sealHolder: str(d, 'seal_holder'),
sealTime: d['seal_time'] == null
? null
: parseRfc3339(str(d, 'seal_time')),
),
);
}
/// The differences of the lines and the earliest seal of a case of lines.
List<String> lineDifferences(Json c) {
final v = verdictsOf(c);
final out = <String>[];
if (canonical(v.lines) != canonical(c['lines'])) {
out.add('lines ${canonical(v.lines)}');
}
final at = v.sealedAt;
final got = at == null ? null : formatRfc3339Nano(at);
if (got != c['sealed_at']) out.add('sealed_at $got');
return out;
}
/// The name of a case of holder: its text, or its UTF-16 code units.
String nameOf(Json c) => c['units'] == null
? str(c, 'name')
: String.fromCharCodes((c['units']! as List).cast<int>());
/// The differences of the commitments of the vectors.
List<String> commitmentDifferences(Json f) {
final out = <String>[];
void same(String what, Object? got, Object? want) {
if (got != want) out.add('$what: got $got, want $want');
}
List<Json> section(String name) => (f[name]! as List).cast<Json>();
for (final c in section('payload_commit')) {
same(
'payload_commit',
toHex(payloadCommit(fromHex(str(c, 'identity')))),
c['commit'],
);
}
for (final c in section('control_commit')) {
final decoded = decodeControl(
fromHex(str(c, 'control')),
CapsuleFormat.fromVersion(c['decode_format']! as int)!,
);
final format = CapsuleFormat.fromVersion(c['format']! as int)!;
String got;
try {
got = toHex(controlCommit(decoded, format));
} on ArgumentError catch (e) {
got = 'error: ${e.message}';
} on DateKeysException catch (e) {
got = 'error: ${e.message}';
}
same(
'control_commit of ${c['name']} in format ${format.version}',
got,
c['commit'] ?? 'error: ${c['error']}',
);
}
for (final c in section('head_digest')) {
same(
'head_digest',
toHex(headDigest(fromHex(str(c, 'head')))),
c['digest'],
);
}
for (final c in section('signers_digest')) {
same(
'signers_digest',
toHex(signersDigest(c['alg']! as int, hexOrNull(c['signers']))),
c['digest'],
);
}
for (final c in section('author_message')) {
final m = authorMessage(
fromHex(str(c, 'control_commit')),
fromHex(str(c, 'head_digest')),
fromHex(str(c, 'signers_digest')),
);
same('author_message', String.fromCharCodes(m), c['message']);
same('author_code', authorCode(m), c['code']);
}
for (final c in section('author_code')) {
final code = authorCode(fromHex(str(c, 'message')));
same('author_code of ${c['message']}', code, c['code']);
// When Go's code is UTF-8, these are its bytes.
final bytes = fromHex(str(c, 'code_hex'));
if (decodeUtf8(bytes) != null) {
same('the bytes of author_code', toHex(utf8Bytes(code)), c['code_hex']);
}
}
for (final c in section('sig_part')) {
same('sig_part', toHex(sigPart(hexOrNull(c['signature']))), c['sig_part']);
}
for (final c in section('seal_subject')) {
same(
'seal_subject',
toHex(
sealSubject(
fromHex(str(c, 'control_commit')),
fromHex(str(c, 'head_digest')),
fromHex(str(c, 'sig_part')),
),
),
c['seal_subject'],
);
}
return out;
}
/// The differences of the encoders.
List<String> encodeDifferences(List<Json> cases) {
final out = <String>[];
for (final c in cases) {
final Uint8List got;
switch (c['what']) {
case 'security':
got = encodeSecurity();
case 'security_with':
got = encodeSecurityWith(
signature: blobOf(c, 'signature'),
seal: blobOf(c, 'seal'),
);
case 'author_signature':
got = encodeAuthorSignature(
c['alg']! as int,
fromHex(str(c, 'key')),
fromHex(str(c, 'value')),
);
default:
got = encodeSeal(c['seal_type']! as int, fromHex(str(c, 'token')));
}
if (!equalBytes(got, blobOf(c, 'hex')!)) out.add('encode ${canonical(c)}');
}
return out;
}
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>
3 days ago
// ---------------------------------------------------------------------------
// testdata/vectors/security_cms.json
/// The results of the signers [lines] as security_cms.json and the records
/// of the fixtures write them, as vectorSignerResults of Go's
/// cmsvectors_test.go: t with its fraction, only for a seal that verifies.
List<Json> signerResults(List<SignerLine> lines) => [
for (final l in lines)
{
'holder': l.holder,
'issuer': l.issuer,
'result': l.result.code,
if (timeText(l.sealTime) != null) 'seal_time': timeText(l.sealTime),
'before_round_time': l.before,
},
];
/// What a case of security_cms.json records of the verdicts [v], as
/// TestCMSVectors of Go reads them: the verdicts, the results of the
/// required signers and of the foreign ones, each list only when it is not
/// empty, the authority and t of a valid seal of key 3, and the lines.
Json cmsVectorOf(Verdicts v) {
final d = v.detail;
final when = d == null ? null : timeText(d.sealTime);
return {
'signature': v.signature?.code,
'seal': v.seal?.code,
if (d != null && d.signers.isNotEmpty) 'signers': signerResults(d.signers),
if (d != null && d.foreign.isNotEmpty)
'foreign_signers': signerResults(d.foreign),
if (when != null) 'seal_holder': d!.sealHolder,
'seal_time': ?when,
'lines': v.lines,
};
}
/// The context of a case of security_cms.json.
SecurityContext cmsVectorContext(Json c) {
final ctx = c['context']! as Json;
return SecurityContext(
controlCommit: fromHex(str(ctx, 'control_commit')),
headDigest: fromHex(str(ctx, 'head_digest')),
roundTime: parseRfc3339(str(ctx, 'round_time')),
);
}
/// The differences between the case [c] of security_cms.json and its
/// evaluation in its context, as TestCMSVectors of Go checks them: the
/// verdicts, the results, the seal and the lines, byte for byte, and no line
/// with a control or a bidirectional character.
List<String> cmsVectorDifferences(Json c) {
final v = evaluateSecurity(
fromHex(str(c, 'security_cbor')),
context: cmsVectorContext(c),
);
final out = <String>[];
final want = {
for (final k in const [
'signature',
'seal',
'signers',
'foreign_signers',
'seal_holder',
'seal_time',
'lines',
])
if (c.containsKey(k)) k: c[k],
};
final got = cmsVectorOf(v);
if (canonical(got) != canonical(want)) out.add('got ${canonical(got)}');
for (final line in v.lines) {
for (final r in line.runes) {
if (r < 0x20 ||
r >= 0x7f && r <= 0x9f ||
r >= 0x202a && r <= 0x202e ||
r >= 0x2066 && r <= 0x2069 ||
r == 0xfeff) {
out.add('a line with U+${r.toRadixString(16)}: $line');
}
}
}
return out;
}

Powered by TurnKey Linux.