5
5
"crypto/x509"
6
6
"encoding/asn1"
7
7
"encoding/base64"
8
- "encoding/json"
9
8
"fmt"
10
9
11
10
"github.com/google/certificate-transparency-go/tls"
@@ -134,37 +133,10 @@ type CTExtensions []byte // tls:"minlen:0,maxlen:65535"`
134
133
// MerkleTreeNode represents an internal node in the CT tree.
135
134
type MerkleTreeNode []byte
136
135
137
- // ConsistencyProof represents a CT consistency proof (see sections 2.1.2 and
138
- // 4.4).
139
- type ConsistencyProof []MerkleTreeNode
140
-
141
- // AuditPath represents a CT inclusion proof (see sections 2.1.1 and 4.5).
142
- type AuditPath []MerkleTreeNode
143
-
144
- // LeafInput represents a serialized MerkleTreeLeaf structure.
145
- type LeafInput []byte
146
-
147
136
// DigitallySigned is a local alias for tls.DigitallySigned so that we can
148
- // attach a MarshalJSON method.
137
+ // attach a Base64String() method.
149
138
type DigitallySigned tls.DigitallySigned
150
139
151
- // FromBase64String populates the DigitallySigned structure from the base64 data passed in.
152
- // Returns an error if the base64 data is invalid.
153
- func (d * DigitallySigned ) FromBase64String (b64 string ) error {
154
- raw , err := base64 .StdEncoding .DecodeString (b64 )
155
- if err != nil {
156
- return fmt .Errorf ("failed to unbase64 DigitallySigned: %v" , err )
157
- }
158
- var ds tls.DigitallySigned
159
- if rest , err := tls .Unmarshal (raw , & ds ); err != nil {
160
- return fmt .Errorf ("failed to unmarshal DigitallySigned: %v" , err )
161
- } else if len (rest ) > 0 {
162
- return fmt .Errorf ("trailing data (%d bytes) after DigitallySigned" , len (rest ))
163
- }
164
- * d = DigitallySigned (ds )
165
- return nil
166
- }
167
-
168
140
// Base64String returns the base64 representation of the DigitallySigned struct.
169
141
func (d DigitallySigned ) Base64String () (string , error ) {
170
142
b , err := tls .Marshal (d )
@@ -174,24 +146,6 @@ func (d DigitallySigned) Base64String() (string, error) {
174
146
return base64 .StdEncoding .EncodeToString (b ), nil
175
147
}
176
148
177
- // MarshalJSON implements the json.Marshaller interface.
178
- func (d DigitallySigned ) MarshalJSON () ([]byte , error ) {
179
- b64 , err := d .Base64String ()
180
- if err != nil {
181
- return []byte {}, err
182
- }
183
- return []byte (`"` + b64 + `"` ), nil
184
- }
185
-
186
- // UnmarshalJSON implements the json.Unmarshaler interface.
187
- func (d * DigitallySigned ) UnmarshalJSON (b []byte ) error {
188
- var content string
189
- if err := json .Unmarshal (b , & content ); err != nil {
190
- return fmt .Errorf ("failed to unmarshal DigitallySigned: %v" , err )
191
- }
192
- return d .FromBase64String (content )
193
- }
194
-
195
149
// RawLogEntry represents the (TLS-parsed) contents of an entry in a CT log.
196
150
type RawLogEntry struct {
197
151
// Index is a position of the entry in the log.
@@ -227,34 +181,6 @@ type LogEntry struct {
227
181
Chain []ASN1Cert
228
182
}
229
183
230
- // PrecertChainEntry holds an precertificate together with a validation chain
231
- // for it; see section 3.1.
232
- type PrecertChainEntry struct {
233
- PreCertificate ASN1Cert `tls:"minlen:1,maxlen:16777215"`
234
- CertificateChain []ASN1Cert `tls:"minlen:0,maxlen:16777215"`
235
- }
236
-
237
- // CertificateChain holds a chain of certificates, as returned as extra data
238
- // for get-entries (section 4.6).
239
- type CertificateChain struct {
240
- Entries []ASN1Cert `tls:"minlen:0,maxlen:16777215"`
241
- }
242
-
243
- // PrecertChainEntryHash is an extended PrecertChainEntry type with the
244
- // IssuanceChainHash field added to store the hash of the
245
- // CertificateChain field of PrecertChainEntry.
246
- type PrecertChainEntryHash struct {
247
- PreCertificate ASN1Cert `tls:"minlen:1,maxlen:16777215"`
248
- IssuanceChainHash []byte `tls:"minlen:0,maxlen:256"`
249
- }
250
-
251
- // CertificateChainHash is an extended CertificateChain type with the
252
- // IssuanceChainHash field added to store the hash of the
253
- // Entries field of CertificateChain.
254
- type CertificateChainHash struct {
255
- IssuanceChainHash []byte `tls:"minlen:0,maxlen:256"`
256
- }
257
-
258
184
// JSONDataEntry holds arbitrary data.
259
185
type JSONDataEntry struct {
260
186
Data []byte `tls:"minlen:0,maxlen:1677215"`
@@ -263,47 +189,20 @@ type JSONDataEntry struct {
263
189
// SHA256Hash represents the output from the SHA256 hash function.
264
190
type SHA256Hash [sha256 .Size ]byte
265
191
266
- // FromBase64String populates the SHA256 struct with the contents of the base64 data passed in.
267
- func (s * SHA256Hash ) FromBase64String (b64 string ) error {
268
- bs , err := base64 .StdEncoding .DecodeString (b64 )
269
- if err != nil {
270
- return fmt .Errorf ("failed to unbase64 LogID: %v" , err )
271
- }
272
- if len (bs ) != sha256 .Size {
273
- return fmt .Errorf ("invalid SHA256 length, expected 32 but got %d" , len (bs ))
274
- }
275
- copy (s [:], bs )
276
- return nil
277
- }
278
-
279
192
// Base64String returns the base64 representation of this SHA256Hash.
280
193
func (s SHA256Hash ) Base64String () string {
281
194
return base64 .StdEncoding .EncodeToString (s [:])
282
195
}
283
196
284
- // MarshalJSON implements the json.Marshaller interface for SHA256Hash.
285
- func (s SHA256Hash ) MarshalJSON () ([]byte , error ) {
286
- return []byte (`"` + s .Base64String () + `"` ), nil
287
- }
288
-
289
- // UnmarshalJSON implements the json.Unmarshaller interface.
290
- func (s * SHA256Hash ) UnmarshalJSON (b []byte ) error {
291
- var content string
292
- if err := json .Unmarshal (b , & content ); err != nil {
293
- return fmt .Errorf ("failed to unmarshal SHA256Hash: %v" , err )
294
- }
295
- return s .FromBase64String (content )
296
- }
297
-
298
197
// SignedTreeHead represents the structure returned by the get-sth CT method
299
198
// after base64 decoding; see sections 3.5 and 4.3.
300
199
type SignedTreeHead struct {
301
- Version Version `json:"sth_version"` // The version of the protocol to which the STH conforms
302
- TreeSize uint64 `json:"tree_size"` // The number of entries in the new tree
303
- Timestamp uint64 `json:"timestamp"` // The time at which the STH was created
304
- SHA256RootHash SHA256Hash `json:"sha256_root_hash"` // The root hash of the log's Merkle tree
305
- TreeHeadSignature DigitallySigned `json:"tree_head_signature"` // Log's signature over a TLS-encoded TreeHeadSignature
306
- LogID SHA256Hash `json:"log_id"` // The SHA256 hash of the log's public key
200
+ Version Version // The version of the protocol to which the STH conforms
201
+ TreeSize uint64 // The number of entries in the new tree
202
+ Timestamp uint64 // The time at which the STH was created
203
+ SHA256RootHash SHA256Hash // The root hash of the log's Merkle tree
204
+ TreeHeadSignature DigitallySigned // Log's signature over a TLS-encoded TreeHeadSignature
205
+ LogID SHA256Hash // The SHA256 hash of the log's public key
307
206
}
308
207
309
208
func (s SignedTreeHead ) String () string {
@@ -396,15 +295,6 @@ type Precertificate struct {
396
295
TBSCertificate * x509.Certificate
397
296
}
398
297
399
- // X509Certificate returns the X.509 Certificate contained within the
400
- // MerkleTreeLeaf.
401
- func (m * MerkleTreeLeaf ) X509Certificate () (* x509.Certificate , error ) {
402
- if m .TimestampedEntry .EntryType != X509LogEntryType {
403
- return nil , fmt .Errorf ("cannot call X509Certificate on a MerkleTreeLeaf that is not an X509 entry" )
404
- }
405
- return x509 .ParseCertificate (m .TimestampedEntry .X509Entry .Data )
406
- }
407
-
408
298
// APIEndpoint is a string that represents one of the Certificate Transparency
409
299
// Log API endpoints.
410
300
type APIEndpoint string
@@ -413,30 +303,18 @@ type APIEndpoint string
413
303
// WARNING: Should match the URI paths without the "/ct/v1/" prefix. If
414
304
// changing these constants, may need to change those too.
415
305
const (
416
- AddChainStr APIEndpoint = "add-chain"
417
- AddPreChainStr APIEndpoint = "add-pre-chain"
418
- GetSTHStr APIEndpoint = "get-sth"
419
- GetEntriesStr APIEndpoint = "get-entries"
420
- GetProofByHashStr APIEndpoint = "get-proof-by-hash"
421
- GetSTHConsistencyStr APIEndpoint = "get-sth-consistency"
422
- GetRootsStr APIEndpoint = "get-roots"
423
- GetEntryAndProofStr APIEndpoint = "get-entry-and-proof"
306
+ AddChainStr APIEndpoint = "add-chain"
307
+ AddPreChainStr APIEndpoint = "add-pre-chain"
308
+ GetRootsStr APIEndpoint = "get-roots"
424
309
)
425
310
426
311
// URI paths for Log requests; see section 4.
427
312
// WARNING: Should match the API endpoints, with the "/ct/v1/" prefix. If
428
313
// changing these constants, may need to change those too.
429
314
const (
430
- AddChainPath = "/ct/v1/add-chain"
431
- AddPreChainPath = "/ct/v1/add-pre-chain"
432
- GetSTHPath = "/ct/v1/get-sth"
433
- GetEntriesPath = "/ct/v1/get-entries"
434
- GetProofByHashPath = "/ct/v1/get-proof-by-hash"
435
- GetSTHConsistencyPath = "/ct/v1/get-sth-consistency"
436
- GetRootsPath = "/ct/v1/get-roots"
437
- GetEntryAndProofPath = "/ct/v1/get-entry-and-proof"
438
-
439
- AddJSONPath = "/ct/v1/add-json" // Experimental addition
315
+ AddChainPath = "/ct/v1/add-chain"
316
+ AddPreChainPath = "/ct/v1/add-pre-chain"
317
+ GetRootsPath = "/ct/v1/get-roots"
440
318
)
441
319
442
320
// AddChainRequest represents the JSON request body sent to the add-chain and
@@ -456,108 +334,3 @@ type AddChainResponse struct {
456
334
Extensions string `json:"extensions"` // Holder for any CT extensions
457
335
Signature []byte `json:"signature"` // Log signature for this SCT
458
336
}
459
-
460
- // ToSignedCertificateTimestamp creates a SignedCertificateTimestamp from the
461
- // AddChainResponse.
462
- func (r * AddChainResponse ) ToSignedCertificateTimestamp () (* SignedCertificateTimestamp , error ) {
463
- sct := SignedCertificateTimestamp {
464
- SCTVersion : r .SCTVersion ,
465
- Timestamp : r .Timestamp ,
466
- }
467
-
468
- if len (r .ID ) != sha256 .Size {
469
- return nil , fmt .Errorf ("id is invalid length, expected %d got %d" , sha256 .Size , len (r .ID ))
470
- }
471
- copy (sct .LogID .KeyID [:], r .ID )
472
-
473
- exts , err := base64 .StdEncoding .DecodeString (r .Extensions )
474
- if err != nil {
475
- return nil , fmt .Errorf ("invalid base64 data in Extensions (%q): %v" , r .Extensions , err )
476
- }
477
- sct .Extensions = CTExtensions (exts )
478
-
479
- var ds DigitallySigned
480
- if rest , err := tls .Unmarshal (r .Signature , & ds ); err != nil {
481
- return nil , fmt .Errorf ("tls.Unmarshal(): %s" , err )
482
- } else if len (rest ) > 0 {
483
- return nil , fmt .Errorf ("trailing data (%d bytes) after DigitallySigned" , len (rest ))
484
- }
485
- sct .Signature = ds
486
-
487
- return & sct , nil
488
- }
489
-
490
- // GetSTHResponse represents the JSON response to the get-sth GET method from section 4.3.
491
- type GetSTHResponse struct {
492
- TreeSize uint64 `json:"tree_size"` // Number of certs in the current tree
493
- Timestamp uint64 `json:"timestamp"` // Time that the tree was created
494
- SHA256RootHash []byte `json:"sha256_root_hash"` // Root hash of the tree
495
- TreeHeadSignature []byte `json:"tree_head_signature"` // Log signature for this STH
496
- }
497
-
498
- // ToSignedTreeHead creates a SignedTreeHead from the GetSTHResponse.
499
- func (r * GetSTHResponse ) ToSignedTreeHead () (* SignedTreeHead , error ) {
500
- sth := SignedTreeHead {
501
- TreeSize : r .TreeSize ,
502
- Timestamp : r .Timestamp ,
503
- }
504
-
505
- if len (r .SHA256RootHash ) != sha256 .Size {
506
- return nil , fmt .Errorf ("sha256_root_hash is invalid length, expected %d got %d" , sha256 .Size , len (r .SHA256RootHash ))
507
- }
508
- copy (sth .SHA256RootHash [:], r .SHA256RootHash )
509
-
510
- var ds DigitallySigned
511
- if rest , err := tls .Unmarshal (r .TreeHeadSignature , & ds ); err != nil {
512
- return nil , fmt .Errorf ("tls.Unmarshal(): %s" , err )
513
- } else if len (rest ) > 0 {
514
- return nil , fmt .Errorf ("trailing data (%d bytes) after DigitallySigned" , len (rest ))
515
- }
516
- sth .TreeHeadSignature = ds
517
-
518
- return & sth , nil
519
- }
520
-
521
- // GetSTHConsistencyResponse represents the JSON response to the get-sth-consistency
522
- // GET method from section 4.4. (The corresponding GET request has parameters 'first' and
523
- // 'second'.)
524
- type GetSTHConsistencyResponse struct {
525
- Consistency [][]byte `json:"consistency"`
526
- }
527
-
528
- // GetProofByHashResponse represents the JSON response to the get-proof-by-hash GET
529
- // method from section 4.5. (The corresponding GET request has parameters 'hash'
530
- // and 'tree_size'.)
531
- type GetProofByHashResponse struct {
532
- LeafIndex int64 `json:"leaf_index"` // The 0-based index of the end entity corresponding to the "hash" parameter.
533
- AuditPath [][]byte `json:"audit_path"` // An array of base64-encoded Merkle Tree nodes proving the inclusion of the chosen certificate.
534
- }
535
-
536
- // LeafEntry represents a leaf in the Log's Merkle tree, as returned by the get-entries
537
- // GET method from section 4.6.
538
- type LeafEntry struct {
539
- // LeafInput is a TLS-encoded MerkleTreeLeaf
540
- LeafInput []byte `json:"leaf_input"`
541
- // ExtraData holds (unsigned) extra data, normally the cert validation chain.
542
- ExtraData []byte `json:"extra_data"`
543
- }
544
-
545
- // GetEntriesResponse represents the JSON response to the get-entries GET method
546
- // from section 4.6.
547
- type GetEntriesResponse struct {
548
- Entries []LeafEntry `json:"entries"` // the list of returned entries
549
- }
550
-
551
- // GetRootsResponse represents the JSON response to the get-roots GET method from section 4.7.
552
- type GetRootsResponse struct {
553
- Certificates []string `json:"certificates"`
554
- }
555
-
556
- // GetEntryAndProofResponse represents the JSON response to the get-entry-and-proof
557
- // GET method from section 4.8. (The corresponding GET request has parameters 'leaf_index'
558
- // and 'tree_size'.)
559
- type GetEntryAndProofResponse struct {
560
- LeafInput []byte `json:"leaf_input"` // the entry itself
561
- ExtraData []byte `json:"extra_data"` // any chain provided when the entry was added to the log
562
- AuditPath [][]byte `json:"audit_path"` // the corresponding proof
563
- }
0 commit comments