diff options
| -rw-r--r-- | client/client.go | 12 | ||||
| -rw-r--r-- | reqres.go | 62 | ||||
| -rw-r--r-- | type.go | 30 | ||||
| -rw-r--r-- | x509.go | 15 | 
4 files changed, 52 insertions, 67 deletions
| diff --git a/client/client.go b/client/client.go index 864afb4..54f75de 100644 --- a/client/client.go +++ b/client/client.go @@ -78,10 +78,10 @@ func (c *Client) AddEntry(ctx context.Context, name, checksum []byte) (*stfe.StI  		return nil, fmt.Errorf("failed marshaling StItem: %v", err)  	}  	data, err := json.Marshal(stfe.AddEntryRequest{ -		Item:            base64.StdEncoding.EncodeToString(leaf), -		Signature:       base64.StdEncoding.EncodeToString(ed25519.Sign(*c.PrivateKey, leaf)), +		Item:            leaf, +		Signature:       ed25519.Sign(*c.PrivateKey, leaf),  		SignatureScheme: uint16(tls.Ed25519), -		Chain:           c.b64Chain(), +		Chain:           c.chain(),  	})  	if err != nil {  		return nil, fmt.Errorf("failed creating post data: %v", err) @@ -189,10 +189,10 @@ func (c *Client) GetAnchors(ctx context.Context, start, end uint64) ([]*x509.Cer  	return nil, fmt.Errorf("TODO: Client.GetAnchors()")  } -func (c *Client) b64Chain() []string { -	chain := make([]string, 0, len(c.Chain)) +func (c *Client) chain() [][]byte { +	chain := make([][]byte, 0, len(c.Chain))  	for _, cert := range c.Chain { -		chain = append(chain, base64.StdEncoding.EncodeToString(cert.Raw)) +		chain = append(chain, cert.Raw)  	}  	return chain  } @@ -4,23 +4,21 @@ import (  	"fmt"  	"strconv" -	stdtls "crypto/tls" +	"crypto/tls"  	"crypto/x509" -	"encoding/base64"  	"encoding/json"  	"io/ioutil"  	"net/http" -	"github.com/google/certificate-transparency-go/tls"  	"github.com/google/trillian"  )  // AddEntryRequest is a collection of add-entry input parameters  type AddEntryRequest struct { -	Item            string   `json:"item"`             // base64-encoded StItem -	Signature       string   `json:"signature"`        // base64-encoded DigitallySigned -	SignatureScheme uint16   `json:"signature_scheme"` // RFC 8446, §4.2.3 -	Chain           []string `json:"chain"`            // base64-encoded X.509 certificates +	Item            []byte   `json:"item"`             // tls-serialized StItem +	Signature       []byte   `json:"signature"`        // serialized signature using the signature scheme below +	SignatureScheme uint16   `json:"signature_scheme"` // rfc 8446, §4.2.3 +	Chain           [][]byte `json:"chain"`            // der-encoded X.509 certificates  }  // GetEntriesRequest is a collection of get-entry input parameters @@ -31,8 +29,8 @@ type GetEntriesRequest struct {  // GetProofByHashRequest is a collection of get-proof-by-hash input parameters  type GetProofByHashRequest struct { -	Hash     []byte `json:"hash"`      // base64-encoded leaf hash -	TreeSize int64  `json:"tree_size"` // Tree head size to base proof on +	Hash     []byte `json:"hash"`      // leaf hash +	TreeSize int64  `json:"tree_size"` // tree head size to base proof on  }  // GetConsistencyProofRequest is a collection of get-consistency-proof input @@ -44,9 +42,9 @@ type GetConsistencyProofRequest struct {  // GetEntryResponse is an assembled log entry and its associated appendix  type GetEntryResponse struct { -	Leaf      string   `json:"leaf"`      // base64-encoded StItem -	Signature string   `json:"signature"` // base64-encoded signature -	Chain     []string `json:"chain"`     // base64-encoded X.509 certificates +	Leaf      []byte   `json:"leaf"`      // tls-serialized StItem +	Signature []byte   `json:"signature"` // Serialized signature using the log's signature scheme +	Chain     [][]byte `json:"chain"`     // der-encoded certificates  }  // NewAddEntryRequest parses and sanitizes the JSON-encoded add-entry @@ -60,36 +58,26 @@ func NewAddEntryRequest(lp *LogParameters, r *http.Request) ([]byte, []byte, err  	}  	var item StItem -	if err := item.UnmarshalB64(entry.Item); err != nil { +	if err := item.Unmarshal(entry.Item); err != nil {  		return nil, nil, fmt.Errorf("StItem(%s): %v", item.Format, err)  	}  	if item.Format != StFormatChecksumV1 {  		return nil, nil, fmt.Errorf("invalid StItem format: %s", item.Format)  	} // note that decode would have failed if invalid checksum/package length -	chain, err := buildChainFromB64List(lp, entry.Chain) +	chain, err := buildChainFromDerList(lp, entry.Chain)  	if err != nil {  		return nil, nil, fmt.Errorf("invalid certificate chain: %v", err)  	} // the final entry in chain is a valid trust anchor - -	signature, err := base64.StdEncoding.DecodeString(entry.Signature) -	if err != nil { -		return nil, nil, fmt.Errorf("invalid signature encoding: %v", err) -	} -	serialized, err := tls.Marshal(item) -	if err != nil { -		return nil, nil, fmt.Errorf("failed tls marshaling StItem(%s): %v", item.Format, err) -	} -	if err := verifySignature(lp, chain[0], stdtls.SignatureScheme(entry.SignatureScheme), serialized, signature); err != nil { +	if err := verifySignature(lp, chain[0], tls.SignatureScheme(entry.SignatureScheme), entry.Item, entry.Signature); err != nil {  		return nil, nil, fmt.Errorf("invalid signature: %v", err)  	} -	extra, err := NewAppendix(chain, signature, entry.SignatureScheme).Marshal() +	extra, err := NewAppendix(chain, entry.Signature, entry.SignatureScheme).Marshal()  	if err != nil {  		return nil, nil, fmt.Errorf("failed marshaling appendix: %v", err)  	} - -	return serialized, extra, nil +	return entry.Item, extra, nil  }  // NewGetEntriesRequest parses and sanitizes the URL-encoded get-entries @@ -129,7 +117,7 @@ func NewGetProofByHashRequest(httpRequest *http.Request) (GetProofByHashRequest,  		return GetProofByHashRequest{}, fmt.Errorf("bad tree_size parameter: negative value")  	} -	hash, err := base64.StdEncoding.DecodeString(httpRequest.FormValue("hash")) +	hash, err := deb64(httpRequest.FormValue("hash"))  	if err != nil {  		return GetProofByHashRequest{}, fmt.Errorf("bad hash parameter: %v", err)  	} @@ -162,17 +150,11 @@ func NewGetEntryResponse(leaf, appendix []byte) (GetEntryResponse, error) {  	if err := app.Unmarshal(appendix); err != nil {  		return GetEntryResponse{}, err  	} - -	chain := make([]string, 0, len(app.Chain)) +	chain := make([][]byte, 0, len(app.Chain))  	for _, c := range app.Chain { -		chain = append(chain, base64.StdEncoding.EncodeToString(c.Data)) +		chain = append(chain, c.Data)  	} - -	return GetEntryResponse{ -		Leaf:      base64.StdEncoding.EncodeToString(leaf), -		Signature: base64.StdEncoding.EncodeToString(app.Signature), -		Chain:     chain, -	}, nil +	return GetEntryResponse{leaf, app.Signature, chain}, nil  }  // NewGetEntriesResponse assembles a get-entries response @@ -188,10 +170,10 @@ func NewGetEntriesResponse(leaves []*trillian.LogLeaf) ([]GetEntryResponse, erro  	return entries, nil  } -func NewGetAnchorsResponse(anchors []*x509.Certificate) []string { -	certificates := make([]string, 0, len(anchors)) +func NewGetAnchorsResponse(anchors []*x509.Certificate) [][]byte { +	certificates := make([][]byte, 0, len(anchors))  	for _, certificate := range anchors { -		certificates = append(certificates, base64.StdEncoding.EncodeToString(certificate.Raw)) +		certificates = append(certificates, certificate.Raw)  	}  	return certificates  } @@ -133,37 +133,37 @@ func (i StItem) String() string {  }  func (i SignedTreeHeadV1) String() string { -	return fmt.Sprintf("LogId(%s) TreeHead(%s) Signature(%s)", base64.StdEncoding.EncodeToString(i.LogId), i.TreeHead, base64.StdEncoding.EncodeToString(i.Signature)) +	return fmt.Sprintf("LogId(%s) TreeHead(%s) Signature(%s)", b64(i.LogId), i.TreeHead, b64(i.Signature))  }  func (i SignedDebugInfoV1) String() string { -	return fmt.Sprintf("LogId(%s) Message(%s) Signature(%s)", base64.StdEncoding.EncodeToString(i.LogId), string(i.Message), base64.StdEncoding.EncodeToString(i.Signature)) +	return fmt.Sprintf("LogId(%s) Message(%s) Signature(%s)", b64(i.LogId), string(i.Message), b64(i.Signature))  }  func (i ConsistencyProofV1) String() string {  	path := make([]string, 0, len(i.ConsistencyPath))  	for _, hash := range i.ConsistencyPath { -		path = append(path, base64.StdEncoding.EncodeToString(hash.Data)) +		path = append(path, b64(hash.Data))  	} -	return fmt.Sprintf("LogID(%s) TreeSize1(%d) TreeSize2(%d) ConsistencyPath(%v)", base64.StdEncoding.EncodeToString(i.LogId), i.TreeSize1, i.TreeSize2, path) +	return fmt.Sprintf("LogID(%s) TreeSize1(%d) TreeSize2(%d) ConsistencyPath(%v)", b64(i.LogId), i.TreeSize1, i.TreeSize2, path)  }  func (i InclusionProofV1) String() string {  	path := make([]string, 0, len(i.InclusionPath))  	for _, hash := range i.InclusionPath { -		path = append(path, base64.StdEncoding.EncodeToString(hash.Data)) +		path = append(path, b64(hash.Data))  	} -	return fmt.Sprintf("LogID(%s) TreeSize(%d) LeafIndex(%d) AuditPath(%v)", base64.StdEncoding.EncodeToString(i.LogId), i.TreeSize, i.LeafIndex, path) +	return fmt.Sprintf("LogID(%s) TreeSize(%d) LeafIndex(%d) AuditPath(%v)", b64(i.LogId), i.TreeSize, i.LeafIndex, path)  }  func (i ChecksumV1) String() string { -	return fmt.Sprintf("Package(%s) Checksum(%s)", string(i.Package), base64.StdEncoding.EncodeToString(i.Checksum)) +	return fmt.Sprintf("Package(%s) Checksum(%s)", string(i.Package), b64(i.Checksum))  }  func (th TreeHeadV1) String() string { -	return fmt.Sprintf("Timestamp(%s) TreeSize(%d) RootHash(%s)", time.Unix(int64(th.Timestamp/1000), 0), th.TreeSize, base64.StdEncoding.EncodeToString(th.RootHash.Data)) +	return fmt.Sprintf("Timestamp(%s) TreeSize(%d) RootHash(%s)", time.Unix(int64(th.Timestamp/1000), 0), th.TreeSize, b64(th.RootHash.Data))  }  // Marshal serializes an Stitem as defined by RFC 5246 @@ -181,7 +181,7 @@ func (i *StItem) MarshalB64() (string, error) {  	if err != nil {  		return "", err  	} -	return base64.StdEncoding.EncodeToString(serialized), nil +	return b64(serialized), nil  }  // Unmarshal unpacks a serialized StItem @@ -197,7 +197,7 @@ func (i *StItem) Unmarshal(serialized []byte) error {  // UnmarshalB64 unpacks a base64-encoded serialized StItem  func (i *StItem) UnmarshalB64(s string) error { -	serialized, err := base64.StdEncoding.DecodeString(s) +	serialized, err := deb64(s)  	if err != nil {  		return fmt.Errorf("base64 decoding failed for StItem(%s): %v", i.Format, err)  	} @@ -213,7 +213,7 @@ func (a *Appendix) Marshal() ([]byte, error) {  	return serialized, nil  } -// Unmarshal unpacks an serialized Appendix +// Unmarshal unpacks a serialized Appendix  func (a *Appendix) Unmarshal(serialized []byte) error {  	extra, err := tls.Unmarshal(serialized, a)  	if err != nil { @@ -336,3 +336,11 @@ func NewAppendix(x509Chain []*x509.Certificate, signature []byte, signatureSchem  		SignatureScheme: signatureScheme,  	}  } + +func b64(b []byte) string { +	return base64.StdEncoding.EncodeToString(b) +} + +func deb64(str string) ([]byte, error) { +	return base64.StdEncoding.DecodeString(str) +} @@ -8,7 +8,6 @@ import (  	"crypto/rand"  	"crypto/tls"  	"crypto/x509" -	"encoding/base64"  	"encoding/pem"  	"io/ioutil"  ) @@ -135,17 +134,13 @@ func ParseChain(rest []byte) ([]*x509.Certificate, error) {  	return chain, nil  } -// ParseB64Chain parses a list of base64 DER-encoded X.509 certificates, such +// ParseDerChain parses a list of base64 DER-encoded X.509 certificates, such  // that the first (zero-index) string is interpretted as an end-entity  // certificate and the remaining ones as the an intermediate CertPool. -func ParseB64Chain(chain []string) (*x509.Certificate, *x509.CertPool, error) { +func ParseDerChain(chain [][]byte) (*x509.Certificate, *x509.CertPool, error) {  	var certificate *x509.Certificate  	intermediatePool := x509.NewCertPool() -	for index, cert := range chain { -		der, err := base64.StdEncoding.DecodeString(cert) -		if err != nil { -			return nil, nil, fmt.Errorf("certificate decoding failed: %v", err) -		} +	for index, der := range chain {  		c, err := x509.ParseCertificate(der)  		if err != nil {  			return nil, nil, fmt.Errorf("certificate decoding failed: %v", err) @@ -163,8 +158,8 @@ func ParseB64Chain(chain []string) (*x509.Certificate, *x509.CertPool, error) {  	return certificate, intermediatePool, nil  } -func buildChainFromB64List(lp *LogParameters, b64chain []string) ([]*x509.Certificate, error) { -	certificate, intermediatePool, err := ParseB64Chain(b64chain) +func buildChainFromDerList(lp *LogParameters, derChain [][]byte) ([]*x509.Certificate, error) { +	certificate, intermediatePool, err := ParseDerChain(derChain)  	if err != nil {  		return nil, err  	} | 
