From ec6aae759954224865a9e0fb83d97c6f9cdf9749 Mon Sep 17 00:00:00 2001 From: Gary Belvin Date: Thu, 29 Jun 2017 18:47:33 +0100 Subject: [PATCH 1/3] Use Trillian map verifier. --- .keytransparency.yaml | 5 +- README.md | 6 +- .../grpcc/grpc_client.go | 5 +- core/client/kt/verify.go | 34 ++-- core/tree/sparse/common.go | 7 +- core/tree/sparse/hasher.go | 81 -------- core/tree/sparse/hasher_test.go | 62 ------ core/tree/sparse/verifier/verifier.go | 132 ------------- core/tree/sparse/verifier/verifier_test.go | 182 ------------------ scripts/map_payload.json | 4 +- 10 files changed, 33 insertions(+), 485 deletions(-) delete mode 100644 core/tree/sparse/hasher.go delete mode 100644 core/tree/sparse/hasher_test.go delete mode 100644 core/tree/sparse/verifier/verifier.go delete mode 100644 core/tree/sparse/verifier/verifier_test.go diff --git a/.keytransparency.yaml b/.keytransparency.yaml index 94ba4fbe2..b5be7dce3 100644 --- a/.keytransparency.yaml +++ b/.keytransparency.yaml @@ -1,9 +1,8 @@ -log-key: "../trillian/testdata/log-rpc-server.pubkey.pem" +log-key: "genfiles/trillian-log.pem" vrf: "genfiles/vrf-pubkey.pem" kt-key: "genfiles/server.crt" kt-sig: "genfiles/p256-pubkey.pem" domain: "example.com" -map-id: 0 kt-url: "35.184.134.53:8080" client-secret: "client_secret.json" -service-key: "" \ No newline at end of file +service-key: "" diff --git a/README.md b/README.md index 056cd6230..b3b0c20b0 100644 --- a/README.md +++ b/README.md @@ -33,15 +33,15 @@ development. ### Setup 1. Install [Go 1.7](https://golang.org/doc/install). 2. `go get -u github.com/google/keytransparency/cmd/keytransparency-client ` -3. Get an [OAuth client ID](https://console.developers.google.com/apis/credentials) and download the generated JSON file. -4. Run the client setup tool: `./scripts/prepare_client.sh` +3. Get an [OAuth client ID](https://console.developers.google.com/apis/credentials) and download the generated JSON file to `client_secret.json`. +4. Run the client setup tool: `./scripts/prepare_client.sh` ### Client operations #### Publish a public key ```sh - keytransparency-client authorized-keys --help` + keytransparency-client authorized-keys --help keytransparency-client authorized-keys add --generate --type=ecdsa --activate keytransparency-client post user@domain.com app1 --config=./.keytransparency.yaml -d 'dGVzdA==' #Base64 ``` diff --git a/cmd/keytransparency-client/grpcc/grpc_client.go b/cmd/keytransparency-client/grpcc/grpc_client.go index 617e03280..ef33edf61 100644 --- a/cmd/keytransparency-client/grpcc/grpc_client.go +++ b/cmd/keytransparency-client/grpcc/grpc_client.go @@ -31,11 +31,10 @@ import ( "github.com/google/keytransparency/core/crypto/vrf" "github.com/google/keytransparency/core/mutator" "github.com/google/keytransparency/core/mutator/entry" - "github.com/google/keytransparency/core/tree/sparse" - tv "github.com/google/keytransparency/core/tree/sparse/verifier" "github.com/golang/protobuf/proto" "github.com/google/trillian/client" + "github.com/google/trillian/merkle/coniks" "golang.org/x/net/context" "google.golang.org/grpc" @@ -99,7 +98,7 @@ func New(mapID int64, return &Client{ cli: client, vrf: vrf, - kt: kt.New(vrf, tv.New(mapID, sparse.CONIKSHasher), verifier, log), + kt: kt.New(mapID, vrf, coniks.Default, verifier, log), log: log, mutator: entry.New(), RetryCount: 1, diff --git a/core/client/kt/verify.go b/core/client/kt/verify.go index 6e9c9e812..44d6ae858 100644 --- a/core/client/kt/verify.go +++ b/core/client/kt/verify.go @@ -24,12 +24,12 @@ import ( "github.com/google/keytransparency/core/crypto/commitments" "github.com/google/keytransparency/core/crypto/vrf" - "github.com/google/keytransparency/core/tree/sparse" - tv "github.com/google/keytransparency/core/tree/sparse/verifier" "github.com/golang/protobuf/proto" "github.com/google/trillian/client" tcrypto "github.com/google/trillian/crypto" + "github.com/google/trillian/merkle" + "github.com/google/trillian/merkle/hashers" "golang.org/x/net/context" tpb "github.com/google/keytransparency/core/proto/keytransparency_v1_types" @@ -46,22 +46,25 @@ var ( // Verifier is a client helper library for verifying request and responses. type Verifier struct { - vrf vrf.PublicKey - tree *tv.Verifier - sig crypto.PublicKey - log client.LogVerifier + mapID int64 + vrf vrf.PublicKey + hasher hashers.MapHasher + sig crypto.PublicKey + log client.LogVerifier } // New creates a new instance of the client verifier. -func New(vrf vrf.PublicKey, - tree *tv.Verifier, +func New(mapID int64, + vrf vrf.PublicKey, + hasher hashers.MapHasher, sig crypto.PublicKey, log client.LogVerifier) *Verifier { return &Verifier{ - vrf: vrf, - tree: tree, - sig: sig, - log: log, + mapID: mapID, + vrf: vrf, + hasher: hasher, + sig: sig, + log: log, } } @@ -106,9 +109,12 @@ func (v *Verifier) VerifyGetEntryResponse(ctx context.Context, userID, appID str return ErrNilProof } - if err := v.tree.VerifyProof(leafProof.Inclusion, index[:], leafProof.Leaf.LeafValue, sparse.FromBytes(in.GetSmr().RootHash)); err != nil { + leaf := leafProof.GetLeaf().GetLeafValue() + proof := leafProof.GetInclusion() + expectedRoot := in.GetSmr().GetRootHash() + if err := merkle.VerifyMapInclusionProof(v.mapID, index[:], leaf, expectedRoot, proof, v.hasher); err != nil { Vlog.Printf("✗ Sparse tree proof verification failed.") - return fmt.Errorf("tree.VerifyProof(): %v", err) + return fmt.Errorf("VerifyMapInclusionProof(): %v", err) } Vlog.Printf("✓ Sparse tree proof verified.") diff --git a/core/tree/sparse/common.go b/core/tree/sparse/common.go index 32377abe3..47182257e 100644 --- a/core/tree/sparse/common.go +++ b/core/tree/sparse/common.go @@ -27,6 +27,7 @@ import ( "fmt" "github.com/google/keytransparency/core/tree" + "github.com/google/trillian/merkle/hashers" ) const ( @@ -37,12 +38,12 @@ const ( ) // Hash represents the output of the hash function used in the sparse tree. -type Hash [HashSize]byte +type Hash []byte // NodeValues computes the new values for leafs up the tree. nbrValues must not // be compressed. value is the actual value of the leaf. NodeValues returns the // leaf hash as part of the returned list. -func NodeValues(mapID int64, hasher TreeHasher, bindex string, value []byte, nbrValues []Hash) []Hash { +func NodeValues(mapID int64, hasher hashers.MapHasher, bindex string, value []byte, nbrValues []Hash) []Hash { levels := len(bindex) + 1 steps := len(bindex) nodeValues := make([]Hash, levels) @@ -59,7 +60,7 @@ func NodeValues(mapID int64, hasher TreeHasher, bindex string, value []byte, nbr left = nbrValues[i] right = nodeValues[i] } - nodeValues[i+1] = hasher.HashInterior(left, right) + nodeValues[i+1] = hasher.HashChildren(left, right) } return nodeValues } diff --git a/core/tree/sparse/hasher.go b/core/tree/sparse/hasher.go deleted file mode 100644 index fb4b9c410..000000000 --- a/core/tree/sparse/hasher.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package sparse - -import ( - "bytes" - "crypto/sha512" - "encoding/binary" -) - -// TreeHasher provides hash functions for tree implementations. -type TreeHasher interface { - HashLeaf(mapID int64, index []byte, depth int, dataHash []byte) Hash - HashInterior(left, right Hash) Hash - HashEmpty(mapID int64, index []byte, depth int) Hash -} - -// CONIKSHasher implements the tree hashes described in CONIKS -// http://www.jbonneau.com/doc/MBBFF15-coniks.pdf -var CONIKSHasher TreeHasher = &coniks{} - -type coniks struct{} - -var ( - leafIdentifier = []byte("L") - emptyIdentifier = []byte("E") - hash = sha512.Sum512_256 -) - -// HashLeaf calculate the merkle tree node value: -// H(Identifier || mapID || depth || index || dataHash) -func (coniks) HashLeaf(mapID int64, index []byte, depth int, dataHash []byte) Hash { - bmapID := make([]byte, 8) - binary.BigEndian.PutUint64(bmapID, uint64(mapID)) - bdepth := make([]byte, 4) - binary.BigEndian.PutUint32(bdepth, uint32(depth)) - - var b bytes.Buffer - b.Write(leafIdentifier) - b.Write(bmapID) - b.Write(index) - b.Write(bdepth) - b.Write(dataHash) - return Hash(hash(b.Bytes())) -} - -// HashInterior calculates an interior node's value: H(left || right) -func (coniks) HashInterior(left, right Hash) Hash { - var b bytes.Buffer - b.Write(left.Bytes()) - b.Write(right.Bytes()) - return Hash(hash(b.Bytes())) -} - -// HashEmpty computes the value of an empty leaf: -// H(EmptyIdentifier || mapID || depth || index) -func (coniks) HashEmpty(mapID int64, index []byte, depth int) Hash { - bmapID := make([]byte, 8) - binary.BigEndian.PutUint64(bmapID, uint64(mapID)) - bdepth := make([]byte, 4) - binary.BigEndian.PutUint32(bdepth, uint32(depth)) - - var b bytes.Buffer - b.Write(emptyIdentifier) - b.Write(bmapID) - b.Write(index) - b.Write(bdepth) - return Hash(hash(b.Bytes())) -} diff --git a/core/tree/sparse/hasher_test.go b/core/tree/sparse/hasher_test.go deleted file mode 100644 index f229fdf22..000000000 --- a/core/tree/sparse/hasher_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package sparse - -import ( - "encoding/hex" - "testing" -) - -// h2h converts a hex string into its Hash object. -func h2h(h string) Hash { - b, err := hex.DecodeString(h) - if err != nil { - panic("invalid hex string") - } - var ret Hash - copy(ret[:], b) - return ret -} - -func TestHashLeafVectors(t *testing.T) { - for _, tc := range []struct { - treeID int64 - index []byte - depth int - leaf []byte - want Hash - }{ - {treeID: 0, index: []byte("foo"), depth: 128, leaf: []byte("leaf"), want: h2h("2d6c9f648b61e786e18bcba49d1dc62dee2020cec168f0d2c9e47a7bd4633f02")}, - } { - if got, want := CONIKSHasher.HashLeaf(tc.treeID, tc.index, tc.depth, tc.leaf), tc.want; got != want { - t.Errorf("HashLeaf(%v, %s, %v, %s): %x, want %x", tc.treeID, tc.index, tc.depth, tc.leaf, got, want) - } - } -} - -func TestHashEmptyVectors(t *testing.T) { - for _, tc := range []struct { - treeID int64 - index []byte - depth int - want Hash - }{ - {treeID: 0, index: []byte("foo"), depth: 128, want: h2h("6db629ab14386f31c5f573a5734d7f3c50d97bf06fa0da606dad47b8b1a3eb32")}, - } { - if got, want := CONIKSHasher.HashEmpty(tc.treeID, tc.index, tc.depth), tc.want; got != want { - t.Errorf("HashEmpty(%v, %s, %v): %x, want %x", tc.treeID, tc.index, tc.depth, got, want) - } - } -} diff --git a/core/tree/sparse/verifier/verifier.go b/core/tree/sparse/verifier/verifier.go deleted file mode 100644 index c73fa054b..000000000 --- a/core/tree/sparse/verifier/verifier.go +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package verifier allows client to verify a tree proof. -package verifier - -import ( - "bytes" - "errors" - "fmt" - - "github.com/google/keytransparency/core/tree" - "github.com/google/keytransparency/core/tree/sparse" -) - -var ( - // ErrNeighborsLen occurs when the neighbor list length is longer than - // the maximum allowed value. - ErrNeighborsLen = fmt.Errorf("Neighbors len > %d", sparse.IndexLen) - // ErrIndexBit occurs when the string-formatted index contains an invalid - // bit (character), i.e., other than '0' or '1'. - ErrIndexBit = errors.New("Invalid index bit") - // ErrInvalidProof occurs when the provided tree proof cannot be - // verified. This can be caused by an invalid neighbor tree or root. - ErrInvalidProof = errors.New("Invalid proof") -) - -// Verifier represents a sparse tree proof verifier object. -type Verifier struct { - mapID int64 - hasher sparse.TreeHasher -} - -// New returns a new tree proofs verifier object. -func New(mapID int64, hasher sparse.TreeHasher) *Verifier { - return &Verifier{ - mapID: mapID, - hasher: hasher, - } -} - -// VerifyProof verifies a tree proof of a given leaf at a given index based on -// the provided root and neighbor list -func (v *Verifier) VerifyProof(neighbors [][]byte, index, leaf []byte, root sparse.Hash) error { - if len(neighbors) > sparse.IndexLen { - return ErrNeighborsLen - } - - // Calculate the tree root based on neighbors and leaf. - calculatedRoot, err := v.calculateRoot(neighbors, tree.BitString(index), leaf) - if err != nil { - return err - } - - // Verify that calculated and provided roots match. - if got, want := calculatedRoot.Bytes(), root.Bytes(); !bytes.Equal(got, want) { - return ErrInvalidProof - } - - return nil -} - -// calculateRoot calculates the root of the tree branch defined by leaf and -// neighbors. -func (v *Verifier) calculateRoot(neighbors [][]byte, bindex string, leaf []byte) (sparse.Hash, error) { - var leafHash sparse.Hash - - // If the leaf is empty, it is a proof of absence. - if len(leaf) == 0 { - // Trim the neighbors list. - neighbors = trimNeighbors(neighbors) - - // Calculate the value of the empty leaf - missingBranchBIndex := bindex[:len(neighbors)] - index, depth := tree.InvertBitString(missingBranchBIndex) - leafHash = v.hasher.HashEmpty(v.mapID, index, depth) - } else { - index, depth := tree.InvertBitString(bindex) - leafHash = v.hasher.HashLeaf(v.mapID, index, depth, leaf) - } - - // calculatedRoot holds the calculated root so far, starting from leaf. - calculatedRoot := leafHash - for i, neighbor := range neighbors { - // TODO convert trimNeighbors to return Hash values. - var neighborHash sparse.Hash - // Get the neighbor bit string index. - neighborBIndex := tree.NeighborString(bindex[:len(neighbors)-i]) - // If the neighbor is empty, set it to HashEmpty output. - if len(neighbor) == 0 { - nIndex, nDepth := tree.InvertBitString(neighborBIndex) - neighborHash = v.hasher.HashEmpty(v.mapID, nIndex, nDepth) - } else { - neighborHash = sparse.FromBytes(neighbor) - } - - // The leaf index is processed starting from len(neighbors)-1 - // down to 0. If the index bit is 0, then neighbor is on the - // right, otherwise, neighbor is on the left. - switch bindex[len(neighbors)-1-i] { - case tree.Zero: - calculatedRoot = v.hasher.HashInterior(calculatedRoot, neighborHash) - case tree.One: - calculatedRoot = v.hasher.HashInterior(neighborHash, calculatedRoot) - default: - return sparse.Hash{}, ErrIndexBit - } - } - return calculatedRoot, nil -} - -// trimNeighbors trims all the empty values at the beginning of the neighbors -// list. The returned list is the one used in the proof of absence. -func trimNeighbors(neighbors [][]byte) [][]byte { - for i, v := range neighbors { - if len(v) != 0 { - return neighbors[i:] - } - } - return [][]byte{} -} diff --git a/core/tree/sparse/verifier/verifier_test.go b/core/tree/sparse/verifier/verifier_test.go deleted file mode 100644 index 6590fe782..000000000 --- a/core/tree/sparse/verifier/verifier_test.go +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package verifier - -import ( - "encoding/hex" - "strings" - "testing" - - "github.com/google/keytransparency/core/tree/sparse" - "golang.org/x/net/context" - - _ "github.com/mattn/go-sqlite3" // Use sqlite database for testing. -) - -const mapID = 0 - -var ( - ctx = context.Background() - AllZeros = strings.Repeat("0", 256/4) - defaultIndex = []string{ - "8000000000000000000000000000000000000000000000000000000000000001", - "C000000000000000000000000000000000000000000000000000000000000001", - "4000000000000000000000000000000000000000000000000000000000000001", - } -) - -type Leaf struct { - index []byte - value []byte - nbrs [][]byte -} - -/* -// generateNbrData constructs an in-memory tree, fills it with the provided leaves -// and returns a slice of inclusion proofs, one for each leaf. -func generateNbrData(t *testing.T, leaves []Leaf) ([][][]byte, error) { - // Generate test data. - clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) - sqldb, err := sql.Open("sqlite3", "file:dummy.db?mode=memory&cache=shared") - if err != nil { - return nil, err - } - factory := transaction.NewFactory(sqldb, nil) - m, err := sqlhist.New(context.Background(), sqldb, mapID, factory) - if err != nil { - return nil, err - } - for _, l := range leaves { - txn, err := factory.NewTxn(context.Background()) - if err != nil { - return nil, err - } - m.QueueLeaf(txn, l.index, l.value) - if err := txn.Commit(); err != nil { - return nil, err - } - } - m.Commit(context.Background()) - ret := make([][][]byte, 0) - for _, l := range leaves { - nbrs, err := m.NeighborsAt(context.Background(), l.index, m.Epoch()) - if err != nil { - return nil, err - } - ret = append(ret, nbrs) - } - return ret, nil -} -*/ - -func TestVerifyProof(t *testing.T) { - verifier := New(mapID, sparse.CONIKSHasher) - for _, tc := range []struct { - root []byte - leaves []Leaf - }{ - // Verify proof of absence in an empty tree. - { - dh("c2fbf0c12eb8ef812d24d08719fdf43bb805595386409baf0150c5e0947e49cd"), - []Leaf{ - {dh(AllZeros), nil, [][]byte{}}, - }, - }, - // Tree with multiple leaves, each has a single existing neighbor - // on the way to the root. - { - dh("58f340a870902df3604315000a0e3ab8c5e6969cfe2ed1ad48c2b8900a72de37"), - []Leaf{ - { - dh(defaultIndex[0]), - []byte("3"), - [][]byte{ - dh("1cf3d1d90436e6ad75eb2ff97816ffcad6f024c6eceb7b86b2c507efdf3567d7"), - {}, - }}, - { - dh(defaultIndex[1]), - []byte("4"), - [][]byte{ - dh("9ddd8781499f29bf51b9047da91e23d6fb18ea8b0439e4f10413ddd280cf2d20"), - {}, - }}, - { - dh(defaultIndex[2]), - nil, - [][]byte{ - dh("0a1db26319a01c8cef10b06c48d6dccce9ac5b951d5b91583a8346530d3d32a5"), - }}, - { - dh(AllZeros), - nil, - [][]byte{ - dh("0a1db26319a01c8cef10b06c48d6dccce9ac5b951d5b91583a8346530d3d32a5"), - }}, - }, - }, - // Tree with multiple leaves, some have multiple existing - // neighbors on the way to the root. - { - dh("bfb7ba5e680bb1382982f1d769733bea32eb602787b1064ebb9f699c1d1710ca"), - []Leaf{ - { - dh(defaultIndex[2]), - []byte("0"), - [][]byte{ - dh("0a1db26319a01c8cef10b06c48d6dccce9ac5b951d5b91583a8346530d3d32a5"), - }}, - { - dh(defaultIndex[0]), - []byte("3"), - [][]byte{ - dh("1cf3d1d90436e6ad75eb2ff97816ffcad6f024c6eceb7b86b2c507efdf3567d7"), - dh("22ed79bb41e8dbaf185691deee13645e6bd1d6faee90dc6d33b7a1342aa35555"), - }}, - { - dh(AllZeros), - nil, - [][]byte{ - dh("a714420de960d9c19e8963301cd7879762cf8255b06d383fba0ea8ab82d5b1c5"), - dh("0a1db26319a01c8cef10b06c48d6dccce9ac5b951d5b91583a8346530d3d32a5"), - }}, - }, - }, - } { - // VerifyProof of each leaf in the tree. - for _, leaf := range tc.leaves { - // The neighbor list must consists of 256 byte arrays, - // all are empty except the last len(leaf.nbrs) ones. - // Those are filled from leaf.nbrs. - nbrs := make([][]byte, 256) - for k, nbr := range leaf.nbrs { - nbrs[256-len(leaf.nbrs)+k] = nbr - } - - if err := verifier.VerifyProof(nbrs, leaf.index, leaf.value, sparse.FromBytes(tc.root)); err != nil { - t.Errorf("VerifyProof(_, %v, _, _)=%v", leaf.index, err) - } - } - } -} - -// Hex to Bytes -func dh(h string) []byte { - result, err := hex.DecodeString(h) - if err != nil { - panic("DecodeString failed") - } - return result -} diff --git a/scripts/map_payload.json b/scripts/map_payload.json index aa963817a..51ff52993 100644 --- a/scripts/map_payload.json +++ b/scripts/map_payload.json @@ -2,7 +2,7 @@ "tree":{ "tree_state":"ACTIVE", "tree_type":"MAP", - "hash_strategy":"TEST_MAP_HASHER", + "hash_strategy":"CONIKS_SHA512_256", "signature_algorithm":"ECDSA", "max_root_duration":"0", "hash_algorithm":"SHA256" @@ -12,4 +12,4 @@ "curve":"P256" } } -} \ No newline at end of file +} From 1388d7b262992b7dacfb7a04f0f4bebbc0382241 Mon Sep 17 00:00:00 2001 From: Gary Belvin Date: Thu, 13 Jul 2017 19:30:30 +0100 Subject: [PATCH 2/3] wip - I'm not sure --- .keytransparency.yaml | 9 +++-- cmd/keytransparency-client/cmd/root.go | 30 +++++++-------- .../grpcc/grpc_client.go | 7 ++-- core/client/kt/verify.go | 38 +++++++++---------- core/client/kt/verify_test.go | 5 ++- core/keyserver/keyserver.go | 16 +++----- docker-compose.yml | 1 - impl/sql/sqlhist/sqlhist.go | 14 ++++--- scripts/prepare_client.sh | 12 +++--- scripts/prepare_server.sh | 5 --- .../{p256-pubkey.pem => trillian-map.pem} | 0 11 files changed, 64 insertions(+), 73 deletions(-) rename testdata/{p256-pubkey.pem => trillian-map.pem} (100%) diff --git a/.keytransparency.yaml b/.keytransparency.yaml index b5be7dce3..85fb3ab04 100644 --- a/.keytransparency.yaml +++ b/.keytransparency.yaml @@ -1,8 +1,9 @@ -log-key: "genfiles/trillian-log.pem" +kt-url: "localhost:8080" +#kt-url: "35.184.134.53:8080" +kt-cert: "genfiles/server.crt" vrf: "genfiles/vrf-pubkey.pem" -kt-key: "genfiles/server.crt" -kt-sig: "genfiles/p256-pubkey.pem" domain: "example.com" -kt-url: "35.184.134.53:8080" +log-key: "genfiles/trillian-log.pem" +map-key: "genfiles/trillian-map.pem" client-secret: "client_secret.json" service-key: "" diff --git a/cmd/keytransparency-client/cmd/root.go b/cmd/keytransparency-client/cmd/root.go index c9b8095be..1cf675897 100644 --- a/cmd/keytransparency-client/cmd/root.go +++ b/cmd/keytransparency-client/cmd/root.go @@ -20,6 +20,7 @@ import ( "log" "net" "os" + "strings" "time" "github.com/google/keytransparency/cmd/keytransparency-client/grpcc" @@ -31,6 +32,7 @@ import ( "github.com/google/keytransparency/core/crypto/vrf/p256" gauth "github.com/google/keytransparency/impl/google/authentication" pb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" + "github.com/google/trillian" "github.com/google/trillian" "github.com/google/trillian/client" @@ -83,11 +85,10 @@ func init() { RootCmd.PersistentFlags().String("log-url", "", "URL of Certificate Transparency server") RootCmd.PersistentFlags().String("log-key", "", "Path to public key PEM for Trillian Log server") - RootCmd.PersistentFlags().Int64("map-id", 0, "Map ID of the backend map server") + RootCmd.PersistentFlags().String("map-key", "genfiles/trillian-map.pem", "Path to public key for signed map heads") RootCmd.PersistentFlags().String("kt-url", "", "URL of Key Transparency server") - RootCmd.PersistentFlags().String("kt-key", "testdata/server.crt", "Path to public key for Key Transparency") - RootCmd.PersistentFlags().String("kt-sig", "testdata/p256-pubkey.pem", "Path to public key for signed map heads") + RootCmd.PersistentFlags().String("kt-cert", "genfiles/server.crt", "Path to public key for Key Transparency") RootCmd.PersistentFlags().String("fake-auth-userid", "", "userid to present to the server as identity for authentication. Only succeeds if fake auth is enabled on the server side.") @@ -101,8 +102,8 @@ func init() { // initConfig reads in config file and ENV variables if set. func initConfig() { + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) viper.AutomaticEnv() // Read in environment variables that match. - if cfgFile != "" { viper.SetConfigFile(cfgFile) if err := viper.ReadInConfig(); err != nil { @@ -186,18 +187,18 @@ func readSignatureVerifier(ktPEM string) (signatures.Verifier, error) { return ver, nil } -func getClient(cc *grpc.ClientConn, mapID int64, vrfPubFile, ktSig string, log client.LogVerifier) (*grpcc.Client, error) { +func getClient(cc *grpc.ClientConn, vrfPubFile, mapKeyFile string, log client.LogVerifier) (*grpcc.Client, error) { // Create Key Transparency client. vrfKey, err := readVrfKey(vrfPubFile) if err != nil { return nil, err } - verifier, err := readSignatureVerifier(ktSig) + mapKey, err := readSignatureVerifier(mapKeyFile) if err != nil { return nil, fmt.Errorf("error reading key transparency PEM: %v", err) } cli := pb.NewKeyTransparencyServiceClient(cc) - return grpcc.New(mapID, cli, vrfKey, verifier, log), nil + return grpcc.New(cli, vrfKey, mapKey, log), nil } func dial(ktURL, caFile, clientSecretFile string, serviceKeyFile string) (*grpc.ClientConn, error) { @@ -255,20 +256,19 @@ func dial(ktURL, caFile, clientSecretFile string, serviceKeyFile string) (*grpc. func GetClient(clientSecretFile string) (*grpcc.Client, error) { vrfFile := viper.GetString("vrf") ktURL := viper.GetString("kt-url") - ktPEM := viper.GetString("kt-key") - ktSig := viper.GetString("kt-sig") - mapID := viper.GetInt64("map-id") + ktCert := viper.GetString("kt-cert") + mapKey := viper.GetString("map-key") logPEM := viper.GetString("log-key") serviceKeyFile := viper.GetString("service-key") - cc, err := dial(ktURL, ktPEM, clientSecretFile, serviceKeyFile) + cc, err := dial(ktURL, ktCert, clientSecretFile, serviceKeyFile) if err != nil { - return nil, fmt.Errorf("Error Dialing %v: %v", ktURL, err) + return nil, fmt.Errorf("Dial(%v): %v", ktURL, err) } // Log verifier. logPubKey, err := keys.NewFromPublicPEMFile(logPEM) if err != nil { - return nil, fmt.Errorf("Failed to open public key %v: %v", logPubKey, err) + return nil, fmt.Errorf("NewFromPublicPEMFile(%v): %v", logPubKey, err) } hasher, err := hashers.NewLogHasher(trillian.HashStrategy_OBJECT_RFC6962_SHA256) @@ -277,9 +277,9 @@ func GetClient(clientSecretFile string) (*grpcc.Client, error) { } log := client.NewLogVerifier(hasher, logPubKey) - c, err := getClient(cc, mapID, vrfFile, ktSig, log) + c, err := getClient(cc, vrfFile, mapKey, log) if err != nil { - return nil, fmt.Errorf("Error creating client: %v", err) + return nil, fmt.Errorf("error creating client: %v", err) } return c, nil } diff --git a/cmd/keytransparency-client/grpcc/grpc_client.go b/cmd/keytransparency-client/grpcc/grpc_client.go index ef33edf61..c264567fd 100644 --- a/cmd/keytransparency-client/grpcc/grpc_client.go +++ b/cmd/keytransparency-client/grpcc/grpc_client.go @@ -90,15 +90,14 @@ type Client struct { } // New creates a new client. -func New(mapID int64, - client spb.KeyTransparencyServiceClient, +func New(client spb.KeyTransparencyServiceClient, vrf vrf.PublicKey, - verifier crypto.PublicKey, + mapKey crypto.PublicKey, log client.LogVerifier) *Client { return &Client{ cli: client, vrf: vrf, - kt: kt.New(mapID, vrf, coniks.Default, verifier, log), + kt: kt.New(vrf, coniks.Default, mapKey, log), log: log, mutator: entry.New(), RetryCount: 1, diff --git a/core/client/kt/verify.go b/core/client/kt/verify.go index 44d6ae858..54439d417 100644 --- a/core/client/kt/verify.go +++ b/core/client/kt/verify.go @@ -15,6 +15,7 @@ package kt import ( + "bytes" "crypto" "encoding/json" "errors" @@ -46,24 +47,21 @@ var ( // Verifier is a client helper library for verifying request and responses. type Verifier struct { - mapID int64 vrf vrf.PublicKey hasher hashers.MapHasher - sig crypto.PublicKey + mapKey crypto.PublicKey log client.LogVerifier } // New creates a new instance of the client verifier. -func New(mapID int64, - vrf vrf.PublicKey, +func New(vrf vrf.PublicKey, hasher hashers.MapHasher, - sig crypto.PublicKey, + mapKey crypto.PublicKey, log client.LogVerifier) *Verifier { return &Verifier{ - mapID: mapID, vrf: vrf, hasher: hasher, - sig: sig, + mapKey: mapKey, log: log, } } @@ -99,31 +97,31 @@ func (v *Verifier) VerifyGetEntryResponse(ctx context.Context, userID, appID str index, err := v.vrf.ProofToHash(vrf.UniqueID(userID, appID), in.VrfProof) if err != nil { - Vlog.Printf("✗ VRF verification failed.") + Vlog.Printf("✗ Index verification failed.") return fmt.Errorf("vrf.ProofToHash(%v, %v): %v", userID, appID, err) } - Vlog.Printf("✓ VRF verified.") - - leafProof := in.GetLeafProof() - if leafProof == nil { - return ErrNilProof + if got, want := in.GetLeafProof().GetLeaf().GetIndex(), index[:]; !bytes.Equal(got, want) { + return fmt.Errorf("Leaf.Index: %x, want %x", got, want) } + Vlog.Printf("✓ Index verified.") - leaf := leafProof.GetLeaf().GetLeafValue() - proof := leafProof.GetInclusion() + mapID := in.GetSmr().GetMapId() + leafValue := in.GetLeafProof().GetLeaf().GetLeafValue() + leafHash := v.hasher.HashLeaf(mapID, index[:], v.hasher.BitLen(), leafValue) + proof := in.GetLeafProof().GetInclusion() expectedRoot := in.GetSmr().GetRootHash() - if err := merkle.VerifyMapInclusionProof(v.mapID, index[:], leaf, expectedRoot, proof, v.hasher); err != nil { - Vlog.Printf("✗ Sparse tree proof verification failed.") + if err := merkle.VerifyMapInclusionProof(mapID, index[:], leafHash, expectedRoot, proof, v.hasher); err != nil { + Vlog.Printf("✗ Map inclusion proof failed.") return fmt.Errorf("VerifyMapInclusionProof(): %v", err) } - Vlog.Printf("✓ Sparse tree proof verified.") + Vlog.Printf("✓ Map inclusion proof verified.") // SignedMapRoot contains its own signature. To verify, we need to create a local // copy of the object and return the object to the state it was in when signed // by removing the signature from the object. smr := *in.GetSmr() smr.Signature = nil // Remove the signature from the object to be verified. - if err := tcrypto.VerifyObject(v.sig, smr, in.GetSmr().Signature); err != nil { + if err := tcrypto.VerifyObject(v.mapKey, smr, in.GetSmr().Signature); err != nil { Vlog.Printf("✗ Signed Map Head signature verification failed.") return fmt.Errorf("sig.Verify(SMR): %v", err) } @@ -131,7 +129,7 @@ func (v *Verifier) VerifyGetEntryResponse(ctx context.Context, userID, appID str // Verify consistency proof between root and newroot. // TODO(gdbelvin): Gossip root. - if err := v.log.VerifyRoot(trusted, in.LogRoot, in.LogConsistency); err != nil { + if err := v.log.VerifyRoot(trusted, in.GetLogRoot(), in.GetLogConsistency()); err != nil { return fmt.Errorf("VerifyRoot(%v, %v): %v", in.LogRoot, in.LogConsistency, err) } Vlog.Printf("✓ Log root updated.") diff --git a/core/client/kt/verify_test.go b/core/client/kt/verify_test.go index f7978965a..92233450e 100644 --- a/core/client/kt/verify_test.go +++ b/core/client/kt/verify_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/google/keytransparency/core/crypto/commitments" + "github.com/google/trillian/merkle/coniks" "github.com/golang/protobuf/proto" @@ -46,7 +47,7 @@ func TestVerifyCommitment(t *testing.T) { fakeEntryData := validEntryData[:len(validEntryData)-1] // Create a dummy client verifier. - verifier := New(nil, nil, nil, nil) + verifier := New(0, nil, coniks.Default, nil, nil) for _, tc := range []struct { userID, appID string entryData []byte @@ -71,3 +72,5 @@ func TestVerifyCommitment(t *testing.T) { } } } + +// TODO(gbelvin): add test for VerifyGetEntryResponse. diff --git a/core/keyserver/keyserver.go b/core/keyserver/keyserver.go index 9e5a72b3e..848031345 100644 --- a/core/keyserver/keyserver.go +++ b/core/keyserver/keyserver.go @@ -106,12 +106,11 @@ func (s *Server) getEntry(ctx context.Context, userID, appID string, firstTreeSi glog.Errorf("GetLeaves(): %v", err) return nil, grpc.Errorf(codes.Internal, "Failed fetching map leaf") } - if got, want := len(getResp.MapLeafInclusion), 1; got != want { + if got, want := len(getResp.GetMapLeafInclusion()), 1; got != want { glog.Errorf("GetLeaves() len: %v, want %v", got, want) return nil, grpc.Errorf(codes.Internal, "Failed fetching map leaf") } - neighbors := getResp.MapLeafInclusion[0].Inclusion - leaf := getResp.MapLeafInclusion[0].Leaf.LeafValue + leaf := getResp.MapLeafInclusion[0].GetLeaf().GetLeafValue() var committed *tpb.Committed if leaf != nil { @@ -177,14 +176,9 @@ func (s *Server) getEntry(ctx context.Context, userID, appID string, firstTreeSi } return &tpb.GetEntryResponse{ - VrfProof: proof, - Committed: committed, - LeafProof: &trillian.MapLeafInclusion{ - Inclusion: neighbors, - Leaf: &trillian.MapLeaf{ - LeafValue: leaf, - }, - }, + VrfProof: proof, + Committed: committed, + LeafProof: getResp.MapLeafInclusion[0], Smr: getResp.GetMapRoot(), LogRoot: logRoot.GetSignedLogRoot(), LogConsistency: logConsistency.GetProof().GetHashes(), diff --git a/docker-compose.yml b/docker-compose.yml index f46cab3a3..621d607de 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -58,7 +58,6 @@ services: DB_PASSWORD: zaphod SEQUENCER_INTERVAL: 1s - trillian-map: depends_on: - db diff --git a/impl/sql/sqlhist/sqlhist.go b/impl/sql/sqlhist/sqlhist.go index c0600c035..9416c5a95 100644 --- a/impl/sql/sqlhist/sqlhist.go +++ b/impl/sql/sqlhist/sqlhist.go @@ -18,6 +18,7 @@ package sqlhist import ( + "bytes" "crypto/sha256" "database/sql" "encoding/binary" @@ -27,6 +28,7 @@ import ( "github.com/google/keytransparency/core/transaction" "github.com/google/keytransparency/core/tree" "github.com/google/keytransparency/core/tree/sparse" + "github.com/google/trillian/merkle/coniks" "golang.org/x/net/context" ) @@ -57,15 +59,15 @@ var ( FOREIGN KEY(MapID) REFERENCES Maps(MapID) ON DELETE CASCADE );`, } - hasher = sparse.CONIKSHasher + hasher = coniks.Default errNilLeaf = errors.New("nil leaf") errIndexLen = errors.New("index len != 32") errInvalidEpoch = errors.New("invalid epoch") + maxDepth = hasher.BitLen() + size = hasher.Size() ) const ( - maxDepth = sparse.IndexLen - size = sparse.HashSize insertMapRowExpr = `INSERT INTO Maps (MapID) VALUES (?);` countMapRowExpr = `SELECT COUNT(*) AS count FROM Maps WHERE MapID = ?;` readExpr = ` @@ -311,10 +313,10 @@ func compressNeighbors(mapID int64, neighbors []sparse.Hash, index []byte, depth neighborBIndexes := tree.Neighbors(bindex) compressed := make([][]byte, len(neighbors)) for i, v := range neighbors { - // TODO: convert values to arrays rather than slices for comparison. nIndex, nDepth := tree.InvertBitString(neighborBIndexes[i]) - if v != hasher.HashEmpty(mapID, nIndex, nDepth) { - compressed[i] = v.Bytes() + emptyHash := hasher.HashEmpty(mapID, nIndex, nDepth) + if !bytes.Equal(v, emptyHash) { + compressed[i] = v } } return compressed diff --git a/scripts/prepare_client.sh b/scripts/prepare_client.sh index 13be2337d..285974c52 100755 --- a/scripts/prepare_client.sh +++ b/scripts/prepare_client.sh @@ -18,7 +18,7 @@ VRFDEFAULT="testdata/vrf-pubkey.pem" VRF="" KTKEYDEFAULT="testdata/server.crt" KTKEY="" -SIGKEYDEFAULT="testdata/p256-pubkey.pem" +SIGKEYDEFAULT="testdata/trillian-map.pem" SIGKEY="" DOMAINDEFAULT="example.com" DOMAIN="" @@ -71,13 +71,13 @@ go build ./cmd/keytransparency-client # TODO(ismail): fetch the keys from the discovery API (#672) # Generate .keytransparency.yaml file. -KTYAML="log-key: \"../trillian/testdata/log-rpc-server.pubkey.pem\" +KTYAML=" +kt-url: \"${KTURL}\" +kt-cert: \"${KTKEY}\" vrf: \"${VRF}\" -kt-key: \"${KTKEY}\" -kt-sig: \"${SIGKEY}\" domain: \"${DOMAIN}\" -mapid: ${MAP_ID} -kt-url: \"${KTURL}\" +log-key: \"../trillian/testdata/ct-http-server.pubkey.pem\" +map-key: \"${SIGKEY}\" client-secret: \"${CLIENTSECRET}\" service-key: \"${SERVICEKEY}\"" diff --git a/scripts/prepare_server.sh b/scripts/prepare_server.sh index c8b605f03..141f42a5b 100755 --- a/scripts/prepare_server.sh +++ b/scripts/prepare_server.sh @@ -155,9 +155,4 @@ VRF_PRIV=\"genfiles/vrf-key.pem\" VRF_PUB=\"genfiles/vrf-pubkey.pem\"" fi -if ((BACKEND == 1)); then - ENV="${ENV} -SIGN_KEY=\"genfiles/p256-key.pem\"" -fi - printf "%s\n" "${ENV}" > .env diff --git a/testdata/p256-pubkey.pem b/testdata/trillian-map.pem similarity index 100% rename from testdata/p256-pubkey.pem rename to testdata/trillian-map.pem From 47c2c45b7c638e983ed7e8c540e92fe3abe70ce3 Mon Sep 17 00:00:00 2001 From: Gary Belvin Date: Tue, 18 Jul 2017 20:54:32 +0100 Subject: [PATCH 3/3] use TEST_MAP_HASHER --- .keytransparency.yaml | 1 - cmd/keytransparency-client/cmd/root.go | 46 +++++++++---------- .../grpcc/grpc_client.go | 8 ++-- core/client/kt/verify.go | 3 +- docker-compose.yml | 4 +- scripts/map_payload.json | 2 +- 6 files changed, 31 insertions(+), 33 deletions(-) diff --git a/.keytransparency.yaml b/.keytransparency.yaml index 85fb3ab04..4f4128ea6 100644 --- a/.keytransparency.yaml +++ b/.keytransparency.yaml @@ -1,5 +1,4 @@ kt-url: "localhost:8080" -#kt-url: "35.184.134.53:8080" kt-cert: "genfiles/server.crt" vrf: "genfiles/vrf-pubkey.pem" domain: "example.com" diff --git a/cmd/keytransparency-client/cmd/root.go b/cmd/keytransparency-client/cmd/root.go index 1cf675897..319db0aa0 100644 --- a/cmd/keytransparency-client/cmd/root.go +++ b/cmd/keytransparency-client/cmd/root.go @@ -26,19 +26,12 @@ import ( "github.com/google/keytransparency/cmd/keytransparency-client/grpcc" "github.com/google/keytransparency/core/authentication" "github.com/google/keytransparency/core/client/kt" - "github.com/google/keytransparency/core/crypto/keymaster" - "github.com/google/keytransparency/core/crypto/signatures" "github.com/google/keytransparency/core/crypto/vrf" "github.com/google/keytransparency/core/crypto/vrf/p256" - gauth "github.com/google/keytransparency/impl/google/authentication" - pb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" - "github.com/google/trillian" - "github.com/google/trillian" "github.com/google/trillian/client" "github.com/google/trillian/crypto/keys" "github.com/google/trillian/merkle/hashers" - _ "github.com/google/trillian/merkle/objhasher" // Register objhasher "github.com/spf13/cobra" "github.com/spf13/viper" "golang.org/x/oauth2" @@ -46,6 +39,13 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/oauth" + + _ "github.com/google/trillian/merkle/coniks" // Register coniks + _ "github.com/google/trillian/merkle/maphasher" // Register maphasher + _ "github.com/google/trillian/merkle/objhasher" // Register objhasher + + gauth "github.com/google/keytransparency/impl/google/authentication" + pb "github.com/google/keytransparency/impl/proto/keytransparency_v1_service" ) var ( @@ -86,6 +86,7 @@ func init() { RootCmd.PersistentFlags().String("log-key", "", "Path to public key PEM for Trillian Log server") RootCmd.PersistentFlags().String("map-key", "genfiles/trillian-map.pem", "Path to public key for signed map heads") + RootCmd.PersistentFlags().String("map-hasher", "TEST_MAP_HASHER", "Hash strategy used by map") RootCmd.PersistentFlags().String("kt-url", "", "URL of Key Transparency server") RootCmd.PersistentFlags().String("kt-cert", "genfiles/server.crt", "Path to public key for Key Transparency") @@ -175,30 +176,19 @@ func getServiceCreds(serviceKeyFile string) (credentials.PerRPCCredentials, erro return oauth.NewServiceAccountFromKey(b, gauth.RequiredScopes...) } -func readSignatureVerifier(ktPEM string) (signatures.Verifier, error) { - pem, err := ioutil.ReadFile(ktPEM) - if err != nil { - return nil, err - } - ver, err := keymaster.NewVerifierFromPEM(pem) - if err != nil { - return nil, err - } - return ver, nil -} - -func getClient(cc *grpc.ClientConn, vrfPubFile, mapKeyFile string, log client.LogVerifier) (*grpcc.Client, error) { +func getClient(cc *grpc.ClientConn, vrfPubFile, mapKeyFile string, mapHasher hashers.MapHasher, log client.LogVerifier) (*grpcc.Client, error) { // Create Key Transparency client. vrfKey, err := readVrfKey(vrfPubFile) if err != nil { return nil, err } - mapKey, err := readSignatureVerifier(mapKeyFile) + mapKey, err := keys.NewFromPublicPEMFile(mapKeyFile) if err != nil { return nil, fmt.Errorf("error reading key transparency PEM: %v", err) } + cli := pb.NewKeyTransparencyServiceClient(cc) - return grpcc.New(cli, vrfKey, mapKey, log), nil + return grpcc.New(cli, vrfKey, mapKey, mapHasher, log), nil } func dial(ktURL, caFile, clientSecretFile string, serviceKeyFile string) (*grpc.ClientConn, error) { @@ -258,6 +248,7 @@ func GetClient(clientSecretFile string) (*grpcc.Client, error) { ktURL := viper.GetString("kt-url") ktCert := viper.GetString("kt-cert") mapKey := viper.GetString("map-key") + mapHashStrategy := viper.GetString("map-hasher") logPEM := viper.GetString("log-key") serviceKeyFile := viper.GetString("service-key") cc, err := dial(ktURL, ktCert, clientSecretFile, serviceKeyFile) @@ -271,13 +262,18 @@ func GetClient(clientSecretFile string) (*grpcc.Client, error) { return nil, fmt.Errorf("NewFromPublicPEMFile(%v): %v", logPubKey, err) } - hasher, err := hashers.NewLogHasher(trillian.HashStrategy_OBJECT_RFC6962_SHA256) + logHasher, err := hashers.NewLogHasher(trillian.HashStrategy_OBJECT_RFC6962_SHA256) if err != nil { return nil, fmt.Errorf("Failed retrieving LogHasher from registry: %v", err) } - log := client.NewLogVerifier(hasher, logPubKey) + log := client.NewLogVerifier(logHasher, logPubKey) + + mapHasher, err := hashers.NewMapHasher(trillian.HashStrategy(trillian.HashStrategy_value[mapHashStrategy])) + if err != nil { + return nil, fmt.Errorf("Failed retrieving MapHasher from registry: %v", err) + } - c, err := getClient(cc, vrfFile, mapKey, log) + c, err := getClient(cc, vrfFile, mapKey, mapHasher, log) if err != nil { return nil, fmt.Errorf("error creating client: %v", err) } diff --git a/cmd/keytransparency-client/grpcc/grpc_client.go b/cmd/keytransparency-client/grpcc/grpc_client.go index c264567fd..079baab5d 100644 --- a/cmd/keytransparency-client/grpcc/grpc_client.go +++ b/cmd/keytransparency-client/grpcc/grpc_client.go @@ -34,7 +34,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/google/trillian/client" - "github.com/google/trillian/merkle/coniks" + "github.com/google/trillian/merkle/hashers" "golang.org/x/net/context" "google.golang.org/grpc" @@ -93,11 +93,12 @@ type Client struct { func New(client spb.KeyTransparencyServiceClient, vrf vrf.PublicKey, mapKey crypto.PublicKey, + mapHasher hashers.MapHasher, log client.LogVerifier) *Client { return &Client{ cli: client, vrf: vrf, - kt: kt.New(vrf, coniks.Default, mapKey, log), + kt: kt.New(vrf, mapHasher, mapKey, log), log: log, mutator: entry.New(), RetryCount: 1, @@ -239,7 +240,8 @@ func (c *Client) Retry(ctx context.Context, req *tpb.UpdateEntryRequest) error { } // Check if the response is a replay. - if got, want := updateResp.GetProof().GetLeafProof().Leaf.LeafValue, req.GetEntryUpdate().GetUpdate().GetKeyValue().GetValue(); !bytes.Equal(got, want) { + if got, want := updateResp.GetProof().GetLeafProof().GetLeaf().GetLeafValue(), + req.GetEntryUpdate().GetUpdate().GetKeyValue().GetValue(); !bytes.Equal(got, want) { return ErrRetry } return nil diff --git a/core/client/kt/verify.go b/core/client/kt/verify.go index 54439d417..7896315bc 100644 --- a/core/client/kt/verify.go +++ b/core/client/kt/verify.go @@ -121,7 +121,8 @@ func (v *Verifier) VerifyGetEntryResponse(ctx context.Context, userID, appID str // by removing the signature from the object. smr := *in.GetSmr() smr.Signature = nil // Remove the signature from the object to be verified. - if err := tcrypto.VerifyObject(v.mapKey, smr, in.GetSmr().Signature); err != nil { + Vlog.Printf("? smr: %#v", smr) + if err := tcrypto.VerifyObject(v.mapKey, smr, in.GetSmr().GetSignature()); err != nil { Vlog.Printf("✗ Signed Map Head signature verification failed.") return fmt.Errorf("sig.Verify(SMR): %v", err) } diff --git a/docker-compose.yml b/docker-compose.yml index 621d607de..5a946674f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -125,6 +125,6 @@ services: LOG_KEY: /kt/trillian-log.pem SIGN_KEY: /kt/p256-key.pem SIGN_KEY_PW: towel - MIN_SIGN_PERIOD: 5s - MAX_SIGN_PERIOD: 5m + MIN_SIGN_PERIOD: 2s + MAX_SIGN_PERIOD: 10s VERBOSITY: 5 diff --git a/scripts/map_payload.json b/scripts/map_payload.json index 51ff52993..fe1754aff 100644 --- a/scripts/map_payload.json +++ b/scripts/map_payload.json @@ -2,7 +2,7 @@ "tree":{ "tree_state":"ACTIVE", "tree_type":"MAP", - "hash_strategy":"CONIKS_SHA512_256", + "hash_strategy":"TEST_MAP_HASHER", "signature_algorithm":"ECDSA", "max_root_duration":"0", "hash_algorithm":"SHA256"