1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package ctfe
16
17 import (
18 "bytes"
19 "crypto/sha256"
20 "testing"
21
22 "github.com/google/certificate-transparency-go/tls"
23 "github.com/google/certificate-transparency-go/trillian/ctfe/testonly"
24 "github.com/google/certificate-transparency-go/trillian/testdata"
25 "github.com/google/certificate-transparency-go/x509"
26 "github.com/google/certificate-transparency-go/x509util"
27 "github.com/google/trillian/crypto/keys/pem"
28 "github.com/kylelemons/godebug/pretty"
29
30 ct "github.com/google/certificate-transparency-go"
31 )
32
33 func TestBuildV1MerkleTreeLeafForCert(t *testing.T) {
34 cert, err := x509util.CertificateFromPEM([]byte(testonly.LeafSignedByFakeIntermediateCertPEM))
35 if x509.IsFatal(err) {
36 t.Fatalf("failed to set up test cert: %v", err)
37 }
38
39 signer, err := setupSigner(fakeSignature)
40 if err != nil {
41 t.Fatalf("could not create signer: %v", err)
42 }
43
44 leaf, err := ct.MerkleTreeLeafFromChain([]*x509.Certificate{cert}, ct.X509LogEntryType, fixedTimeMillis)
45 if err != nil {
46 t.Fatalf("buildV1MerkleTreeLeafForCert()=nil,%v; want _,nil", err)
47 }
48 got, err := buildV1SCT(signer, leaf)
49 if err != nil {
50 t.Fatalf("buildV1SCT()=nil,%v; want _,nil", err)
51 }
52
53 expected := ct.SignedCertificateTimestamp{
54 SCTVersion: 0,
55 LogID: ct.LogID{KeyID: demoLogID},
56 Timestamp: fixedTimeMillis,
57 Extensions: ct.CTExtensions{},
58 Signature: ct.DigitallySigned{
59 Algorithm: tls.SignatureAndHashAlgorithm{
60 Hash: tls.SHA256,
61 Signature: tls.ECDSA},
62 Signature: fakeSignature,
63 },
64 }
65
66 if diff := pretty.Compare(*got, expected); diff != "" {
67 t.Fatalf("Mismatched SCT (cert), diff:\n%v", diff)
68 }
69
70
71 if got, want := leaf.Version, ct.V1; got != want {
72 t.Fatalf("Got a %v leaf, expected a %v leaf", got, want)
73 }
74 if got, want := leaf.LeafType, ct.TimestampedEntryLeafType; got != want {
75 t.Fatalf("Got leaf type %v, expected %v", got, want)
76 }
77 if got, want := leaf.TimestampedEntry.EntryType, ct.X509LogEntryType; got != want {
78 t.Fatalf("Got entry type %v, expected %v", got, want)
79 }
80 if got, want := leaf.TimestampedEntry.Timestamp, got.Timestamp; got != want {
81 t.Fatalf("Entry / sct timestamp mismatch; got %v, expected %v", got, want)
82 }
83 if got, want := leaf.TimestampedEntry.X509Entry.Data, cert.Raw; !bytes.Equal(got, want) {
84 t.Fatalf("Cert bytes mismatch, got %x, expected %x", got, want)
85 }
86 }
87
88 func TestSignV1SCTForPrecertificate(t *testing.T) {
89 cert, err := x509util.CertificateFromPEM([]byte(testonly.PrecertPEMValid))
90 if x509.IsFatal(err) {
91 t.Fatalf("failed to set up test precert: %v", err)
92 }
93
94 signer, err := setupSigner(fakeSignature)
95 if err != nil {
96 t.Fatalf("could not create signer: %v", err)
97 }
98
99
100 leaf, err := ct.MerkleTreeLeafFromChain([]*x509.Certificate{cert, cert}, ct.PrecertLogEntryType, fixedTimeMillis)
101 if err != nil {
102 t.Fatalf("buildV1MerkleTreeLeafForCert()=nil,%v; want _,nil", err)
103 }
104 got, err := buildV1SCT(signer, leaf)
105 if err != nil {
106 t.Fatalf("buildV1SCT()=nil,%v; want _,nil", err)
107 }
108
109 expected := ct.SignedCertificateTimestamp{
110 SCTVersion: 0,
111 LogID: ct.LogID{KeyID: demoLogID},
112 Timestamp: fixedTimeMillis,
113 Extensions: ct.CTExtensions{},
114 Signature: ct.DigitallySigned{
115 Algorithm: tls.SignatureAndHashAlgorithm{
116 Hash: tls.SHA256,
117 Signature: tls.ECDSA},
118 Signature: fakeSignature}}
119
120 if diff := pretty.Compare(*got, expected); diff != "" {
121 t.Fatalf("Mismatched SCT (precert), diff:\n%v", diff)
122 }
123
124
125 if got, want := leaf.Version, ct.V1; got != want {
126 t.Fatalf("Got a %v leaf, expected a %v leaf", got, want)
127 }
128 if got, want := leaf.LeafType, ct.TimestampedEntryLeafType; got != want {
129 t.Fatalf("Got leaf type %v, expected %v", got, want)
130 }
131 if got, want := leaf.TimestampedEntry.EntryType, ct.PrecertLogEntryType; got != want {
132 t.Fatalf("Got entry type %v, expected %v", got, want)
133 }
134 if got, want := got.Timestamp, leaf.TimestampedEntry.Timestamp; got != want {
135 t.Fatalf("Entry / sct timestamp mismatch; got %v, expected %v", got, want)
136 }
137 keyHash := sha256.Sum256(cert.RawSubjectPublicKeyInfo)
138 if got, want := keyHash[:], leaf.TimestampedEntry.PrecertEntry.IssuerKeyHash[:]; !bytes.Equal(got, want) {
139 t.Fatalf("Issuer key hash bytes mismatch, got %v, expected %v", got, want)
140 }
141 defangedTBS, _ := x509.RemoveCTPoison(cert.RawTBSCertificate)
142 if got, want := leaf.TimestampedEntry.PrecertEntry.TBSCertificate, defangedTBS; !bytes.Equal(got, want) {
143 t.Fatalf("TBS cert mismatch, got %v, expected %v", got, want)
144 }
145 }
146
147 func TestSignV1TreeHead(t *testing.T) {
148 signer, err := pem.UnmarshalPrivateKey(testdata.DemoPrivateKey, testdata.DemoPrivateKeyPass)
149 if err != nil {
150 t.Fatalf("could not create signer: %v", err)
151 }
152 var cache SignatureCache
153
154 sth := ct.SignedTreeHead{
155 Version: ct.V1,
156 TreeSize: 10,
157 Timestamp: 1512993312000,
158 }
159 if err := signV1TreeHead(signer, &sth, &cache); err != nil {
160 t.Fatalf("signV1TreeHead()=%v; want nil", err)
161 }
162 prevSig := make([]byte, len(sth.TreeHeadSignature.Signature))
163 copy(prevSig, sth.TreeHeadSignature.Signature)
164
165
166 for i := 0; i < 5; i++ {
167 if err := signV1TreeHead(signer, &sth, &cache); err != nil {
168 t.Fatalf("signV1TreeHead()=%v; want nil", err)
169 }
170 sig := make([]byte, len(sth.TreeHeadSignature.Signature))
171 copy(sig, sth.TreeHeadSignature.Signature)
172
173 if diff := pretty.Compare(prevSig, sig); diff != "" {
174 t.Fatalf("signV1TreeHead().TreeHeadSignature mismatched, diff:\n%v", diff)
175 }
176 }
177
178
179 for i := 0; i < 5; i++ {
180 sth.TreeSize = uint64(11 + i)
181 if err := signV1TreeHead(signer, &sth, &cache); err != nil {
182 t.Errorf("signV1TreeHead()=%v; want nil", err)
183 }
184 sig := make([]byte, len(sth.TreeHeadSignature.Signature))
185 copy(sig, sth.TreeHeadSignature.Signature)
186
187 if bytes.Equal(prevSig, sig) {
188 t.Fatalf("signV1TreeHead(size=%d).TreeHeadSignature unexpectedly matched", sth.TreeSize)
189 }
190 prevSig := sig
191
192
193 if err := signV1TreeHead(signer, &sth, &cache); err != nil {
194 t.Errorf("signV1TreeHead(size=%d)=%v; want nil", sth.TreeSize, err)
195 }
196 sig = make([]byte, len(sth.TreeHeadSignature.Signature))
197 copy(sig, sth.TreeHeadSignature.Signature)
198 if diff := pretty.Compare(prevSig, sig); diff != "" {
199 t.Fatalf("signV1TreeHead(size=%d).TreeHeadSignature mismatched, diff:\n%v", sth.TreeSize, diff)
200 }
201 }
202 }
203
204 func TestSignV1TreeHeadDifferentSigners(t *testing.T) {
205 signer1, err := pem.UnmarshalPrivateKey(testdata.DemoPrivateKey, testdata.DemoPrivateKeyPass)
206 if err != nil {
207 t.Fatalf("could not create signer1: %v", err)
208 }
209 signer2, err := setupSigner(fakeSignature)
210 if err != nil {
211 t.Fatalf("could not create signer2: %v", err)
212 }
213
214 var cache1, cache2 SignatureCache
215 sth := ct.SignedTreeHead{
216 Version: ct.V1,
217 TreeSize: 10,
218 Timestamp: 1512993312000,
219 }
220
221 if err := signV1TreeHead(signer1, &sth, &cache1); err != nil {
222 t.Fatalf("signV1TreeHead(signer1)=%v; want nil", err)
223 }
224 sig1 := make([]byte, len(sth.TreeHeadSignature.Signature))
225 copy(sig1, sth.TreeHeadSignature.Signature)
226
227 if err := signV1TreeHead(signer2, &sth, &cache2); err != nil {
228 t.Fatalf("signV1TreeHead(signer2)=%v; want nil", err)
229 }
230 sig2 := make([]byte, len(sth.TreeHeadSignature.Signature))
231 copy(sig2, sth.TreeHeadSignature.Signature)
232
233
234 if bytes.Equal(sig1, sig2) {
235 t.Fatal("signV1TreeHead().TreeHeadSignature unexpectedly matched")
236 }
237 }
238
View as plain text