aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRasmus Dahlberg <rasmus.dahlberg@kau.se>2020-10-28 14:56:11 +0100
committerRasmus Dahlberg <rasmus.dahlberg@kau.se>2020-10-28 14:56:11 +0100
commitcaca215c9516e8dc236a8510a6a5467c267d2331 (patch)
treeb4d0ee37f09e525e9402c5d2bdcbed72ef0cd483
parentd752d967335e1418f27e03e0389b01178b28f232 (diff)
added consistency-proof code path
-rw-r--r--handler.go24
-rw-r--r--reqres.go44
-rwxr-xr-xserver/testdata/cmd/get-consistency-proof16
-rw-r--r--type.go37
4 files changed, 119 insertions, 2 deletions
diff --git a/handler.go b/handler.go
index ee1eae6..119f65c 100644
--- a/handler.go
+++ b/handler.go
@@ -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
}
diff --git a/reqres.go b/reqres.go
index e223fd9..d0257ab 100644
--- a/reqres.go
+++ b/reqres.go
@@ -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
diff --git a/type.go b/type.go
index be2571e..729f54f 100644
--- a/type.go
+++ b/type.go
@@ -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)