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/capsule/cmsvectors_test.go

109 lines
4.1 KiB

package capsule_test
import (
"encoding/hex"
"path/filepath"
"reflect"
security_cms.json for spec v0.12: 135 cases, each with its lines The frozen vector of alg 2 and seal_type 2, made again with the profile of v0.12: - each case carries the lines of Verdicts.Lines, so that a second implementation compares the texts byte for byte, and its times keep the fraction of the token; - the two cases without a context, which gave the verdicts of a reader of v0.10, are gone, and the case named a seal from before the certificate was valid, which gave an invalid seal, is named so; - new cases for each row of §29.7 and each item of the lists of §64 for v0.11 and v0.12: out of validity with a valid authority, SIGNERS that break its rule beside a valid CMS (out of order, empty, 17 entries, 31 bytes, a hash twice) and 16 signers, the version against the sid, two content-type attributes, the ESSCertIDv2, PSS with and without trailerField, an arc of 2^31, a certificate twice or of version 1, keys outside the table, every hash and curve of the table, BER, two SignerInfo of one certificate, two time-stamps, the names of the holder and of the issuer in each string type and against each rule, and the edges of the token: accuracy, genTime, ordering, fields after the last, the imprint, crls and the authority. The generator checks each case against what the spec gives, written apart from the code: the verdicts, the result of each signer and the lines, built from the texts of §29.7. It fails when the reader gives anything else. capsule reads every field of the file, the lines included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
"slices"
"strings"
"testing"
"time"
datekeys "g.activething.com/go/DateKeys"
"g.activething.com/go/DateKeys/capsule"
"g.activething.com/go/DateKeys/internal/testkit"
)
// testdata/vectors/security_cms.json is frozen: each case is evaluated again,
security_cms.json for spec v0.12: 135 cases, each with its lines The frozen vector of alg 2 and seal_type 2, made again with the profile of v0.12: - each case carries the lines of Verdicts.Lines, so that a second implementation compares the texts byte for byte, and its times keep the fraction of the token; - the two cases without a context, which gave the verdicts of a reader of v0.10, are gone, and the case named a seal from before the certificate was valid, which gave an invalid seal, is named so; - new cases for each row of §29.7 and each item of the lists of §64 for v0.11 and v0.12: out of validity with a valid authority, SIGNERS that break its rule beside a valid CMS (out of order, empty, 17 entries, 31 bytes, a hash twice) and 16 signers, the version against the sid, two content-type attributes, the ESSCertIDv2, PSS with and without trailerField, an arc of 2^31, a certificate twice or of version 1, keys outside the table, every hash and curve of the table, BER, two SignerInfo of one certificate, two time-stamps, the names of the holder and of the issuer in each string type and against each rule, and the edges of the token: accuracy, genTime, ordering, fields after the last, the imprint, crls and the authority. The generator checks each case against what the spec gives, written apart from the code: the verdicts, the result of each signer and the lines, built from the texts of §29.7. It fails when the reader gives anything else. capsule reads every field of the file, the lines included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
// with its context, and must give its verdicts, the result of each signer,
// the authority and the time of a valid seal, and its lines, byte for byte
// (spec v0.16 §29.7, §29.10, §29.11).
func TestCMSVectors(t *testing.T) {
var f testkit.CMSVectorFile
if err := testkit.ReadJSON(filepath.Join("..", "testdata", "vectors", "security_cms.json"), &f); err != nil {
t.Fatal(err)
}
if f.Spec != datekeys.SpecVersion || !strings.Contains(f.Description, "v0.16") || len(f.Cases) < 140 {
security_cms.json for spec v0.12: 135 cases, each with its lines The frozen vector of alg 2 and seal_type 2, made again with the profile of v0.12: - each case carries the lines of Verdicts.Lines, so that a second implementation compares the texts byte for byte, and its times keep the fraction of the token; - the two cases without a context, which gave the verdicts of a reader of v0.10, are gone, and the case named a seal from before the certificate was valid, which gave an invalid seal, is named so; - new cases for each row of §29.7 and each item of the lists of §64 for v0.11 and v0.12: out of validity with a valid authority, SIGNERS that break its rule beside a valid CMS (out of order, empty, 17 entries, 31 bytes, a hash twice) and 16 signers, the version against the sid, two content-type attributes, the ESSCertIDv2, PSS with and without trailerField, an arc of 2^31, a certificate twice or of version 1, keys outside the table, every hash and curve of the table, BER, two SignerInfo of one certificate, two time-stamps, the names of the holder and of the issuer in each string type and against each rule, and the edges of the token: accuracy, genTime, ordering, fields after the last, the imprint, crls and the authority. The generator checks each case against what the spec gives, written apart from the code: the verdicts, the result of each signer and the lines, built from the texts of §29.7. It fails when the reader gives anything else. capsule reads every field of the file, the lines included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
t.Fatalf("spec %q, %d cases: %s", f.Spec, len(f.Cases), f.Description)
}
security_cms.json for spec v0.12: 135 cases, each with its lines The frozen vector of alg 2 and seal_type 2, made again with the profile of v0.12: - each case carries the lines of Verdicts.Lines, so that a second implementation compares the texts byte for byte, and its times keep the fraction of the token; - the two cases without a context, which gave the verdicts of a reader of v0.10, are gone, and the case named a seal from before the certificate was valid, which gave an invalid seal, is named so; - new cases for each row of §29.7 and each item of the lists of §64 for v0.11 and v0.12: out of validity with a valid authority, SIGNERS that break its rule beside a valid CMS (out of order, empty, 17 entries, 31 bytes, a hash twice) and 16 signers, the version against the sid, two content-type attributes, the ESSCertIDv2, PSS with and without trailerField, an arc of 2^31, a certificate twice or of version 1, keys outside the table, every hash and curve of the table, BER, two SignerInfo of one certificate, two time-stamps, the names of the holder and of the issuer in each string type and against each rule, and the edges of the token: accuracy, genTime, ordering, fields after the last, the imprint, crls and the authority. The generator checks each case against what the spec gives, written apart from the code: the verdicts, the result of each signer and the lines, built from the texts of §29.7. It fails when the reader gives anything else. capsule reads every field of the file, the lines included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
seen := map[string]bool{}
verdicts := map[string]bool{}
for _, c := range f.Cases {
security_cms.json for spec v0.12: 135 cases, each with its lines The frozen vector of alg 2 and seal_type 2, made again with the profile of v0.12: - each case carries the lines of Verdicts.Lines, so that a second implementation compares the texts byte for byte, and its times keep the fraction of the token; - the two cases without a context, which gave the verdicts of a reader of v0.10, are gone, and the case named a seal from before the certificate was valid, which gave an invalid seal, is named so; - new cases for each row of §29.7 and each item of the lists of §64 for v0.11 and v0.12: out of validity with a valid authority, SIGNERS that break its rule beside a valid CMS (out of order, empty, 17 entries, 31 bytes, a hash twice) and 16 signers, the version against the sid, two content-type attributes, the ESSCertIDv2, PSS with and without trailerField, an arc of 2^31, a certificate twice or of version 1, keys outside the table, every hash and curve of the table, BER, two SignerInfo of one certificate, two time-stamps, the names of the holder and of the issuer in each string type and against each rule, and the edges of the token: accuracy, genTime, ordering, fields after the last, the imprint, crls and the authority. The generator checks each case against what the spec gives, written apart from the code: the verdicts, the result of each signer and the lines, built from the texts of §29.7. It fails when the reader gives anything else. capsule reads every field of the file, the lines included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
if seen[c.Name] {
t.Errorf("two cases named %q", c.Name)
}
seen[c.Name] = true
verdicts[c.Signature] = true
verdicts[c.Seal] = true
t.Run(c.Name, func(t *testing.T) {
area, err := hex.DecodeString(c.SecurityCBOR)
if err != nil {
t.Fatal(err)
}
security_cms.json for spec v0.12: 135 cases, each with its lines The frozen vector of alg 2 and seal_type 2, made again with the profile of v0.12: - each case carries the lines of Verdicts.Lines, so that a second implementation compares the texts byte for byte, and its times keep the fraction of the token; - the two cases without a context, which gave the verdicts of a reader of v0.10, are gone, and the case named a seal from before the certificate was valid, which gave an invalid seal, is named so; - new cases for each row of §29.7 and each item of the lists of §64 for v0.11 and v0.12: out of validity with a valid authority, SIGNERS that break its rule beside a valid CMS (out of order, empty, 17 entries, 31 bytes, a hash twice) and 16 signers, the version against the sid, two content-type attributes, the ESSCertIDv2, PSS with and without trailerField, an arc of 2^31, a certificate twice or of version 1, keys outside the table, every hash and curve of the table, BER, two SignerInfo of one certificate, two time-stamps, the names of the holder and of the issuer in each string type and against each rule, and the edges of the token: accuracy, genTime, ordering, fields after the last, the imprint, crls and the authority. The generator checks each case against what the spec gives, written apart from the code: the verdicts, the result of each signer and the lines, built from the texts of §29.7. It fails when the reader gives anything else. capsule reads every field of the file, the lines included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
var sc capsule.SecurityContext
cc, err1 := hex.DecodeString(c.Context.ControlCommit)
hd, err2 := hex.DecodeString(c.Context.HeadDigest)
if err1 != nil || err2 != nil || len(cc) != 32 || len(hd) != 32 {
t.Fatalf("the context: %+v", c.Context)
}
copy(sc.ControlCommit[:], cc)
copy(sc.HeadDigest[:], hd)
if sc.RoundTime, err = time.Parse(time.RFC3339, c.Context.RoundTime); err != nil {
t.Fatal(err)
}
security_cms.json for spec v0.12: 135 cases, each with its lines The frozen vector of alg 2 and seal_type 2, made again with the profile of v0.12: - each case carries the lines of Verdicts.Lines, so that a second implementation compares the texts byte for byte, and its times keep the fraction of the token; - the two cases without a context, which gave the verdicts of a reader of v0.10, are gone, and the case named a seal from before the certificate was valid, which gave an invalid seal, is named so; - new cases for each row of §29.7 and each item of the lists of §64 for v0.11 and v0.12: out of validity with a valid authority, SIGNERS that break its rule beside a valid CMS (out of order, empty, 17 entries, 31 bytes, a hash twice) and 16 signers, the version against the sid, two content-type attributes, the ESSCertIDv2, PSS with and without trailerField, an arc of 2^31, a certificate twice or of version 1, keys outside the table, every hash and curve of the table, BER, two SignerInfo of one certificate, two time-stamps, the names of the holder and of the issuer in each string type and against each rule, and the edges of the token: accuracy, genTime, ordering, fields after the last, the imprint, crls and the authority. The generator checks each case against what the spec gives, written apart from the code: the verdicts, the result of each signer and the lines, built from the texts of §29.7. It fails when the reader gives anything else. capsule reads every field of the file, the lines included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
v := capsule.EvaluateSecurityIn(area, &sc)
if string(v.Signature) != c.Signature || string(v.Seal) != c.Seal {
t.Fatalf("verdicts %s and %s, want %s and %s", v.Signature, v.Seal, c.Signature, c.Seal)
}
var signers, foreign []testkit.FixtureSignerResult
var holder, when, reason string
if d := v.Detail; d != nil {
security_cms.json for spec v0.12: 135 cases, each with its lines The frozen vector of alg 2 and seal_type 2, made again with the profile of v0.12: - each case carries the lines of Verdicts.Lines, so that a second implementation compares the texts byte for byte, and its times keep the fraction of the token; - the two cases without a context, which gave the verdicts of a reader of v0.10, are gone, and the case named a seal from before the certificate was valid, which gave an invalid seal, is named so; - new cases for each row of §29.7 and each item of the lists of §64 for v0.11 and v0.12: out of validity with a valid authority, SIGNERS that break its rule beside a valid CMS (out of order, empty, 17 entries, 31 bytes, a hash twice) and 16 signers, the version against the sid, two content-type attributes, the ESSCertIDv2, PSS with and without trailerField, an arc of 2^31, a certificate twice or of version 1, keys outside the table, every hash and curve of the table, BER, two SignerInfo of one certificate, two time-stamps, the names of the holder and of the issuer in each string type and against each rule, and the edges of the token: accuracy, genTime, ordering, fields after the last, the imprint, crls and the authority. The generator checks each case against what the spec gives, written apart from the code: the verdicts, the result of each signer and the lines, built from the texts of §29.7. It fails when the reader gives anything else. capsule reads every field of the file, the lines included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
signers, foreign = vectorSignerResults(d.Signers), vectorSignerResults(d.Foreign)
if !d.SealTime.IsZero() {
security_cms.json for spec v0.12: 135 cases, each with its lines The frozen vector of alg 2 and seal_type 2, made again with the profile of v0.12: - each case carries the lines of Verdicts.Lines, so that a second implementation compares the texts byte for byte, and its times keep the fraction of the token; - the two cases without a context, which gave the verdicts of a reader of v0.10, are gone, and the case named a seal from before the certificate was valid, which gave an invalid seal, is named so; - new cases for each row of §29.7 and each item of the lists of §64 for v0.11 and v0.12: out of validity with a valid authority, SIGNERS that break its rule beside a valid CMS (out of order, empty, 17 entries, 31 bytes, a hash twice) and 16 signers, the version against the sid, two content-type attributes, the ESSCertIDv2, PSS with and without trailerField, an arc of 2^31, a certificate twice or of version 1, keys outside the table, every hash and curve of the table, BER, two SignerInfo of one certificate, two time-stamps, the names of the holder and of the issuer in each string type and against each rule, and the edges of the token: accuracy, genTime, ordering, fields after the last, the imprint, crls and the authority. The generator checks each case against what the spec gives, written apart from the code: the verdicts, the result of each signer and the lines, built from the texts of §29.7. It fails when the reader gives anything else. capsule reads every field of the file, the lines included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
holder, when = d.SealHolder, d.SealTime.UTC().Format(time.RFC3339Nano)
}
reason = string(d.SealReason)
}
if !reflect.DeepEqual(signers, c.Signers) || !reflect.DeepEqual(foreign, c.Foreign) || holder != c.SealHolder || when != c.SealTime || reason != c.SealReason {
t.Errorf("signers %+v foreign %+v seal %q %q %q; want %+v %+v %q %q %q", signers, foreign, holder, when, reason, c.Signers, c.Foreign, c.SealHolder, c.SealTime, c.SealReason)
}
security_cms.json for spec v0.12: 135 cases, each with its lines The frozen vector of alg 2 and seal_type 2, made again with the profile of v0.12: - each case carries the lines of Verdicts.Lines, so that a second implementation compares the texts byte for byte, and its times keep the fraction of the token; - the two cases without a context, which gave the verdicts of a reader of v0.10, are gone, and the case named a seal from before the certificate was valid, which gave an invalid seal, is named so; - new cases for each row of §29.7 and each item of the lists of §64 for v0.11 and v0.12: out of validity with a valid authority, SIGNERS that break its rule beside a valid CMS (out of order, empty, 17 entries, 31 bytes, a hash twice) and 16 signers, the version against the sid, two content-type attributes, the ESSCertIDv2, PSS with and without trailerField, an arc of 2^31, a certificate twice or of version 1, keys outside the table, every hash and curve of the table, BER, two SignerInfo of one certificate, two time-stamps, the names of the holder and of the issuer in each string type and against each rule, and the edges of the token: accuracy, genTime, ordering, fields after the last, the imprint, crls and the authority. The generator checks each case against what the spec gives, written apart from the code: the verdicts, the result of each signer and the lines, built from the texts of §29.7. It fails when the reader gives anything else. capsule reads every field of the file, the lines included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
if lines := v.Lines(); !slices.Equal(lines, c.Lines) {
t.Errorf("lines %q, want %q", lines, c.Lines)
}
// No line of the verdicts carries a control or a bidi character,
// whatever the certificates say (spec §29.7).
for _, line := range c.Lines {
for _, r := range line {
if r < 0x20 || r >= 0x7f && r <= 0x9f || r >= 0x202a && r <= 0x202e || r >= 0x2066 && r <= 0x2069 || r == 0xfeff {
t.Errorf("a line with %U: %q", r, line)
}
}
}
})
}
security_cms.json for spec v0.12: 135 cases, each with its lines The frozen vector of alg 2 and seal_type 2, made again with the profile of v0.12: - each case carries the lines of Verdicts.Lines, so that a second implementation compares the texts byte for byte, and its times keep the fraction of the token; - the two cases without a context, which gave the verdicts of a reader of v0.10, are gone, and the case named a seal from before the certificate was valid, which gave an invalid seal, is named so; - new cases for each row of §29.7 and each item of the lists of §64 for v0.11 and v0.12: out of validity with a valid authority, SIGNERS that break its rule beside a valid CMS (out of order, empty, 17 entries, 31 bytes, a hash twice) and 16 signers, the version against the sid, two content-type attributes, the ESSCertIDv2, PSS with and without trailerField, an arc of 2^31, a certificate twice or of version 1, keys outside the table, every hash and curve of the table, BER, two SignerInfo of one certificate, two time-stamps, the names of the holder and of the issuer in each string type and against each rule, and the edges of the token: accuracy, genTime, ordering, fields after the last, the imprint, crls and the authority. The generator checks each case against what the spec gives, written apart from the code: the verdicts, the result of each signer and the lines, built from the texts of §29.7. It fails when the reader gives anything else. capsule reads every field of the file, the lines included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
// Every verdict of alg 2 and of seal_type 2 has a case.
for _, want := range []capsule.Verdict{
capsule.VerdictNoSignature, capsule.VerdictSignatureUnchecked, capsule.VerdictSignatureInvalid, capsule.VerdictSignedOther,
capsule.VerdictSignedIncomplete, capsule.VerdictSignedComplete, capsule.VerdictNoSeal, capsule.VerdictSealUnsupported,
capsule.VerdictSealUnreadable, capsule.VerdictSealInvalid, capsule.VerdictSealed, capsule.VerdictSealedLate,
} {
if !verdicts[string(want)] {
t.Errorf("no case gives %s", want)
}
}
}
// vectorSignerResults are the results of the signers as security_cms.json
// writes them: t with the fraction of its token when it has one.
func vectorSignerResults(lines []capsule.SignerLine) []testkit.FixtureSignerResult {
var out []testkit.FixtureSignerResult
for _, l := range lines {
r := testkit.FixtureSignerResult{Holder: l.Holder, Issuer: l.Issuer, Result: l.Result, Before: l.Before, SealReason: string(l.Reason)}
security_cms.json for spec v0.12: 135 cases, each with its lines The frozen vector of alg 2 and seal_type 2, made again with the profile of v0.12: - each case carries the lines of Verdicts.Lines, so that a second implementation compares the texts byte for byte, and its times keep the fraction of the token; - the two cases without a context, which gave the verdicts of a reader of v0.10, are gone, and the case named a seal from before the certificate was valid, which gave an invalid seal, is named so; - new cases for each row of §29.7 and each item of the lists of §64 for v0.11 and v0.12: out of validity with a valid authority, SIGNERS that break its rule beside a valid CMS (out of order, empty, 17 entries, 31 bytes, a hash twice) and 16 signers, the version against the sid, two content-type attributes, the ESSCertIDv2, PSS with and without trailerField, an arc of 2^31, a certificate twice or of version 1, keys outside the table, every hash and curve of the table, BER, two SignerInfo of one certificate, two time-stamps, the names of the holder and of the issuer in each string type and against each rule, and the edges of the token: accuracy, genTime, ordering, fields after the last, the imprint, crls and the authority. The generator checks each case against what the spec gives, written apart from the code: the verdicts, the result of each signer and the lines, built from the texts of §29.7. It fails when the reader gives anything else. capsule reads every field of the file, the lines included. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
if !l.SealTime.IsZero() {
r.SealTime = l.SealTime.UTC().Format(time.RFC3339Nano)
}
out = append(out, r)
}
return out
}

Powered by TurnKey Linux.