// Package cmstest builds the CMS signatures and the RFC 3161 tokens that the // tests of internal/cms and of capsule read, and that the generator of the // test vectors writes: certificates of test keys, made by crypto/x509 or field // by field (cert.go), a detached signature of a message with its signedAttrs // and, optionally, a time-stamp token of its signature, with options to write // what the profiles of spec §29.10 and §29.11 reject, or what verifies to // something else, and edits of the DER of the result (edit.go). It is the // encoder that a signing application has; nothing outside tests uses it. package cmstest import ( "bytes" "crypto" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/rsa" "crypto/sha1" "crypto/sha256" "crypto/sha512" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" "fmt" "math/big" "slices" "strings" "time" ) // Cert is a certificate as a signature or a token names it. type Cert struct { // Raw is the DER of the certificate. Raw []byte // RawIssuer is the DER of its issuer, Serial the DER of its serialNumber, // an INTEGER, and SubjectKeyId the keyIdentifier of its extension // subjectKeyIdentifier, nil without it: what a sid names. RawIssuer, Serial, SubjectKeyId []byte } // Signer is a certificate with its private key. type Signer struct { Cert *Cert Key crypto.Signer } // RSAKey returns a new RSA key of bits bits. func RSAKey(bits int) *rsa.PrivateKey { k, err := rsa.GenerateKey(rand.Reader, bits) if err != nil { panic(err) } return k } // ECKey returns a new ECDSA key on curve. func ECKey(curve elliptic.Curve) *ecdsa.PrivateKey { k, err := ecdsa.GenerateKey(curve, rand.Reader) if err != nil { panic(err) } return k } // NewRSA returns a signer with an RSA key of bits bits, valid in // [notBefore, notAfter], named cn, with a certificate that crypto/x509 makes. func NewRSA(cn string, bits int, notBefore, notAfter time.Time) Signer { return newSigner(cn, RSAKey(bits), notBefore, notAfter) } // NewECDSA returns a signer with an ECDSA key on curve, with a certificate // that crypto/x509 makes. func NewECDSA(cn string, curve elliptic.Curve, notBefore, notAfter time.Time) Signer { return newSigner(cn, ECKey(curve), notBefore, notAfter) } func newSigner(cn string, k crypto.Signer, notBefore, notAfter time.Time) Signer { serial, _ := rand.Int(rand.Reader, big.NewInt(1<<62)) t := &x509.Certificate{ SerialNumber: serial, Subject: pkix.Name{CommonName: cn, Organization: []string{"DateKeys test"}}, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageDigitalSignature, SubjectKeyId: []byte(cn), } raw, err := x509.CreateCertificate(rand.Reader, t, t, k.Public(), k) if err != nil { panic(err) } c, err := x509.ParseCertificate(raw) if err != nil { panic(err) } return Signer{Cert: &Cert{Raw: c.Raw, RawIssuer: c.RawIssuer, Serial: mustMarshal(c.SerialNumber), SubjectKeyId: c.SubjectKeyId}, Key: k} } // The DER building blocks. func tlv(tag byte, content ...[]byte) []byte { c := bytes.Join(content, nil) out := []byte{tag} switch n := len(c); { case n < 0x80: out = append(out, byte(n)) case n < 0x100: out = append(out, 0x81, byte(n)) case n < 0x10000: out = append(out, 0x82, byte(n>>8), byte(n)) default: out = append(out, 0x83, byte(n>>16), byte(n>>8), byte(n)) } return append(out, c...) } // TLV builds an element of any tag from the encodings of its content. func TLV(tag byte, content ...[]byte) []byte { return tlv(tag, content...) } // Seq is a SEQUENCE. func Seq(content ...[]byte) []byte { return tlv(0x30, content...) } // Set is a SET OF with the identifier octet tag, in DER order. A SET OF in // another order is TLV(tag, elems...). func Set(tag byte, elems ...[]byte) []byte { e := slices.Clone(elems) slices.SortFunc(e, bytes.Compare) return tlv(tag, e...) } // OID is an OBJECT IDENTIFIER. func OID(oid asn1.ObjectIdentifier) []byte { return mustMarshal(oid) } // OIDBytes is an OBJECT IDENTIFIER with the content as given: an arc of any // size, or a content that is not one. func OIDBytes(content []byte) []byte { return tlv(0x06, content) } // Octets is an OCTET STRING. func Octets(b []byte) []byte { return tlv(0x04, b) } // Int is an INTEGER. func Int(n int64) []byte { return mustMarshal(n) } // BigInt is an INTEGER of any size. func BigInt(n *big.Int) []byte { return mustMarshal(n) } // IntBytes is an INTEGER with the content as given, minimal or not. func IntBytes(content []byte) []byte { return tlv(0x02, content) } // Null is a NULL. func Null() []byte { return []byte{0x05, 0x00} } // Bool is a BOOLEAN, as DER writes it. func Bool(v bool) []byte { if v { return []byte{0x01, 0x01, 0xff} } return []byte{0x01, 0x01, 0x00} } // BitString is a BIT STRING of whole bytes. func BitString(b []byte) []byte { return tlv(0x03, append([]byte{0}, b...)) } // UTCTime builds a UTCTime with the text s. func UTCTime(s string) []byte { return tlv(0x17, []byte(s)) } // GeneralizedTime builds a GeneralizedTime with the text s. func GeneralizedTime(s string) []byte { return tlv(0x18, []byte(s)) } // GeneralizedTimeOf builds the GeneralizedTime of t in UTC as DER writes it: // the fraction of a second only when there is one, without trailing zeros. func GeneralizedTimeOf(t time.Time) []byte { t = t.UTC() s := t.Format("20060102150405") if ns := t.Nanosecond(); ns != 0 { s += "." + strings.TrimRight(fmt.Sprintf("%09d", ns), "0") } return GeneralizedTime(s + "Z") } // CertTimeOf builds a time of validity as RFC 5280 4.1.2.5 writes it: UTCTime // until 2049 and GeneralizedTime from 2050, without a fraction. func CertTimeOf(t time.Time) []byte { t = t.UTC().Truncate(time.Second) if t.Year() < 2050 { return UTCTime(t.Format("060102150405") + "Z") } return GeneralizedTimeOf(t) } // AlgID is an AlgorithmIdentifier. func AlgID(oid asn1.ObjectIdentifier, params ...[]byte) []byte { return Seq(append([][]byte{OID(oid)}, params...)...) } func mustMarshal(v any) []byte { b, err := asn1.Marshal(v) if err != nil { panic(err) } return b } // The object identifiers. var ( OIDData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1} OIDSignedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2} OIDContentType = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 3} OIDMessageDigest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 4} OIDSigningTime = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 5} OIDSigCertV1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 12} OIDSigCertV2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 47} OIDTimeStamp = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 2, 14} OIDTSTInfo = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 1, 4} OIDOCSP = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 16, 2} OIDSHA1 = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26} OIDSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1} OIDSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2} OIDSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3} OIDRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} OIDMGF1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 8} OIDPSS = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10} OIDSHA256RSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} OIDSHA384RSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} OIDSHA512RSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} OIDECDSASHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} OIDECDSA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} OIDECDSA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} OIDECDSA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} OIDECPublicKey = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} OIDP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} OIDP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} OIDP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} OIDBrainpoolP256 = asn1.ObjectIdentifier{1, 3, 36, 3, 3, 2, 8, 1, 1, 7} ) // HashAlg is the AlgorithmIdentifier of h, without parameters: SHA-1, // SHA-256, SHA-384 or SHA-512. func HashAlg(h crypto.Hash) []byte { return AlgID(hashOID(h)) } func hashOID(h crypto.Hash) asn1.ObjectIdentifier { switch h { case crypto.SHA1: return OIDSHA1 case crypto.SHA384: return OIDSHA384 case crypto.SHA512: return OIDSHA512 } return OIDSHA256 } func ecdsaOID(h crypto.Hash) asn1.ObjectIdentifier { switch h { case crypto.SHA1: return OIDECDSASHA1 case crypto.SHA384: return OIDECDSA384 case crypto.SHA512: return OIDECDSA512 } return OIDECDSA256 } func sum(h crypto.Hash, b []byte) []byte { switch h { case crypto.SHA1: s := sha1.Sum(b) return s[:] case crypto.SHA384: s := sha512.Sum384(b) return s[:] case crypto.SHA512: s := sha512.Sum512(b) return s[:] } s := sha256.Sum256(b) return s[:] } // hashNamed returns the hash that the AlgorithmIdentifier a names, SHA-256 // for one that this package does not write. func hashNamed(a []byte) crypto.Hash { for _, h := range []crypto.Hash{crypto.SHA1, crypto.SHA384, crypto.SHA512} { if bytes.HasPrefix(a[2:], OID(hashOID(h))) { return h } } return crypto.SHA256 } // Options changes what Signature and Token write, to make signatures that the // profile rejects or that verify to something else. The zero value writes // what AutoFirma writes. type Options struct { // Hash is the digest of the signature, SHA-256 by default; SHA-1 writes // ecdsa-with-SHA1 for an ECDSA key. Hash crypto.Hash // PSS signs with RSASSA-PSS instead of PKCS #1 v1.5, and PSSTrailer // writes trailerField [3] 1 in its parameters, which is its default and // DER does not write. PSS, PSSTrailer bool // SKI names the signer by subjectKeyIdentifier instead of by issuer and // serial. SKI bool // Version is the version of each SignerInfo; 0 writes 1 with // issuerAndSerialNumber and 3 with subjectKeyIdentifier (RFC 5652 5.3). Version int // DigestAlg, when not nil, is written as the digestAlgorithm of each // SignerInfo instead of that of Hash. DigestAlg []byte // SigAlg, when not nil, is written as the signatureAlgorithm instead of // the one of the key; the key still signs with its own scheme. SigAlg []byte // CorruptSignature flips a bit of each signature value, after signing. CorruptSignature bool // Message is what the message-digest covers, when not the signed message. Message []byte // ContentType2 adds a second content-type attribute, the same as the // first, and NoMessageDigest leaves the message-digest out. ContentType2, NoMessageDigest bool // SigCertV1 adds a signing-certificate attribute (RFC 2634) beside the // v2. SigCertV2 writes signing-certificate-v2 in a token, which writes // signing-certificate by default; NoSigCertV2 leaves it out of a // signature. SigCertV1, SigCertV2, NoSigCertV2 bool // ESSHashAlg, when not nil, is written as the hashAlgorithm of the // ESSCertIDv2, which DER leaves out for SHA-256, its default; certHash is // the hash that it names. ESSCert, when not nil, is the certificate whose // hash certHash gives, instead of that of the signer. ESSHashAlg, ESSCert []byte // ExtraAttrs are added to the signed attributes, as the DER of each. ExtraAttrs [][]byte // UnsortedAttrs writes the signed attributes in descending order: not a // SET OF of DER. They are signed as written. UnsortedAttrs bool // Mutate edits the signedAttrs, as a list of the DER of each attribute, // before they are signed. Mutate func(attrs [][]byte) [][]byte // Token, when not nil, is the time-stamp token of the signature that // Signature puts as an unsigned attribute: it receives the signature // value. Token2 puts it in one attribute with a second value, and // TimeStamps2 adds a second signature-time-stamp attribute with a token // of its own. Token func(signature []byte) []byte Token2, TimeStamps2 bool // Junk adds an unsigned attribute of this many bytes, which decides // nothing, to make a signature as large as a chain of certificates. Junk int // ExtraUnsigned are added to the unsigned attributes, as the DER of each. ExtraUnsigned [][]byte // OmitCert leaves the certificate of each signer out of certificates, // and ExtraCerts adds these, as the DER of each: the certificate of a // signer for a repetition, a certificate that breaks the profile, or // another choice of CertificateChoices. OmitCert bool ExtraCerts [][]byte // OCSP adds this response in crls, as an OtherRevocationInfoFormat of // id-ri-ocsp-response, and CRLs adds these elements in crls as given. OCSP []byte CRLs [][]byte // SignerInfoTwice writes each SignerInfo twice, Unsorted writes // signerInfos in descending order, and BER writes the ContentInfo with // an indefinite length. SignerInfoTwice, Unsorted, BER bool // EditSignerInfo edits the fields of each SignerInfo after it is signed, // and EditSignedData the fields of the SignedData. EditSignerInfo, EditSignedData func(fields [][]byte) [][]byte } // Attr is an Attribute of the type with the values, in DER order. func Attr(oid asn1.ObjectIdentifier, values ...[]byte) []byte { return Seq(OID(oid), Set(0x31, values...)) } // BigArcAttr is an attribute whose type has an arc of 2^31: an identifier // that the profile does not name, and decides nothing (spec §29.10). func BigArcAttr() []byte { // 1.2.840.113549.1.9.2147483648: the last arc is 2^31. return Seq(OIDBytes([]byte{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x88, 0x80, 0x80, 0x80, 0x00}), Set(0x31, Null())) } // Signature returns the detached CMS signature of message by the signers, in // DER, as AutoFirma writes it: one SignerInfo each, with content-type, // message-digest and signing-certificate-v2 as signed attributes. func Signature(message []byte, opts Options, signers ...Signer) []byte { return build(message, opts, false, signers) } // TokenRaw returns a token that tsa signs over the given TSTInfo, as it is: // for tests that need a TSTInfo that Token would not write. func TokenRaw(tstInfo []byte, tsa Signer) []byte { return build(tstInfo, Options{Hash: crypto.SHA256}, true, []Signer{tsa}) } // TokenRawWith is TokenRaw with the options of the SignedData of the token. func TokenRawWith(tstInfo []byte, o Options, tsa Signer) []byte { return build(tstInfo, o, true, []Signer{tsa}) } func build(content []byte, o Options, token bool, signers []Signer) []byte { if o.Hash == 0 { o.Hash = crypto.SHA256 } var certs, infos [][]byte for _, s := range signers { if !o.OmitCert { certs = append(certs, s.Cert.Raw) } info := signerInfo(content, o, token, s) infos = append(infos, info) if o.SignerInfoTwice { infos = append(infos, info) } } certs = append(certs, o.ExtraCerts...) fields := [][]byte{Int(1), Set(0x31, HashAlg(o.Hash)), encap(content, token)} if len(certs) > 0 { fields = append(fields, Set(0xa0, certs...)) } var crls [][]byte if o.OCSP != nil { crls = append(crls, tlv(0xa1, OID(OIDOCSP), o.OCSP)) } if crls = append(crls, o.CRLs...); len(crls) > 0 { fields = append(fields, Set(0xa1, crls...)) } if o.Unsorted { slices.SortFunc(infos, func(a, b []byte) int { return bytes.Compare(b, a) }) fields = append(fields, tlv(0x31, infos...)) } else { fields = append(fields, Set(0x31, infos...)) } if o.EditSignedData != nil { fields = o.EditSignedData(fields) } ci := Seq(OID(OIDSignedData), tlv(0xa0, Seq(fields...))) if o.BER { return Indefinite(ci) } return ci } func encap(content []byte, token bool) []byte { if !token { return Seq(OID(OIDData)) } return Seq(OID(OIDTSTInfo), tlv(0xa0, Octets(content))) } // essCertID returns the SigningCertificate (v1, SHA-1) or the // SigningCertificateV2 of a certificate. func essCertID(cert []byte, o Options, v2 bool) []byte { if o.ESSCert != nil { cert = o.ESSCert } if !v2 { h := sha1.Sum(cert) return Seq(Seq(Seq(Octets(h[:])))) } if o.ESSHashAlg == nil { h := sha256.Sum256(cert) return Seq(Seq(Seq(Octets(h[:])))) } return Seq(Seq(Seq(o.ESSHashAlg, Octets(sum(hashNamed(o.ESSHashAlg), cert))))) } func signerInfo(message []byte, o Options, token bool, s Signer) []byte { sid := Seq(s.Cert.RawIssuer, s.Cert.Serial) if o.SKI { sid = tlv(0x80, s.Cert.SubjectKeyId) } contentType := OIDData if token { contentType = OIDTSTInfo } md := message if o.Message != nil { md = o.Message } attrs := [][]byte{Attr(OIDContentType, OID(contentType))} if o.ContentType2 { attrs = append(attrs, attrs[0]) } if !o.NoMessageDigest { attrs = append(attrs, Attr(OIDMessageDigest, Octets(sum(o.Hash, md)))) } switch { case token && !o.SigCertV2: attrs = append(attrs, Attr(OIDSigCertV1, essCertID(s.Cert.Raw, o, false))) case !o.NoSigCertV2: attrs = append(attrs, Attr(OIDSigCertV2, essCertID(s.Cert.Raw, o, true))) } if o.SigCertV1 { attrs = append(attrs, Attr(OIDSigCertV1, essCertID(s.Cert.Raw, Options{}, false))) } attrs = append(attrs, o.ExtraAttrs...) if o.Mutate != nil { attrs = o.Mutate(attrs) } var signed []byte if o.UnsortedAttrs { attrs = slices.Clone(attrs) slices.SortFunc(attrs, func(a, b []byte) int { return bytes.Compare(b, a) }) signed = tlv(0xa0, attrs...) } else { signed = Set(0xa0, attrs...) } // The signature covers the signedAttrs with the tag of a SET. digest := sum(o.Hash, append([]byte{0x31}, signed[1:]...)) sigAlg, sig := sign(s.Key, o, digest) if o.SigAlg != nil { sigAlg = o.SigAlg } if o.CorruptSignature { sig[len(sig)/2] ^= 1 } version := int64(1) if o.SKI { version = 3 } if o.Version != 0 { version = int64(o.Version) } digestAlg := HashAlg(o.Hash) if o.DigestAlg != nil { digestAlg = o.DigestAlg } f := [][]byte{Int(version), sid, digestAlg, signed, sigAlg, Octets(sig)} var unsigned [][]byte if o.Junk > 0 { unsigned = append(unsigned, Attr(asn1.ObjectIdentifier{1, 2, 3, 4, 5}, Octets(make([]byte, o.Junk)))) } if o.Token != nil { t := o.Token(sig) if o.Token2 { unsigned = append(unsigned, Seq(OID(OIDTimeStamp), Set(0x31, t, Seq(OID(OIDData))))) } else { unsigned = append(unsigned, Attr(OIDTimeStamp, t)) } if o.TimeStamps2 { unsigned = append(unsigned, Attr(OIDTimeStamp, o.Token(sig))) } } unsigned = append(unsigned, o.ExtraUnsigned...) if len(unsigned) > 0 { f = append(f, Set(0xa1, unsigned...)) } if o.EditSignerInfo != nil { f = o.EditSignerInfo(f) } return Seq(f...) } // sign signs digest with key and returns the signatureAlgorithm of the key // and the signature value. func sign(key crypto.Signer, o Options, digest []byte) (sigAlg, sig []byte) { var err error switch k := key.(type) { case *rsa.PrivateKey: if o.PSS { params := [][]byte{tlv(0xa0, HashAlg(o.Hash)), tlv(0xa1, AlgID(OIDMGF1, HashAlg(o.Hash))), tlv(0xa2, Int(int64(o.Hash.Size())))} if o.PSSTrailer { params = append(params, tlv(0xa3, Int(1))) } sigAlg = AlgID(OIDPSS, Seq(params...)) sig, err = rsa.SignPSS(rand.Reader, k, o.Hash, digest, &rsa.PSSOptions{SaltLength: o.Hash.Size(), Hash: o.Hash}) } else { sigAlg = AlgID(OIDRSA, Null()) sig, err = rsa.SignPKCS1v15(rand.Reader, k, o.Hash, digest) } case *ecdsa.PrivateKey: sigAlg = AlgID(ecdsaOID(o.Hash)) sig, err = ecdsa.SignASN1(rand.Reader, k, digest) default: panic(fmt.Sprintf("cmstest: a key of type %T", key)) } if err != nil { panic(err) } return sigAlg, sig } // TokenOptions changes what Token writes. type TokenOptions struct { // Hash is the hash of the messageImprint, SHA-256 by default. Hash crypto.Hash // Accuracy is written as its seconds, millis and micros, each only when // it is not zero; zero writes no accuracy. AccuracyRaw, when not nil, is // the element of the accuracy as given: negative, not minimal, 0 or 1000. Accuracy time.Duration AccuracyRaw []byte // Version is the version of the TSTInfo, 1 by default. Version int // Imprint, when not nil, is written as the hashed message instead of the // hash of the subject, of any length. Imprint []byte // GenTimeRaw, when not nil, is written as genTime instead of the // GeneralizedTime of the time given: free text, or another type. GenTimeRaw []byte // OrderingFalse writes ordering FALSE, its default, which DER does not // write; After are elements written after the accuracy and the ordering: // nonce, tsa and extensions, or anything after the last field. OrderingFalse bool After [][]byte // SigCertV2 signs with signing-certificate-v2 instead of // signing-certificate (ESSCertID). SigCertV2 bool // NoMessageDigest leaves the message-digest out of the token, CRL puts // this element in its crls, and TSATwice writes the certificate of the // authority twice in its certificates. NoMessageDigest, TSATwice bool CRL []byte // CMS are the options of the SignedData of the token; its Hash is the // digest of the signature of the authority, SHA-256 by default. CMS Options } // AccuracyOf is the Accuracy element of d: its seconds, millis and micros, // each only when it is not zero. func AccuracyOf(d time.Duration) []byte { var f [][]byte if s := d / time.Second; s != 0 { f = append(f, Int(int64(s))) } if ms := d % time.Second / time.Millisecond; ms != 0 { f = append(f, tlv(0x80, Int(int64(ms))[2:])) } if us := d % time.Millisecond / time.Microsecond; us != 0 { f = append(f, tlv(0x81, Int(int64(us))[2:])) } return Seq(f...) } // TSTInfo returns the TSTInfo that Token signs. func TSTInfo(subject []byte, genTime time.Time, o TokenOptions) []byte { if o.Hash == 0 { o.Hash = crypto.SHA256 } if o.Version == 0 { o.Version = 1 } imprint := sum(o.Hash, subject) if o.Imprint != nil { imprint = o.Imprint } gt := GeneralizedTimeOf(genTime) if o.GenTimeRaw != nil { gt = o.GenTimeRaw } info := [][]byte{Int(int64(o.Version)), OID(asn1.ObjectIdentifier{1, 2, 3, 4}), Seq(HashAlg(o.Hash), Octets(imprint)), Int(42), gt} switch { case o.AccuracyRaw != nil: info = append(info, o.AccuracyRaw) case o.Accuracy != 0: info = append(info, AccuracyOf(o.Accuracy)) } if o.OrderingFalse { info = append(info, Bool(false)) } return Seq(append(info, o.After...)...) } // Token returns the RFC 3161 time-stamp token that tsa issues over subject // at genTime. func Token(subject []byte, genTime time.Time, o TokenOptions, tsa Signer) []byte { cms := o.CMS cms.SigCertV2 = cms.SigCertV2 || o.SigCertV2 cms.NoMessageDigest = cms.NoMessageDigest || o.NoMessageDigest if o.CRL != nil { cms.CRLs = append(slices.Clone(cms.CRLs), o.CRL) } if o.TSATwice { cms.ExtraCerts = append(slices.Clone(cms.ExtraCerts), tsa.Cert.Raw) } return build(TSTInfo(subject, genTime, o), cms, true, []Signer{tsa}) }