package cms_test import ( "bytes" "crypto" "crypto/ecdsa" "crypto/elliptic" "encoding/asn1" "math/big" "testing" "time" "g.activething.com/go/DateKeys/internal/cms" "g.activething.com/go/DateKeys/internal/cms/cmstest" ) var ( p384Key = cmstest.ECKey(elliptic.P384()) p521Key = cmstest.ECKey(elliptic.P521()) ) // pss is the AlgorithmIdentifier of RSASSA-PSS with the fields of its // parameters given. func pss(fields ...[]byte) []byte { return cmstest.AlgID(cmstest.OIDPSS, cmstest.Seq(fields...)) } // Spec §29.10, "Algoritmos" and step 2 of "Verificación": the closed table of // algorithms, and a key of another scheme than its algorithm, which is // invalid and not outside the table (step 3). func TestAlgorithmTable(t *testing.T) { alg, null := cmstest.AlgID, cmstest.Null h0 := cmstest.TLV(0xa0, cmstest.HashAlg(crypto.SHA256)) m1 := cmstest.TLV(0xa1, alg(cmstest.OIDMGF1, cmstest.HashAlg(crypto.SHA256))) s2 := cmstest.TLV(0xa2, cmstest.Int(32)) p384 := cmstest.NewCert(cmstest.CertSpec{CN: "P-384"}, p384Key) p521 := cmstest.NewCert(cmstest.CertSpec{CN: "P-521"}, p521Key) for name, tc := range map[string]struct { s cmstest.Signer o cmstest.Options want cms.Result }{ "SHA-1, ECDSA": {ana, cmstest.Options{Hash: crypto.SHA1}, cms.NotVerifiable}, "SHA-1, RSA": {luis, cmstest.Options{Hash: crypto.SHA1}, cms.NotVerifiable}, "SHA-1, and another message": {ana, cmstest.Options{Hash: crypto.SHA1, Message: []byte("other")}, cms.NotVerifiable}, "SHA-256 with NULL": {ana, cmstest.Options{DigestAlg: alg(cmstest.OIDSHA256, null())}, cms.Valid}, "SHA-256 with an INTEGER": {ana, cmstest.Options{DigestAlg: alg(cmstest.OIDSHA256, cmstest.Int(0))}, cms.NotVerifiable}, "P-256 with SHA-384": {ana, cmstest.Options{Hash: crypto.SHA384}, cms.Valid}, "P-256 with SHA-512": {ana, cmstest.Options{Hash: crypto.SHA512}, cms.Valid}, "P-384 with SHA-384": {p384, cmstest.Options{Hash: crypto.SHA384}, cms.Valid}, "P-521 with SHA-512": {p521, cmstest.Options{Hash: crypto.SHA512}, cms.Valid}, "P-521 with SHA-256": {p521, cmstest.Options{}, cms.Valid}, "rsaEncryption": {luis, cmstest.Options{}, cms.Valid}, "rsaEncryption without parameters": {luis, cmstest.Options{SigAlg: alg(cmstest.OIDRSA)}, cms.Valid}, "rsaEncryption with an INTEGER": {luis, cmstest.Options{SigAlg: alg(cmstest.OIDRSA, cmstest.Int(0))}, cms.NotVerifiable}, "rsaEncryption with SHA-512": {luis, cmstest.Options{Hash: crypto.SHA512}, cms.Valid}, "sha256WithRSAEncryption": {luis, cmstest.Options{SigAlg: alg(cmstest.OIDSHA256RSA, null())}, cms.Valid}, "sha256WithRSAEncryption without NULL": {luis, cmstest.Options{SigAlg: alg(cmstest.OIDSHA256RSA)}, cms.Valid}, "sha256WithRSAEncryption, INTEGER": {luis, cmstest.Options{SigAlg: alg(cmstest.OIDSHA256RSA, cmstest.Int(0))}, cms.NotVerifiable}, "sha256WithRSAEncryption, SHA-384": {luis, cmstest.Options{Hash: crypto.SHA384, SigAlg: alg(cmstest.OIDSHA256RSA, null())}, cms.NotVerifiable}, "sha384WithRSAEncryption": {luis, cmstest.Options{Hash: crypto.SHA384, SigAlg: alg(cmstest.OIDSHA384RSA, null())}, cms.Valid}, "sha384WithRSAEncryption, SHA-256": {luis, cmstest.Options{SigAlg: alg(cmstest.OIDSHA384RSA, null())}, cms.NotVerifiable}, "sha384WithRSAEncryption, INTEGER": {luis, cmstest.Options{Hash: crypto.SHA384, SigAlg: alg(cmstest.OIDSHA384RSA, cmstest.Int(0))}, cms.NotVerifiable}, "sha512WithRSAEncryption": {luis, cmstest.Options{Hash: crypto.SHA512, SigAlg: alg(cmstest.OIDSHA512RSA, null())}, cms.Valid}, "sha512WithRSAEncryption, SHA-256": {luis, cmstest.Options{SigAlg: alg(cmstest.OIDSHA512RSA, null())}, cms.NotVerifiable}, "sha512WithRSAEncryption, INTEGER": {luis, cmstest.Options{Hash: crypto.SHA512, SigAlg: alg(cmstest.OIDSHA512RSA, cmstest.Int(0))}, cms.NotVerifiable}, "ecdsa-with-SHA256 with NULL": {ana, cmstest.Options{SigAlg: alg(cmstest.OIDECDSA256, null())}, cms.NotVerifiable}, "ecdsa-with-SHA256, SHA-384": {ana, cmstest.Options{Hash: crypto.SHA384, SigAlg: alg(cmstest.OIDECDSA256)}, cms.NotVerifiable}, "ecdsa-with-SHA384, SHA-256": {ana, cmstest.Options{SigAlg: alg(cmstest.OIDECDSA384)}, cms.NotVerifiable}, "ecdsa-with-SHA384 with NULL": {ana, cmstest.Options{Hash: crypto.SHA384, SigAlg: alg(cmstest.OIDECDSA384, null())}, cms.NotVerifiable}, "ecdsa-with-SHA512, SHA-256": {ana, cmstest.Options{SigAlg: alg(cmstest.OIDECDSA512)}, cms.NotVerifiable}, "ecdsa-with-SHA512 with NULL": {ana, cmstest.Options{Hash: crypto.SHA512, SigAlg: alg(cmstest.OIDECDSA512, null())}, cms.NotVerifiable}, "an algorithm outside the table": {ana, cmstest.Options{SigAlg: alg(asn1.ObjectIdentifier{1, 3, 101, 112})}, cms.NotVerifiable}, "another algorithm, an RSA key": {luis, cmstest.Options{SigAlg: alg(asn1.ObjectIdentifier{1, 3, 101, 112})}, cms.NotVerifiable}, "another algorithm with PSS parameters": {luis, cmstest.Options{PSS: true, SigAlg: alg(asn1.ObjectIdentifier{1, 2, 3, 4}, cmstest.Seq(h0, m1, s2))}, cms.NotVerifiable}, "PSS": {luis, cmstest.Options{PSS: true}, cms.Valid}, "PSS with SHA-384": {luis, cmstest.Options{PSS: true, Hash: crypto.SHA384}, cms.Valid}, "PSS, its fields written again": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, m1, s2)}, cms.Valid}, "PSS with NULL in its hashes": {luis, cmstest.Options{PSS: true, SigAlg: pss(cmstest.TLV(0xa0, alg(cmstest.OIDSHA256, null())), cmstest.TLV(0xa1, alg(cmstest.OIDMGF1, alg(cmstest.OIDSHA256, null()))), s2)}, cms.Valid}, "PSS without parameters": {luis, cmstest.Options{PSS: true, SigAlg: alg(cmstest.OIDPSS)}, cms.NotVerifiable}, "PSS with NULL parameters": {luis, cmstest.Options{PSS: true, SigAlg: alg(cmstest.OIDPSS, null())}, cms.NotVerifiable}, "PSS parameters as a SET": {luis, cmstest.Options{PSS: true, SigAlg: alg(cmstest.OIDPSS, cmstest.TLV(0x31, h0, m1, s2))}, cms.NotVerifiable}, "PSS with [0] of two elements": {luis, cmstest.Options{PSS: true, SigAlg: pss(cmstest.TLV(0xa0, cmstest.HashAlg(crypto.SHA256), null()), m1, s2)}, cms.NotVerifiable}, "PSS with [0] primitive": {luis, cmstest.Options{PSS: true, SigAlg: pss(cmstest.TLV(0x80, cmstest.HashAlg(crypto.SHA256)), m1, s2)}, cms.NotVerifiable}, "PSS with [1] before [0]": {luis, cmstest.Options{PSS: true, SigAlg: pss(m1, h0, s2)}, cms.NotVerifiable}, "PSS with [0] twice": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, h0, m1, s2)}, cms.NotVerifiable}, "PSS of SHA-512 with SHA-256": {luis, cmstest.Options{PSS: true, SigAlg: pss(cmstest.TLV(0xa0, cmstest.HashAlg(crypto.SHA512)), m1, s2)}, cms.NotVerifiable}, "PSS with a hash of an INTEGER": {luis, cmstest.Options{PSS: true, SigAlg: pss(cmstest.TLV(0xa0, alg(cmstest.OIDSHA256, cmstest.Int(0))), m1, s2)}, cms.NotVerifiable}, "PSS with a hash without an OID": {luis, cmstest.Options{PSS: true, SigAlg: pss(cmstest.TLV(0xa0, cmstest.Seq(cmstest.Int(0))), m1, s2)}, cms.NotVerifiable}, "PSS with another mask": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, cmstest.TLV(0xa1, alg(asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 9}, cmstest.HashAlg(crypto.SHA256))), s2)}, cms.NotVerifiable}, "PSS with MGF1 without its hash": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, cmstest.TLV(0xa1, alg(cmstest.OIDMGF1)), s2)}, cms.NotVerifiable}, "PSS with MGF1 not an algorithm": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, cmstest.TLV(0xa1, cmstest.Seq(cmstest.Int(1))), s2)}, cms.NotVerifiable}, "PSS with MGF1 of SHA-512": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, cmstest.TLV(0xa1, alg(cmstest.OIDMGF1, cmstest.HashAlg(crypto.SHA512))), s2)}, cms.NotVerifiable}, "PSS with MGF1 of a hash with INTEGER": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, cmstest.TLV(0xa1, alg(cmstest.OIDMGF1, alg(cmstest.OIDSHA256, cmstest.Int(0)))), s2)}, cms.NotVerifiable}, "PSS with MGF1 of a hash without OID": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, cmstest.TLV(0xa1, alg(cmstest.OIDMGF1, cmstest.Seq(cmstest.Int(0)))), s2)}, cms.NotVerifiable}, "PSS with a salt of 20": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, m1, cmstest.TLV(0xa2, cmstest.Int(20)))}, cms.NotVerifiable}, "PSS with a salt in OCTETS": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, m1, cmstest.TLV(0xa2, cmstest.Octets([]byte{32})))}, cms.NotVerifiable}, "PSS with a salt of 2^64 + 32": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, m1, cmstest.TLV(0xa2, cmstest.IntBytes([]byte{1, 0, 0, 0, 0, 0, 0, 0, 32})))}, cms.NotVerifiable}, "PSS with a negative salt": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, m1, cmstest.TLV(0xa2, cmstest.Int(-224)))}, cms.NotVerifiable}, "PSS with trailerField": {luis, cmstest.Options{PSS: true, PSSTrailer: true}, cms.NotVerifiable}, "PSS with a field [4]": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, m1, s2, cmstest.TLV(0xa4, cmstest.Int(1)))}, cms.NotVerifiable}, "PSS without [0]": {luis, cmstest.Options{PSS: true, SigAlg: pss(m1, s2)}, cms.NotVerifiable}, "PSS without [1]": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, s2)}, cms.NotVerifiable}, "PSS without [2]": {luis, cmstest.Options{PSS: true, SigAlg: pss(h0, m1)}, cms.NotVerifiable}, "step 3: an RSA key with ECDSA": {luis, cmstest.Options{SigAlg: alg(cmstest.OIDECDSA256)}, cms.Invalid}, "step 3: an EC key with PKCS #1": {ana, cmstest.Options{SigAlg: alg(cmstest.OIDRSA, null())}, cms.Invalid}, "step 3: an EC key with PSS": {ana, cmstest.Options{SigAlg: pss(h0, m1, s2)}, cms.Invalid}, "step 3: PKCS #1, a bit flipped": {luis, cmstest.Options{CorruptSignature: true}, cms.Invalid}, "step 3: PSS, a bit flipped": {luis, cmstest.Options{PSS: true, CorruptSignature: true}, cms.Invalid}, "step 3: ECDSA, a bit flipped": {ana, cmstest.Options{CorruptSignature: true}, cms.Invalid}, "step 3: the digest of another message": {ana, cmstest.Options{Message: []byte("other")}, cms.Invalid}, } { if got := resultOf(t, name, cmstest.Signature(msg, tc.o, tc.s)); got != tc.want { t.Errorf("%s: %v, want %v", name, got, tc.want) } } } // The keys of the table (spec §29.10): RSA with NULL parameters, exactly a // modulus and an exponent, the modulus odd of 2048 to 4096 bits and the // exponent odd from 3 to 2^31 - 1; EC on P-256, P-384 or P-521, the point // uncompressed and on the curve. Any other is not verifiable; a key of the // table that does not verify the signature is invalid. func TestKeyTable(t *testing.T) { n, e := rsaKey.N, big.NewInt(65537) two := func(bits uint) *big.Int { return new(big.Int).Add(new(big.Int).Lsh(big.NewInt(1), bits), big.NewInt(1)) } key := func(fields ...[]byte) []byte { return cmstest.BitString(cmstest.Seq(fields...)) } rsaAlg := cmstest.AlgID(cmstest.OIDRSA, cmstest.Null()) ecAlg := cmstest.AlgID(cmstest.OIDECPublicKey, cmstest.OID(cmstest.OIDP256)) point := cmstest.Uncompressed(&ecKey.PublicKey) off := bytes.Clone(point) off[len(off)-1] ^= 1 even := evenPointKey() evenPoint := cmstest.Uncompressed(&even.PublicKey) for name, tc := range map[string]struct { spki []byte key crypto.Signer want cms.Result }{ "RSA of 2048 bits": {cmstest.SPKIRSA(n, e), rsaKey, cms.Valid}, "RSA of 2047 bits": {cmstest.SPKIRSA(two(2046), e), rsaKey, cms.NotVerifiable}, "RSA of 4096 bits that is another": {cmstest.SPKIRSA(two(4095), e), rsaKey, cms.Invalid}, "RSA of 4097 bits": {cmstest.SPKIRSA(two(4096), e), rsaKey, cms.NotVerifiable}, "an even modulus": {cmstest.SPKIRSA(new(big.Int).Add(n, big.NewInt(1)), e), rsaKey, cms.NotVerifiable}, "a negative modulus": {cmstest.SPKIRSA(new(big.Int).Neg(n), e), rsaKey, cms.NotVerifiable}, "an exponent of 1": {cmstest.SPKIRSA(n, big.NewInt(1)), rsaKey, cms.NotVerifiable}, "an exponent of 3": {cmstest.SPKIRSA(n, big.NewInt(3)), rsaKey, cms.Invalid}, "an even exponent": {cmstest.SPKIRSA(n, big.NewInt(65536)), rsaKey, cms.NotVerifiable}, "an exponent of 2^31 - 1": {cmstest.SPKIRSA(n, big.NewInt(1<<31-1)), rsaKey, cms.Invalid}, "an exponent of 2^64 + 65537": {cmstest.SPKIRSA(n, new(big.Int).Add(new(big.Int).Lsh(big.NewInt(1), 64), e)), rsaKey, cms.NotVerifiable}, "a negative exponent": {cmstest.SPKIRSA(n, big.NewInt(-1)), rsaKey, cms.NotVerifiable}, "an RSAPublicKey with a byte more": {cmstest.Seq(rsaAlg, cmstest.BitString(append(cmstest.Seq(cmstest.BigInt(n), cmstest.BigInt(e)), 0))), rsaKey, cms.NotVerifiable}, "an RSAPublicKey as a SET": {cmstest.Seq(rsaAlg, cmstest.BitString(cmstest.TLV(0x31, cmstest.BigInt(n), cmstest.BigInt(e)))), rsaKey, cms.NotVerifiable}, "an RSAPublicKey of three INTEGERs": {cmstest.Seq(rsaAlg, key(cmstest.BigInt(n), cmstest.BigInt(e), cmstest.Int(1))), rsaKey, cms.NotVerifiable}, "an RSAPublicKey that is an INTEGER": {cmstest.Seq(rsaAlg, cmstest.BitString(cmstest.BigInt(n))), rsaKey, cms.NotVerifiable}, "a modulus in OCTETS": {cmstest.Seq(rsaAlg, key(cmstest.Octets(append([]byte{0}, n.Bytes()...)), cmstest.BigInt(e))), rsaKey, cms.NotVerifiable}, "an exponent in OCTETS": {cmstest.Seq(rsaAlg, key(cmstest.BigInt(n), cmstest.Octets(e.Bytes()))), rsaKey, cms.NotVerifiable}, "rsaEncryption without NULL": {cmstest.Seq(cmstest.AlgID(cmstest.OIDRSA), key(cmstest.BigInt(n), cmstest.BigInt(e))), rsaKey, cms.NotVerifiable}, "an RSA key of id-RSASSA-PSS": {cmstest.Seq(cmstest.AlgID(cmstest.OIDPSS, cmstest.Null()), key(cmstest.BigInt(n), cmstest.BigInt(e))), rsaKey, cms.NotVerifiable}, "an SPKI of three elements": {cmstest.Seq(rsaAlg, key(cmstest.BigInt(n), cmstest.BigInt(e)), cmstest.Null()), rsaKey, cms.NotVerifiable}, "an SPKI whose key is OCTETS": {cmstest.Seq(rsaAlg, cmstest.Octets(append([]byte{0}, cmstest.Seq(cmstest.BigInt(n), cmstest.BigInt(e))...))), rsaKey, cms.NotVerifiable}, "an SPKI whose algorithm is a SET": {cmstest.Seq(cmstest.TLV(0x31, cmstest.OID(cmstest.OIDRSA), cmstest.Null()), key(cmstest.BigInt(n), cmstest.BigInt(e))), rsaKey, cms.NotVerifiable}, "an SPKI of no algorithm": {cmstest.Seq(cmstest.Seq(cmstest.Int(1)), key(cmstest.BigInt(n), cmstest.BigInt(e))), rsaKey, cms.NotVerifiable}, "P-256": {cmstest.SPKIEC(cmstest.OID(cmstest.OIDP256), point), ecKey, cms.Valid}, "a compressed point": {cmstest.SPKICompressed(&ecKey.PublicKey), ecKey, cms.NotVerifiable}, "a point off the curve": {cmstest.SPKIEC(cmstest.OID(cmstest.OIDP256), off), ecKey, cms.NotVerifiable}, "a point of P-256 said P-384": {cmstest.SPKIEC(cmstest.OID(cmstest.OIDP384), point), ecKey, cms.NotVerifiable}, "brainpoolP256r1": {cmstest.SPKIEC(cmstest.OID(cmstest.OIDBrainpoolP256), point), ecKey, cms.NotVerifiable}, "a point of P-521, another curve": {cmstest.SPKIEC(cmstest.OID(cmstest.OIDBrainpoolP256), cmstest.Uncompressed(&p521Key.PublicKey)), p521Key, cms.NotVerifiable}, "id-ecPublicKey without a curve": {cmstest.Seq(cmstest.AlgID(cmstest.OIDECPublicKey), cmstest.BitString(point)), ecKey, cms.NotVerifiable}, "id-ecPublicKey with NULL": {cmstest.SPKIEC(cmstest.Null(), point), ecKey, cms.NotVerifiable}, "an EC key of id-ecDH": {cmstest.Seq(cmstest.AlgID(asn1.ObjectIdentifier{1, 3, 132, 1, 12}, cmstest.OID(cmstest.OIDP256)), cmstest.BitString(point)), ecKey, cms.NotVerifiable}, "a BIT STRING of 1 unused bit": {cmstest.Seq(ecAlg, cmstest.TLV(0x03, append([]byte{1}, evenPoint...))), even, cms.NotVerifiable}, "an empty BIT STRING": {cmstest.Seq(ecAlg, cmstest.TLV(0x03, []byte{0})), ecKey, cms.NotVerifiable}, } { s := cmstest.NewCert(cmstest.CertSpec{CN: "Clave", SPKI: tc.spki}, tc.key) if got := resultOf(t, name, cmstest.Signature(msg, cmstest.Options{}, s)); got != tc.want { t.Errorf("%s: %v, want %v", name, got, tc.want) } } } // evenPointKey returns a P-256 key whose point ends in an even byte: a BIT // STRING with one unused bit holds it in DER. func evenPointKey() *ecdsa.PrivateKey { for { k := cmstest.ECKey(elliptic.P256()) if p := cmstest.Uncompressed(&k.PublicKey); p[len(p)-1]&1 == 0 { return k } } } // Spec §29.11: the token in the order of its profile, form (S2), algorithms // (S1) and verification (S3). func TestTokenProfile(t *testing.T) { subject := []byte("seal subject") tok := func(o cmstest.TokenOptions, s cmstest.Signer) []byte { return cmstest.Token(subject, now, o, s) } small := cmstest.NewCert(cmstest.CertSpec{CN: "TSA 1024"}, cmstest.RSAKey(1024)) compressed := cmstest.NewCert(cmstest.CertSpec{CN: "TSA comprimida", SPKI: cmstest.SPKICompressed(&ecKey2.PublicKey)}, ecKey2) notYet := cmstest.NewCert(cmstest.CertSpec{CN: "TSA futura", From: now.Add(time.Second)}, ecKey2) expired := cmstest.NewCert(cmstest.CertSpec{CN: "TSA caducada", To: now.Add(-time.Second)}, ecKey2) exact := cmstest.NewCert(cmstest.CertSpec{CN: "TSA justa", From: now, To: now}, ecKey2) badImprintAlg := func() []byte { info := cmstest.Seq(cmstest.Int(1), cmstest.OID(asn1.ObjectIdentifier{1, 2, 3, 4}), cmstest.Seq(cmstest.Seq(cmstest.Int(1)), cmstest.Octets(make([]byte, 32))), cmstest.Int(42), cmstest.GeneralizedTimeOf(now)) return cmstest.TokenRaw(info, tsa) } for name, tc := range map[string]struct { token []byte form bool // S2, else S1 }{ "S1: an imprint of SHA-1": {tok(cmstest.TokenOptions{Hash: crypto.SHA1}, tsa), false}, "S1: a signature of SHA-1": {tok(cmstest.TokenOptions{CMS: cmstest.Options{Hash: crypto.SHA1}}, tsa), false}, "S1: a key of 1024 bits": {tok(cmstest.TokenOptions{}, small), false}, "S1: a compressed key": {tok(cmstest.TokenOptions{}, compressed), false}, "S1: PSS with trailerField": {tok(cmstest.TokenOptions{CMS: cmstest.Options{PSS: true, PSSTrailer: true}}, luis), false}, "S2 before S1: SHA-1 and version 2": {tok(cmstest.TokenOptions{Hash: crypto.SHA1, Version: 2}, tsa), true}, "S2 before S1: SHA-1 and no digest": {tok(cmstest.TokenOptions{Hash: crypto.SHA1, NoMessageDigest: true}, tsa), true}, "S2: an imprint algorithm that is no one": {badImprintAlg(), true}, } { _, err := cms.ParseToken(tc.token) if tc.form && !isForm(err) || !tc.form && !isAlgorithm(err) { t.Errorf("%s: %v", name, err) } } // S3: it reads, and does not verify. for name, b := range map[string][]byte{ "the signature of the authority, a bit flipped": tok(cmstest.TokenOptions{CMS: cmstest.Options{CorruptSignature: true}}, tsa), "the message-digest of another TSTInfo": tok(cmstest.TokenOptions{CMS: cmstest.Options{Message: []byte("other")}}, tsa), "an imprint of 33 bytes": tok(cmstest.TokenOptions{Imprint: append(sha256Of(subject), 0)}, tsa), "an imprint of 31 bytes": tok(cmstest.TokenOptions{Imprint: sha256Of(subject)[:31]}, tsa), "another imprint": tok(cmstest.TokenOptions{Imprint: make([]byte, 32)}, tsa), "an authority not yet valid": tok(cmstest.TokenOptions{}, notYet), "an authority expired": tok(cmstest.TokenOptions{}, expired), "an authority of PSS, a bit flipped": tok(cmstest.TokenOptions{CMS: cmstest.Options{PSS: true, CorruptSignature: true}}, luis), } { token, err := cms.ParseToken(b) if err != nil || token.Check(subject) { t.Errorf("%s: %v, valid %v", name, err, err == nil && token.Check(subject)) } } // Valid: at the first and the last instant of the validity of the // authority, with RSA, PSS and SHA-512, and with the imprint of SHA-384, // which only seal_type 2 refuses. for name, b := range map[string][]byte{ "an authority valid exactly then": tok(cmstest.TokenOptions{}, exact), "an authority of RSA": tok(cmstest.TokenOptions{}, luis), "an authority of PSS": tok(cmstest.TokenOptions{CMS: cmstest.Options{PSS: true}}, luis), "a signature of SHA-512": tok(cmstest.TokenOptions{CMS: cmstest.Options{Hash: crypto.SHA512}}, tsa), } { token, err := cms.ParseToken(b) if err != nil || !token.Check(subject) || !token.ImprintIsSHA256() { t.Errorf("%s: %v", name, err) } } token, err := cms.ParseToken(tok(cmstest.TokenOptions{Hash: crypto.SHA384}, tsa)) if err != nil || !token.Check(subject) || token.ImprintIsSHA256() { t.Errorf("an imprint of SHA-384: %v", err) } } func sha256Of(b []byte) []byte { h := crypto.SHA256.New() h.Write(b) return h.Sum(nil) }