diff options
| author | Rasmus Dahlberg <rasmus.dahlberg@kau.se> | 2020-10-28 14:56:11 +0100 | 
|---|---|---|
| committer | Rasmus Dahlberg <rasmus.dahlberg@kau.se> | 2020-10-28 14:56:11 +0100 | 
| commit | caca215c9516e8dc236a8510a6a5467c267d2331 (patch) | |
| tree | b4d0ee37f09e525e9402c5d2bdcbed72ef0cd483 | |
| parent | d752d967335e1418f27e03e0389b01178b28f232 (diff) | |
added consistency-proof code path
| -rw-r--r-- | handler.go | 24 | ||||
| -rw-r--r-- | reqres.go | 44 | ||||
| -rwxr-xr-x | server/testdata/cmd/get-consistency-proof | 16 | ||||
| -rw-r--r-- | type.go | 37 | 
4 files changed, 119 insertions, 2 deletions
| @@ -174,6 +174,30 @@ func getProofByHash(ctx context.Context, i *Instance, w http.ResponseWriter, r *  // getConsistencyProof provides a consistency proof between two STHs  func getConsistencyProof(ctx context.Context, i *Instance, w http.ResponseWriter, r *http.Request) (int, error) {  	glog.Info("in getConsistencyProof") +	request, err := NewGetConsistencyProofRequest(r) +	if err != nil { +		return http.StatusBadRequest, err +	} // request can be decoded and is valid + +	trillianRequest := trillian.GetConsistencyProofRequest{ +		LogId: i.LogParameters.TreeId, +		FirstTreeSize: int64(request.First), +		SecondTreeSize: int64(request.Second), +	} +	trillianResponse, err := i.Client.GetConsistencyProof(ctx, &trillianRequest) +	if err != nil { +		return http.StatusInternalServerError, fmt.Errorf("failed fetching consistency proof from Trillian backend: %v", err) +	} +	// TODO: santity-checks? + +	response, err := NewGetConsistencyProofResponse(i.LogParameters.LogId, request.First, request.Second, trillianResponse.Proof) +	if err != nil { +		return http.StatusInternalServerError, fmt.Errorf("failed creating get-consistency-proof response: %v", err) +	} +	if err := WriteJsonResponse(response, w); err != nil { +		return http.StatusInternalServerError, err +	} +	return http.StatusOK, nil  	return http.StatusOK, nil // TODO  } @@ -33,6 +33,13 @@ type GetProofByHashRequest struct {  	TreeSize int64  `json:"tree_size"` // Tree head size to base proof on  } +// GetConsistencyProofRequest is a collection of get-consistency-proof input +// parameters +type GetConsistencyProofRequest struct { +	First int64 `json:"first"` +	Second int64 `json:"second"` +} +  // AddEntryResponse is an assembled add-entry response  type AddEntryResponse struct {  	SignedDebugInfo string `json:"sdi"` @@ -55,6 +62,10 @@ type GetProofByHashResponse struct {  	InclusionProof string `json:"inclusion_proof"` // base64-encoded StItem  } +type GetConsistencyProofResponse struct { +	ConsistencyProof string `json:"consistency_proof"` // base64-encoded StItem +} +  // GetAnchorsResponse is an assembled get-anchor response  type GetAnchorsResponse struct {  	Certificates []string `json:"certificates"` @@ -102,7 +113,7 @@ func NewGetEntriesRequest(httpRequest *http.Request) (GetEntriesRequest, error)  		return GetEntriesRequest{}, fmt.Errorf("bad parameters: start(%v) must have a non-negative value", start)  	}  	if start > end { -		return GetEntriesRequest{}, fmt.Errorf("bad parameters: start(%v) must be larger than end(%v)", start, end) +		return GetEntriesRequest{}, fmt.Errorf("bad parameters: start(%v) must be less than or equal to end(%v)", start, end)  	}  	// TODO: check that range is not larger than the max range. Yes -> truncate  	// TODO: check that end is not past the most recent STH. Yes -> truncate @@ -128,6 +139,26 @@ func NewGetProofByHashRequest(httpRequest *http.Request) (GetProofByHashRequest,  	return GetProofByHashRequest{TreeSize: treeSize, Hash: hash}, nil  } +func NewGetConsistencyProofRequest(httpRequest *http.Request) (GetConsistencyProofRequest, error) { +	first, err := strconv.ParseInt(httpRequest.FormValue("first"), 10, 64) +	if err != nil { +		return GetConsistencyProofRequest{}, fmt.Errorf("bad first parameter: %v", err) +	} +	second, err := strconv.ParseInt(httpRequest.FormValue("second"), 10, 64) +	if err != nil { +		return GetConsistencyProofRequest{}, fmt.Errorf("bad second parameter: %v", err) +	} + +	if first < 1 { +		return GetConsistencyProofRequest{}, fmt.Errorf("bad parameters: first(%v) must be a natural number", first) +	} +	if first >= second { +		return GetConsistencyProofRequest{}, fmt.Errorf("bad parameters: second(%v) must be larger than first(%v)", first, second) +	} + +	return GetConsistencyProofRequest{ First: first, Second: second}, nil +} +  // NewAddEntryResponse assembles an add-entry response from an SDI  func NewAddEntryResponse(sdi StItem) (AddEntryResponse, error) {  	b, err := tls.Marshal(sdi) @@ -186,6 +217,17 @@ func NewGetProofByHashResponse(treeSize uint64, inclusionProof *trillian.Proof)  	}, nil  } +func NewGetConsistencyProofResponse(logId []byte, first, second int64, consistencyProof *trillian.Proof) (*GetConsistencyProofResponse, error) { +	item := NewConsistencyProofV1(logId, first, second, consistencyProof) +	b, err := tls.Marshal(item) +	if err != nil { +		return nil, fmt.Errorf("tls marshal failed: %v", err) +	} +	return &GetConsistencyProofResponse{ +		ConsistencyProof: base64.StdEncoding.EncodeToString(b), +	}, nil +} +  func NewGetAnchorsResponse(anchors []*x509.Certificate) GetAnchorsResponse {  	certificates := make([]string, 0, len(anchors))  	for _, certificate := range anchors { diff --git a/server/testdata/cmd/get-consistency-proof b/server/testdata/cmd/get-consistency-proof new file mode 100755 index 0000000..b5b749c --- /dev/null +++ b/server/testdata/cmd/get-consistency-proof @@ -0,0 +1,16 @@ +#!/bin/bash + +set -eo pipefail +source config + +first="1" +second="2" +if [[ ! -z $1 ]] && [[ ! -z $2 ]]; then +	first=$1 +	second=$2 +fi + +info "sending get-consistency-proof request" +curl -G -d "first=$first" -d "second=$second" $base_url/get-consistency-proof +newline +# TODO: try decoding and verifying proof @@ -28,11 +28,18 @@ type StItem struct {  	Format           StFormat          `tls:"maxval:65535"`  	SignedTreeHeadV1 *SignedTreeHeadV1 `tls:"selector:Format,val:1"`  	SignedDebugInfoV1 *SignedDebugInfoV1 `tls:"selector:Format,val:2"` -	// TODO: add consistency proof +	ConsistencyProofV1 *ConsistencyProofV1 `tls:"selector:Format,val:3"`  	InclusionProofV1 *InclusionProofV1 `tls:"selector:Format,val:4"`  	ChecksumV1       *ChecksumV1       `tls:"selector:Format,val:5"`  } +type ConsistencyProofV1 struct { +	LogId []byte `tls:"minlen:2,maxlen:127"` +	TreeSize1 uint64 +	TreeSize2 uint64 +	ConsistencyPath []NodeHash `tls:"minlen:1,maxlen:65535"` +} +  type SignedTreeHeadV1 struct {  	LogId []byte `tls:"minlen:2,maxlen:127"`  	TreeHead TreeHeadV1 `tls:minlen:0, maxlen:65535` // what should maxlen be? @@ -137,6 +144,23 @@ func NewInclusionProofV1(logID []byte, treeSize uint64, proof *trillian.Proof) S  	}  } +func NewConsistencyProofV1(logId []byte, first, second int64, proof *trillian.Proof) StItem { +	path := make([]NodeHash, 0, len(proof.Hashes)) +	for _, hash := range proof.Hashes { +		path = append(path, NodeHash{Data: hash}) +	} + +	return StItem{ +		Format: StFormatConsistencyProofV1, +		ConsistencyProofV1: &ConsistencyProofV1{ +			LogId: logId, +			TreeSize1: uint64(first), +			TreeSize2: uint64(second), +			ConsistencyPath: path, +		}, +	} +} +  func (f StFormat) String() string {  	switch f {  	case StFormatReserved: @@ -160,6 +184,8 @@ func (i StItem) String() string {  	switch i.Format {  	case StFormatChecksumV1:  		return fmt.Sprintf("Format(%s): %s", i.Format, *i.ChecksumV1) +	case StFormatConsistencyProofV1: +		return fmt.Sprintf("Format(%s): %s", i.Format, *i.ConsistencyProofV1)  	case StFormatInclusionProofV1:  		return fmt.Sprintf("Format(%s): %s", i.Format, *i.InclusionProofV1)  	case StFormatSignedDebugInfoV1: @@ -196,6 +222,15 @@ func (i InclusionProofV1) String() string {  	return fmt.Sprintf("LogID(%s) TreeSize(%d) LeafIndex(%d) AuditPath(%v)", base64.StdEncoding.EncodeToString(i.LogID), i.TreeSize, i.LeafIndex, path)  } +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)) +	} + +	return fmt.Sprintf("LogID(%s) TreeSize1(%d) TreeSize2(%d) ConsistencyPath(%v)", base64.StdEncoding.EncodeToString(i.LogId), i.TreeSize1, i.TreeSize2, path) +} +  // StItemFromB64 creates an StItem from a serialized and base64-encoded string  func StItemFromB64(s string) (StItem, error) {  	b, err := base64.StdEncoding.DecodeString(s) | 
