Revert "Update google/certificate-transparency dependency. (#2242)" (#2255)

This reverts commit 277cdf1638.

The updated dependencies caused breakage on Go 1.5, which we are still running in prod.
This commit is contained in:
Jacob Hoffman-Andrews 2016-10-17 15:35:18 -07:00 committed by GitHub
commit faee874c1d
4 changed files with 120 additions and 213 deletions

10
Godeps/Godeps.json generated
View File

@ -108,23 +108,23 @@
}, },
{ {
"ImportPath": "github.com/google/certificate-transparency/go", "ImportPath": "github.com/google/certificate-transparency/go",
"Rev": "10e14470ce93d5dfe6eff6b85d3e7a06ef2f4809" "Rev": "0f6e3d1d1ba4d03fdaab7cd716f36255c2e48341"
}, },
{ {
"ImportPath": "github.com/google/certificate-transparency/go/asn1", "ImportPath": "github.com/google/certificate-transparency/go/asn1",
"Rev": "10e14470ce93d5dfe6eff6b85d3e7a06ef2f4809" "Rev": "0f6e3d1d1ba4d03fdaab7cd716f36255c2e48341"
}, },
{ {
"ImportPath": "github.com/google/certificate-transparency/go/client", "ImportPath": "github.com/google/certificate-transparency/go/client",
"Rev": "10e14470ce93d5dfe6eff6b85d3e7a06ef2f4809" "Rev": "0f6e3d1d1ba4d03fdaab7cd716f36255c2e48341"
}, },
{ {
"ImportPath": "github.com/google/certificate-transparency/go/x509", "ImportPath": "github.com/google/certificate-transparency/go/x509",
"Rev": "10e14470ce93d5dfe6eff6b85d3e7a06ef2f4809" "Rev": "0f6e3d1d1ba4d03fdaab7cd716f36255c2e48341"
}, },
{ {
"ImportPath": "github.com/google/certificate-transparency/go/x509/pkix", "ImportPath": "github.com/google/certificate-transparency/go/x509/pkix",
"Rev": "10e14470ce93d5dfe6eff6b85d3e7a06ef2f4809" "Rev": "0f6e3d1d1ba4d03fdaab7cd716f36255c2e48341"
}, },
{ {
"ImportPath": "github.com/jmhodges/clock", "ImportPath": "github.com/jmhodges/clock",

View File

@ -8,15 +8,15 @@ import (
"crypto/sha256" "crypto/sha256"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"net/http" "net/http"
"net/url"
"strconv" "strconv"
"time" "time"
ct "github.com/google/certificate-transparency/go" "github.com/google/certificate-transparency/go"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
@ -27,8 +27,6 @@ const (
AddJSONPath = "/ct/v1/add-json" AddJSONPath = "/ct/v1/add-json"
GetSTHPath = "/ct/v1/get-sth" GetSTHPath = "/ct/v1/get-sth"
GetEntriesPath = "/ct/v1/get-entries" GetEntriesPath = "/ct/v1/get-entries"
GetProofByHashPath = "/ct/v1/get-proof-by-hash"
GetSTHConsistencyPath = "/ct/v1/get-sth-consistency"
) )
// LogClient represents a client for a given CT Log instance // LogClient represents a client for a given CT Log instance
@ -45,7 +43,7 @@ type LogClient struct {
// addChainRequest represents the JSON request body sent to the add-chain CT // addChainRequest represents the JSON request body sent to the add-chain CT
// method. // method.
type addChainRequest struct { type addChainRequest struct {
Chain [][]byte `json:"chain"` Chain []string `json:"chain"`
} }
// addChainResponse represents the JSON response to the add-chain CT method. // addChainResponse represents the JSON response to the add-chain CT method.
@ -53,10 +51,10 @@ type addChainRequest struct {
// log within a defined period of time. // log within a defined period of time.
type addChainResponse struct { type addChainResponse struct {
SCTVersion ct.Version `json:"sct_version"` // SCT structure version SCTVersion ct.Version `json:"sct_version"` // SCT structure version
ID []byte `json:"id"` // Log ID ID string `json:"id"` // Log ID
Timestamp uint64 `json:"timestamp"` // Timestamp of issuance Timestamp uint64 `json:"timestamp"` // Timestamp of issuance
Extensions string `json:"extensions"` // Holder for any CT extensions Extensions string `json:"extensions"` // Holder for any CT extensions
Signature []byte `json:"signature"` // Log signature for this SCT Signature string `json:"signature"` // Log signature for this SCT
} }
// addJSONRequest represents the JSON request body sent ot the add-json CT // addJSONRequest represents the JSON request body sent ot the add-json CT
@ -69,13 +67,24 @@ type addJSONRequest struct {
type getSTHResponse struct { type getSTHResponse struct {
TreeSize uint64 `json:"tree_size"` // Number of certs in the current tree TreeSize uint64 `json:"tree_size"` // Number of certs in the current tree
Timestamp uint64 `json:"timestamp"` // Time that the tree was created Timestamp uint64 `json:"timestamp"` // Time that the tree was created
SHA256RootHash []byte `json:"sha256_root_hash"` // Root hash of the tree SHA256RootHash string `json:"sha256_root_hash"` // Root hash of the tree
TreeHeadSignature []byte `json:"tree_head_signature"` // Log signature for this STH TreeHeadSignature string `json:"tree_head_signature"` // Log signature for this STH
} }
// getConsistencyProofResponse represents the JSON response to the get-consistency-proof CT method // base64LeafEntry respresents a Base64 encoded leaf entry
type base64LeafEntry struct {
LeafInput string `json:"leaf_input"`
ExtraData string `json:"extra_data"`
}
// getEntriesReponse respresents the JSON response to the CT get-entries method
type getEntriesResponse struct {
Entries []base64LeafEntry `json:"entries"` // the list of returned entries
}
// getConsistencyProofResponse represents the JSON response to the CT get-consistency-proof method
type getConsistencyProofResponse struct { type getConsistencyProofResponse struct {
Consistency [][]byte `json:"consistency"` Consistency []string `json:"consistency"`
} }
// getAuditProofResponse represents the JSON response to the CT get-audit-proof method // getAuditProofResponse represents the JSON response to the CT get-audit-proof method
@ -96,12 +105,6 @@ type getEntryAndProofResponse struct {
AuditPath []string `json:"audit_path"` // the corresponding proof AuditPath []string `json:"audit_path"` // the corresponding proof
} }
// GetProofByHashResponse represents the JSON response to the CT get-proof-by-hash method.
type GetProofByHashResponse struct {
LeafIndex int64 `json:"leaf_index"` // The 0-based index of the end entity corresponding to the "hash" parameter.
AuditPath [][]byte `json:"audit_path"` // An array of base64-encoded Merkle Tree nodes proving the inclusion of the chosen certificate.
}
// New constructs a new LogClient instance. // New constructs a new LogClient instance.
// |uri| is the base URI of the CT log instance to interact with, e.g. // |uri| is the base URI of the CT log instance to interact with, e.g.
// http://ct.googleapis.com/pilot // http://ct.googleapis.com/pilot
@ -113,33 +116,29 @@ func New(uri string, hc *http.Client) *LogClient {
return &LogClient{uri: uri, httpClient: hc} return &LogClient{uri: uri, httpClient: hc}
} }
// Makes a HTTP call to |uri|, and attempts to parse the response as a // Makes a HTTP call to |uri|, and attempts to parse the response as a JSON
// JSON representation of the structure in |res|. Uses |ctx| to // representation of the structure in |res|.
// control the HTTP call (so it can have a timeout or be cancelled by
// the caller), and |httpClient| to make the actual HTTP call.
// Returns a non-nil |error| if there was a problem. // Returns a non-nil |error| if there was a problem.
func fetchAndParse(ctx context.Context, httpClient *http.Client, uri string, res interface{}) error { func (c *LogClient) fetchAndParse(uri string, res interface{}) error {
req, err := http.NewRequest(http.MethodGet, uri, nil) req, err := http.NewRequest("GET", uri, nil)
if err != nil { if err != nil {
return err return err
} }
req.Cancel = ctx.Done() resp, err := c.httpClient.Do(req)
resp, err := httpClient.Do(req) var body []byte
if resp != nil {
body, err = ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil { if err != nil {
return err return err
} }
defer resp.Body.Close()
// Make sure everything is read, so http.Client can reuse the connection.
defer ioutil.ReadAll(resp.Body)
if resp.StatusCode != 200 {
return fmt.Errorf("got HTTP Status %s", resp.Status)
} }
if err != nil {
if err := json.NewDecoder(resp.Body).Decode(res); err != nil { return err
}
if err = json.Unmarshal(body, &res); err != nil {
return err return err
} }
return nil return nil
} }
@ -151,7 +150,7 @@ func (c *LogClient) postAndParse(uri string, req interface{}, res interface{}) (
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
httpReq, err := http.NewRequest(http.MethodPost, uri, bytes.NewReader(postBody)) httpReq, err := http.NewRequest("POST", uri, bytes.NewReader(postBody))
if err != nil { if err != nil {
return nil, "", err return nil, "", err
} }
@ -199,7 +198,7 @@ func (c *LogClient) addChainWithRetry(ctx context.Context, path string, chain []
var resp addChainResponse var resp addChainResponse
var req addChainRequest var req addChainRequest
for _, link := range chain { for _, link := range chain {
req.Chain = append(req.Chain, link) req.Chain = append(req.Chain, base64.StdEncoding.EncodeToString(link))
} }
httpStatus := "Unknown" httpStatus := "Unknown"
backoffSeconds := 0 backoffSeconds := 0
@ -215,7 +214,7 @@ func (c *LogClient) addChainWithRetry(ctx context.Context, path string, chain []
if backoffSeconds > 0 { if backoffSeconds > 0 {
backoffSeconds = 0 backoffSeconds = 0
} }
httpResp, _, err := c.postAndParse(c.uri+path, &req, &resp) httpResp, errorBody, err := c.postAndParse(c.uri+path, &req, &resp)
if err != nil { if err != nil {
backoffSeconds = 10 backoffSeconds = 10
continue continue
@ -234,17 +233,25 @@ func (c *LogClient) addChainWithRetry(ctx context.Context, path string, chain []
} }
} }
default: default:
return nil, fmt.Errorf("got HTTP Status %s", httpResp.Status) return nil, fmt.Errorf("got HTTP Status %s: %s", httpResp.Status, errorBody)
} }
httpStatus = httpResp.Status httpStatus = httpResp.Status
} }
ds, err := ct.UnmarshalDigitallySigned(bytes.NewReader(resp.Signature)) rawLogID, err := base64.StdEncoding.DecodeString(resp.ID)
if err != nil {
return nil, err
}
rawSignature, err := base64.StdEncoding.DecodeString(resp.Signature)
if err != nil {
return nil, err
}
ds, err := ct.UnmarshalDigitallySigned(bytes.NewReader(rawSignature))
if err != nil { if err != nil {
return nil, err return nil, err
} }
var logID ct.SHA256Hash var logID ct.SHA256Hash
copy(logID[:], resp.ID) copy(logID[:], rawLogID)
return &ct.SignedCertificateTimestamp{ return &ct.SignedCertificateTimestamp{
SCTVersion: resp.SCTVersion, SCTVersion: resp.SCTVersion,
LogID: logID, LogID: logID,
@ -269,7 +276,6 @@ func (c *LogClient) AddChainWithContext(ctx context.Context, chain []ct.ASN1Cert
return c.addChainWithRetry(ctx, AddChainPath, chain) return c.addChainWithRetry(ctx, AddChainPath, chain)
} }
// AddJSON submits arbitrary data to to XJSON server.
func (c *LogClient) AddJSON(data interface{}) (*ct.SignedCertificateTimestamp, error) { func (c *LogClient) AddJSON(data interface{}) (*ct.SignedCertificateTimestamp, error) {
req := addJSONRequest{ req := addJSONRequest{
Data: data, Data: data,
@ -279,12 +285,20 @@ func (c *LogClient) AddJSON(data interface{}) (*ct.SignedCertificateTimestamp, e
if err != nil { if err != nil {
return nil, err return nil, err
} }
ds, err := ct.UnmarshalDigitallySigned(bytes.NewReader(resp.Signature)) rawLogID, err := base64.StdEncoding.DecodeString(resp.ID)
if err != nil {
return nil, err
}
rawSignature, err := base64.StdEncoding.DecodeString(resp.Signature)
if err != nil {
return nil, err
}
ds, err := ct.UnmarshalDigitallySigned(bytes.NewReader(rawSignature))
if err != nil { if err != nil {
return nil, err return nil, err
} }
var logID ct.SHA256Hash var logID ct.SHA256Hash
copy(logID[:], resp.ID) copy(logID[:], rawLogID)
return &ct.SignedCertificateTimestamp{ return &ct.SignedCertificateTimestamp{
SCTVersion: resp.SCTVersion, SCTVersion: resp.SCTVersion,
LogID: logID, LogID: logID,
@ -297,7 +311,7 @@ func (c *LogClient) AddJSON(data interface{}) (*ct.SignedCertificateTimestamp, e
// Returns a populated SignedTreeHead, or a non-nil error. // Returns a populated SignedTreeHead, or a non-nil error.
func (c *LogClient) GetSTH() (sth *ct.SignedTreeHead, err error) { func (c *LogClient) GetSTH() (sth *ct.SignedTreeHead, err error) {
var resp getSTHResponse var resp getSTHResponse
if err = fetchAndParse(context.TODO(), c.httpClient, c.uri+GetSTHPath, &resp); err != nil { if err = c.fetchAndParse(c.uri+GetSTHPath, &resp); err != nil {
return return
} }
sth = &ct.SignedTreeHead{ sth = &ct.SignedTreeHead{
@ -305,12 +319,20 @@ func (c *LogClient) GetSTH() (sth *ct.SignedTreeHead, err error) {
Timestamp: resp.Timestamp, Timestamp: resp.Timestamp,
} }
if len(resp.SHA256RootHash) != sha256.Size { rawRootHash, err := base64.StdEncoding.DecodeString(resp.SHA256RootHash)
return nil, fmt.Errorf("sha256_root_hash is invalid length, expected %d got %d", sha256.Size, len(resp.SHA256RootHash)) if err != nil {
return nil, fmt.Errorf("invalid base64 encoding in sha256_root_hash: %v", err)
} }
copy(sth.SHA256RootHash[:], resp.SHA256RootHash) if len(rawRootHash) != sha256.Size {
return nil, fmt.Errorf("sha256_root_hash is invalid length, expected %d got %d", sha256.Size, len(rawRootHash))
}
copy(sth.SHA256RootHash[:], rawRootHash)
ds, err := ct.UnmarshalDigitallySigned(bytes.NewReader(resp.TreeHeadSignature)) rawSignature, err := base64.StdEncoding.DecodeString(resp.TreeHeadSignature)
if err != nil {
return nil, errors.New("invalid base64 encoding in tree_head_signature")
}
ds, err := ct.UnmarshalDigitallySigned(bytes.NewReader(rawSignature))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -319,23 +341,47 @@ func (c *LogClient) GetSTH() (sth *ct.SignedTreeHead, err error) {
return return
} }
// GetSTHConsistency retrieves the consistency proof between two snapshots. // GetEntries attempts to retrieve the entries in the sequence [|start|, |end|] from the CT
func (c *LogClient) GetSTHConsistency(ctx context.Context, first, second uint64) ([][]byte, error) { // log server. (see section 4.6.)
u := fmt.Sprintf("%s%s?first=%d&second=%d", c.uri, GetSTHConsistencyPath, first, second) // Returns a slice of LeafInputs or a non-nil error.
var resp getConsistencyProofResponse func (c *LogClient) GetEntries(start, end int64) ([]ct.LogEntry, error) {
if err := fetchAndParse(ctx, c.httpClient, u, &resp); err != nil { if end < 0 {
return nil, errors.New("end should be >= 0")
}
if end < start {
return nil, errors.New("start should be <= end")
}
var resp getEntriesResponse
err := c.fetchAndParse(fmt.Sprintf("%s%s?start=%d&end=%d", c.uri, GetEntriesPath, start, end), &resp)
if err != nil {
return nil, err return nil, err
} }
return resp.Consistency, nil entries := make([]ct.LogEntry, len(resp.Entries))
} for index, entry := range resp.Entries {
leafBytes, err := base64.StdEncoding.DecodeString(entry.LeafInput)
leaf, err := ct.ReadMerkleTreeLeaf(bytes.NewBuffer(leafBytes))
if err != nil {
return nil, err
}
entries[index].Leaf = *leaf
chainBytes, err := base64.StdEncoding.DecodeString(entry.ExtraData)
// GetProofByHash returns an audit path for the hash of an SCT. var chain []ct.ASN1Cert
func (c *LogClient) GetProofByHash(ctx context.Context, hash []byte, treeSize uint64) (*GetProofByHashResponse, error) { switch leaf.TimestampedEntry.EntryType {
b64Hash := url.QueryEscape(base64.StdEncoding.EncodeToString(hash)) case ct.X509LogEntryType:
u := fmt.Sprintf("%s%s?tree_size=%d&hash=%v", c.uri, GetProofByHashPath, treeSize, b64Hash) chain, err = ct.UnmarshalX509ChainArray(chainBytes)
var resp GetProofByHashResponse
if err := fetchAndParse(ctx, c.httpClient, u, &resp); err != nil { case ct.PrecertLogEntryType:
chain, err = ct.UnmarshalPrecertChainArray(chainBytes)
default:
return nil, fmt.Errorf("saw unknown entry type: %v", leaf.TimestampedEntry.EntryType)
}
if err != nil {
return nil, err return nil, err
} }
return &resp, nil entries[index].Chain = chain
entries[index].Index = start + int64(index)
}
return entries, nil
} }

View File

@ -6,11 +6,9 @@ import (
"crypto" "crypto"
"encoding/asn1" "encoding/asn1"
"encoding/binary" "encoding/binary"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"strings"
) )
// Variable size structure prefix-header byte lengths // Variable size structure prefix-header byte lengths
@ -20,7 +18,6 @@ const (
ExtensionsLengthBytes = 2 ExtensionsLengthBytes = 2
CertificateChainLengthBytes = 3 CertificateChainLengthBytes = 3
SignatureLengthBytes = 2 SignatureLengthBytes = 2
JSONLengthBytes = 3
) )
// Max lengths // Max lengths
@ -147,10 +144,6 @@ func ReadTimestampedEntryInto(r io.Reader, t *TimestampedEntry) error {
if t.PrecertEntry.TBSCertificate, err = readVarBytes(r, PreCertificateLengthBytes); err != nil { if t.PrecertEntry.TBSCertificate, err = readVarBytes(r, PreCertificateLengthBytes); err != nil {
return err return err
} }
case XJSONLogEntryType:
if t.JSONData, err = readVarBytes(r, JSONLengthBytes); err != nil {
return err
}
default: default:
return fmt.Errorf("unknown EntryType: %d", t.EntryType) return fmt.Errorf("unknown EntryType: %d", t.EntryType)
} }
@ -158,41 +151,6 @@ func ReadTimestampedEntryInto(r io.Reader, t *TimestampedEntry) error {
return nil return nil
} }
// SerializeTimestampedEntry writes timestamped entry to Writer.
// In case of error, w may contain garbage.
func SerializeTimestampedEntry(w io.Writer, t *TimestampedEntry) error {
if err := binary.Write(w, binary.BigEndian, t.Timestamp); err != nil {
return err
}
if err := binary.Write(w, binary.BigEndian, t.EntryType); err != nil {
return err
}
switch t.EntryType {
case X509LogEntryType:
if err := writeVarBytes(w, t.X509Entry, CertificateLengthBytes); err != nil {
return err
}
case PrecertLogEntryType:
if err := binary.Write(w, binary.BigEndian, t.PrecertEntry.IssuerKeyHash); err != nil {
return err
}
if err := writeVarBytes(w, t.PrecertEntry.TBSCertificate, PreCertificateLengthBytes); err != nil {
return err
}
case XJSONLogEntryType:
// TODO: Pending google/certificate-transparency#1243, replace
// with ObjectHash once supported by CT server.
//jsonhash := objecthash.CommonJSONHash(string(t.JSONData))
if err := writeVarBytes(w, []byte(t.JSONData), JSONLengthBytes); err != nil {
return err
}
default:
return fmt.Errorf("unknown EntryType: %d", t.EntryType)
}
writeVarBytes(w, t.Extensions, ExtensionsLengthBytes)
return nil
}
// ReadMerkleTreeLeaf parses the byte-stream representation of a MerkleTreeLeaf // ReadMerkleTreeLeaf parses the byte-stream representation of a MerkleTreeLeaf
// and returns a pointer to a new MerkleTreeLeaf structure containing the // and returns a pointer to a new MerkleTreeLeaf structure containing the
// parsed data. // parsed data.
@ -341,29 +299,6 @@ func serializeV1CertSCTSignatureInput(timestamp uint64, cert ASN1Cert, ext CTExt
return buf.Bytes(), nil return buf.Bytes(), nil
} }
func serializeV1JSONSCTSignatureInput(timestamp uint64, j []byte) ([]byte, error) {
var buf bytes.Buffer
if err := binary.Write(&buf, binary.BigEndian, V1); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, CertificateTimestampSignatureType); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, timestamp); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, XJSONLogEntryType); err != nil {
return nil, err
}
if err := writeVarBytes(&buf, j, JSONLengthBytes); err != nil {
return nil, err
}
if err := writeVarBytes(&buf, nil, ExtensionsLengthBytes); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func serializeV1PrecertSCTSignatureInput(timestamp uint64, issuerKeyHash [issuerKeyHashLength]byte, tbs []byte, ext CTExtensions) ([]byte, error) { func serializeV1PrecertSCTSignatureInput(timestamp uint64, issuerKeyHash [issuerKeyHashLength]byte, tbs []byte, ext CTExtensions) ([]byte, error) {
if err := checkCertificateFormat(tbs); err != nil { if err := checkCertificateFormat(tbs); err != nil {
return nil, err return nil, err
@ -410,8 +345,6 @@ func serializeV1SCTSignatureInput(sct SignedCertificateTimestamp, entry LogEntry
return serializeV1PrecertSCTSignatureInput(sct.Timestamp, entry.Leaf.TimestampedEntry.PrecertEntry.IssuerKeyHash, return serializeV1PrecertSCTSignatureInput(sct.Timestamp, entry.Leaf.TimestampedEntry.PrecertEntry.IssuerKeyHash,
entry.Leaf.TimestampedEntry.PrecertEntry.TBSCertificate, entry.Leaf.TimestampedEntry.PrecertEntry.TBSCertificate,
entry.Leaf.TimestampedEntry.Extensions) entry.Leaf.TimestampedEntry.Extensions)
case XJSONLogEntryType:
return serializeV1JSONSCTSignatureInput(sct.Timestamp, entry.Leaf.TimestampedEntry.JSONData)
default: default:
return nil, fmt.Errorf("unknown TimestampedEntryLeafType %s", entry.Leaf.TimestampedEntry.EntryType) return nil, fmt.Errorf("unknown TimestampedEntryLeafType %s", entry.Leaf.TimestampedEntry.EntryType)
} }
@ -526,7 +459,6 @@ func deserializeSCTV1(r io.Reader, sct *SignedCertificateTimestamp) error {
return nil return nil
} }
// DeserializeSCT reads an SCT from Reader.
func DeserializeSCT(r io.Reader) (*SignedCertificateTimestamp, error) { func DeserializeSCT(r io.Reader) (*SignedCertificateTimestamp, error) {
var sct SignedCertificateTimestamp var sct SignedCertificateTimestamp
if err := binary.Read(r, binary.BigEndian, &sct.SCTVersion); err != nil { if err := binary.Read(r, binary.BigEndian, &sct.SCTVersion); err != nil {
@ -629,63 +561,3 @@ func SerializeSCTList(scts []SignedCertificateTimestamp) ([]byte, error) {
} }
return asn1.Marshal(buf.Bytes()) // transform to Octet String return asn1.Marshal(buf.Bytes()) // transform to Octet String
} }
// SerializeMerkleTreeLeaf writes MerkleTreeLeaf to Writer.
// In case of error, w may contain garbage.
func SerializeMerkleTreeLeaf(w io.Writer, m *MerkleTreeLeaf) error {
if m.Version != V1 {
return fmt.Errorf("unknown Version %d", m.Version)
}
if err := binary.Write(w, binary.BigEndian, m.Version); err != nil {
return err
}
if m.LeafType != TimestampedEntryLeafType {
return fmt.Errorf("unknown LeafType %d", m.LeafType)
}
if err := binary.Write(w, binary.BigEndian, m.LeafType); err != nil {
return err
}
if err := SerializeTimestampedEntry(w, &m.TimestampedEntry); err != nil {
return err
}
return nil
}
// CreateX509MerkleTreeLeaf generates a MerkleTreeLeaf for an X509 cert
func CreateX509MerkleTreeLeaf(cert ASN1Cert, timestamp uint64) *MerkleTreeLeaf {
return &MerkleTreeLeaf{
Version: V1,
LeafType: TimestampedEntryLeafType,
TimestampedEntry: TimestampedEntry{
Timestamp: timestamp,
EntryType: X509LogEntryType,
X509Entry: cert,
},
}
}
// CreateJSONMerkleTreeLeaf creates the merkle tree leaf for json data.
func CreateJSONMerkleTreeLeaf(data interface{}, timestamp uint64) *MerkleTreeLeaf {
jsonData, err := json.Marshal(AddJSONRequest{Data: data})
if err != nil {
return nil
}
// Match the JSON serialization implemented by json-c
jsonStr := strings.Replace(string(jsonData), ":", ": ", -1)
jsonStr = strings.Replace(jsonStr, ",", ", ", -1)
jsonStr = strings.Replace(jsonStr, "{", "{ ", -1)
jsonStr = strings.Replace(jsonStr, "}", " }", -1)
jsonStr = strings.Replace(jsonStr, "/", `\/`, -1)
// TODO: Pending google/certificate-transparency#1243, replace with
// ObjectHash once supported by CT server.
return &MerkleTreeLeaf{
Version: V1,
LeafType: TimestampedEntryLeafType,
TimestampedEntry: TimestampedEntry{
Timestamp: timestamp,
EntryType: XJSONLogEntryType,
JSONData: []byte(jsonStr),
},
}
}

View File

@ -28,8 +28,6 @@ func (e LogEntryType) String() string {
return "X509LogEntryType" return "X509LogEntryType"
case PrecertLogEntryType: case PrecertLogEntryType:
return "PrecertLogEntryType" return "PrecertLogEntryType"
case XJSONLogEntryType:
return "XJSONLogEntryType"
} }
panic(fmt.Sprintf("No string defined for LogEntryType constant value %d", e)) panic(fmt.Sprintf("No string defined for LogEntryType constant value %d", e))
} }
@ -38,7 +36,6 @@ func (e LogEntryType) String() string {
const ( const (
X509LogEntryType LogEntryType = 0 X509LogEntryType LogEntryType = 0
PrecertLogEntryType LogEntryType = 1 PrecertLogEntryType LogEntryType = 1
XJSONLogEntryType LogEntryType = 0x8000 // Experimental. Don't rely on this!
) )
// MerkleLeafType represents the MerkleLeafType enum from section 3.4 of the // MerkleLeafType represents the MerkleLeafType enum from section 3.4 of the
@ -241,7 +238,6 @@ type LogEntry struct {
Leaf MerkleTreeLeaf Leaf MerkleTreeLeaf
X509Cert *x509.Certificate X509Cert *x509.Certificate
Precert *Precertificate Precert *Precertificate
JSONData []byte
Chain []ASN1Cert Chain []ASN1Cert
} }
@ -317,7 +313,6 @@ type TimestampedEntry struct {
Timestamp uint64 Timestamp uint64
EntryType LogEntryType EntryType LogEntryType
X509Entry ASN1Cert X509Entry ASN1Cert
JSONData []byte
PrecertEntry PreCert PrecertEntry PreCert
Extensions CTExtensions Extensions CTExtensions
} }
@ -366,9 +361,3 @@ func (e sctError) Error() string {
return "unknown error" return "unknown error"
} }
} }
// AddJSONRequest represents the JSON request body sent ot the add-json CT
// method.
type AddJSONRequest struct {
Data interface{} `json:"data"`
}