Add GetAuditProof to LogClient

This commit is contained in:
Andrew Ayer 2016-11-25 20:09:59 -08:00
parent b63a024876
commit adce61e035
1 changed files with 25 additions and 0 deletions

View File

@ -6,11 +6,13 @@ package client
import ( import (
"bytes" "bytes"
"crypto/sha256" "crypto/sha256"
"encoding/base64"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url"
"time" "time"
"github.com/mreiferson/go-httpclient" "github.com/mreiferson/go-httpclient"
@ -22,6 +24,7 @@ const (
GetSTHPath = "/ct/v1/get-sth" GetSTHPath = "/ct/v1/get-sth"
GetEntriesPath = "/ct/v1/get-entries" GetEntriesPath = "/ct/v1/get-entries"
GetSTHConsistencyPath = "/ct/v1/get-sth-consistency" GetSTHConsistencyPath = "/ct/v1/get-sth-consistency"
GetProofByHashPath = "/ct/v1/get-proof-by-hash"
) )
// LogClient represents a client for a given CT Log instance // LogClient represents a client for a given CT Log instance
@ -59,6 +62,12 @@ type getConsistencyProofResponse struct {
Consistency [][]byte `json:"consistency"` Consistency [][]byte `json:"consistency"`
} }
// getAuditProofResponse represents the JSON response to the CT get-proof-by-hash method
type getAuditProofResponse struct {
LeafIndex uint64 `json:"leaf_index"`
AuditPath [][]byte `json:"audit_path"`
}
// 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
@ -196,3 +205,19 @@ func (c *LogClient) GetConsistencyProof(first, second int64) (ct.ConsistencyProo
} }
return nodes, nil return nodes, nil
} }
// GetAuditProof retrieves a Merkle Audit Proof (aka Inclusion Proof) for the given
// |hash| based on the STH at |treeSize| from the log. Returns a slice of MerkleTreeNodes
// and the index of the leaf.
func (c *LogClient) GetAuditProof(hash ct.MerkleTreeNode, treeSize uint64) (ct.AuditPath, uint64, error) {
var resp getAuditProofResponse
err := c.fetchAndParse(fmt.Sprintf("%s%s?hash=%s&tree_size=%d", c.uri, GetProofByHashPath, url.QueryEscape(base64.StdEncoding.EncodeToString(hash)), treeSize), &resp)
if err != nil {
return nil, 0, err
}
path := make([]ct.MerkleTreeNode, len(resp.AuditPath))
for index, nodeBytes := range resp.AuditPath {
path[index] = nodeBytes
}
return path, resp.LeafIndex, nil
}