Skip to content

Commit

Permalink
Unexport HashLogRoot. Verify with VerifySignedLogRoot. (#1042)
Browse files Browse the repository at this point in the history
* SignedLogRoot <-> VerifySignedLogRoot

SignLogRoot should produce a *trillian.SignedLogRoot
VerifyLogRoot should verify a *trillian.SignedLogRoot

This prevents clients from needing to parse the SignedLogRoot object
themslves. It also provides a single API point to maintain.

VerifySignedLogRoot will produce a *trillian.SignedLogRoot.
The idea is the force clients to only use data that has been returned
from a successful verification.

* Unexport HashLogRoot

* reviewer edits
  • Loading branch information
gdbelvin authored Mar 8, 2018
1 parent 36c4f21 commit 0e6d950
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 57 deletions.
6 changes: 1 addition & 5 deletions client/log_verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,7 @@ func (c *LogVerifier) VerifyRoot(trusted, newRoot *trillian.SignedLogRoot,
}

// Verify SignedLogRoot signature.
hash, err := tcrypto.HashLogRoot(*newRoot)
if err != nil {
return err
}
if err := tcrypto.Verify(c.pubKey, hash, newRoot.Signature); err != nil {
if _, err := tcrypto.VerifySignedLogRoot(c.pubKey, newRoot); err != nil {
return err
}

Expand Down
12 changes: 3 additions & 9 deletions client/log_verifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,18 @@ func TestVerifyRootErrors(t *testing.T) {
t.Fatalf("Failed to load public key, err=%v", err)
}

signedRoot := trillian.SignedLogRoot{}
hash, err := tcrypto.HashLogRoot(signedRoot)
if err != nil {
t.Fatalf("HashLogRoot(): %v", err)
}
signature, err := signer.Sign(hash)
signedRoot, err := signer.SignLogRoot(&trillian.SignedLogRoot{})
if err != nil {
t.Fatal("Failed to create test signature")
}
signedRoot.Signature = signature

// Test execution
tests := []struct {
desc string
trusted, newRoot *trillian.SignedLogRoot
}{
{desc: "newRootNil", trusted: &signedRoot, newRoot: nil},
{desc: "trustedNil", trusted: nil, newRoot: &signedRoot},
{desc: "newRootNil", trusted: signedRoot, newRoot: nil},
{desc: "trustedNil", trusted: nil, newRoot: signedRoot},
}
for _, test := range tests {
logVerifier := NewLogVerifier(rfc6962.DefaultHasher, pk)
Expand Down
4 changes: 2 additions & 2 deletions crypto/data_formats.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ const (
mapKeyTreeSize string = "TreeSize"
)

// HashLogRoot hashes SignedLogRoot objects using ObjectHash with
// hashLogRoot hashes SignedLogRoot objects using ObjectHash with
// "RootHash", "TimestampNanos", and "TreeSize", used as keys in
// a map.
func HashLogRoot(root trillian.SignedLogRoot) ([]byte, error) {
func hashLogRoot(root trillian.SignedLogRoot) ([]byte, error) {
// Pull out the fields we want to hash.
// Caution: use string format for int64 values as they can overflow when
// JSON encoded otherwise (it uses floats). We want to be sure that people
Expand Down
4 changes: 2 additions & 2 deletions crypto/data_formats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestHashLogRootKnownValue(t *testing.T) {
RootHash: []byte("Some bytes that won't change"),
TreeSize: 167329345,
}
hash, err := HashLogRoot(root)
hash, err := hashLogRoot(root)
if err != nil {
t.Fatalf("HashLogRoot(): %v", err)
}
Expand Down Expand Up @@ -75,7 +75,7 @@ func TestHashLogRoot(t *testing.T) {
},
},
} {
hash, err := HashLogRoot(test.root)
hash, err := hashLogRoot(test.root)
if err != nil {
t.Fatalf("HashLogRoot(): %v", err)
}
Expand Down
12 changes: 7 additions & 5 deletions crypto/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,9 @@ func (s *Signer) SignObject(obj interface{}) (*sigpb.DigitallySigned, error) {
return s.Sign(hash[:])
}

// SignLogRoot hashes and signs the supplied (to-be) SignedLogRoot and returns a
// signature. Hashing is performed by github.com/benlaurie/objecthash.
func (s *Signer) SignLogRoot(root *trillian.SignedLogRoot) (*sigpb.DigitallySigned, error) {
hash, err := HashLogRoot(*root)
// SignLogRoot returns a complete SignedLogRoot (including signature).
func (s *Signer) SignLogRoot(root *trillian.SignedLogRoot) (*trillian.SignedLogRoot, error) {
hash, err := hashLogRoot(*root)
if err != nil {
return nil, err
}
Expand All @@ -96,7 +95,10 @@ func (s *Signer) SignLogRoot(root *trillian.SignedLogRoot) (*sigpb.DigitallySign
return nil, err
}

return signature, nil
ret := *root // Don't modify the input variable.
ret.Signature = signature

return &ret, nil
}

// SignMapRoot hashes and signs the supplied (to-be) SignedMapRoot and returns a
Expand Down
18 changes: 6 additions & 12 deletions crypto/signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func TestSignWithSignedLogRoot_SignerFails(t *testing.T) {

s := testonly.NewSignerWithErr(key, errors.New("signfail"))
root := trillian.SignedLogRoot{TimestampNanos: 2267709, RootHash: []byte("Islington"), TreeSize: 2}
hash, err := HashLogRoot(root)
hash, err := hashLogRoot(root)
if err != nil {
t.Fatalf("HashLogRoot(): %v", err)
}
Expand All @@ -110,28 +110,22 @@ func TestSignLogRoot(t *testing.T) {
}{
{root: trillian.SignedLogRoot{TimestampNanos: 2267709, RootHash: []byte("Islington"), TreeSize: 2}},
} {
sig, err := signer.SignLogRoot(&test.root)
slr, err := signer.SignLogRoot(&test.root)
if err != nil {
t.Errorf("Failed to sign log root: %v", err)
continue
}
if got := len(sig.Signature); got == 0 {
if got := len(slr.Signature.Signature); got == 0 {
t.Errorf("len(sig): %v, want > 0", got)
}
if got, want := sig.HashAlgorithm, sigpb.DigitallySigned_SHA256; got != want {
if got, want := slr.Signature.HashAlgorithm, sigpb.DigitallySigned_SHA256; got != want {
t.Errorf("Hash alg incorrect, got %s expected %s", got, want)
}
if got, want := sig.SignatureAlgorithm, sigpb.DigitallySigned_ECDSA; got != want {
if got, want := slr.Signature.SignatureAlgorithm, sigpb.DigitallySigned_ECDSA; got != want {
t.Errorf("Sig alg incorrect, got %s expected %s", got, want)
}
// Check that the signature is correct
obj, err := HashLogRoot(test.root)
if err != nil {
t.Errorf("HashLogRoot err: got %v want nil", err)
continue
}

if err := Verify(key.Public(), obj, sig); err != nil {
if _, err := VerifySignedLogRoot(key.Public(), slr); err != nil {
t.Errorf("Verify(%v) failed: %v", test.root, err)
}
}
Expand Down
15 changes: 15 additions & 0 deletions crypto/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"math/big"

"github.com/benlaurie/objecthash/go/objecthash"
"github.com/google/trillian"
"github.com/google/trillian/crypto/sigpb"
)

Expand All @@ -36,6 +37,20 @@ var (
}
)

// VerifySignedLogRoot verifies the SignedLogRoot and returns its contents.
func VerifySignedLogRoot(pub crypto.PublicKey, r *trillian.SignedLogRoot) (*trillian.SignedLogRoot, error) {
// Verify SignedLogRoot signature.
hash, err := hashLogRoot(*r)
if err != nil {
return nil, err
}
if err := Verify(pub, hash, r.Signature); err != nil {
return nil, err
}
return r, nil

}

// VerifyObject verifies the output of Signer.SignObject.
func VerifyObject(pub crypto.PublicKey, obj interface{}, sig *sigpb.DigitallySigned) error {
j, err := json.Marshal(obj)
Expand Down
12 changes: 4 additions & 8 deletions log/sequencer.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,19 +385,17 @@ func (s Sequencer) IntegrateBatch(ctx context.Context, tree *trillian.Tree, limi

// Create the log root ready for signing
seqTreeSize.Set(float64(merkleTree.Size()), label)
newLogRoot = &trillian.SignedLogRoot{
newLogRoot, err := s.signer.SignLogRoot(&trillian.SignedLogRoot{
RootHash: merkleTree.CurrentRoot(),
TimestampNanos: s.timeSource.Now().UnixNano(),
TreeSize: merkleTree.Size(),
LogId: currentRoot.LogId,
TreeRevision: newVersion,
}
sig, err := s.signer.SignLogRoot(newLogRoot)
})
if err != nil {
glog.Warningf("%v: signer failed to sign root: %v", tree.TreeId, err)
return err
}
newLogRoot.Signature = sig

if err := tx.StoreSignedLogRoot(ctx, *newLogRoot); err != nil {
glog.Warningf("%v: failed to write updated tree root: %v", tree.TreeId, err)
Expand Down Expand Up @@ -457,19 +455,17 @@ func (s Sequencer) SignRoot(ctx context.Context, tree *trillian.Tree) error {
if err != nil {
return err
}
newLogRoot := &trillian.SignedLogRoot{
newLogRoot, err := s.signer.SignLogRoot(&trillian.SignedLogRoot{
RootHash: merkleTree.CurrentRoot(),
TimestampNanos: s.timeSource.Now().UnixNano(),
TreeSize: merkleTree.Size(),
LogId: currentRoot.LogId,
TreeRevision: currentRoot.TreeRevision + 1,
}
sig, err := s.signer.SignLogRoot(newLogRoot)
})
if err != nil {
glog.Warningf("%v: signer failed to sign root: %v", tree.TreeId, err)
return err
}
newLogRoot.Signature = sig

// Store the new root and we're done
if err := tx.StoreSignedLogRoot(ctx, *newLogRoot); err != nil {
Expand Down
18 changes: 8 additions & 10 deletions server/log_rpc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,24 +599,22 @@ func (t *TrillianLogRPCServer) InitLog(ctx context.Context, req *trillian.InitLo
return status.Errorf(codes.AlreadyExists, "log is already initialised")
}

newRoot = &trillian.SignedLogRoot{
RootHash: hasher.EmptyRoot(),
TimestampNanos: t.timeSource.Now().UnixNano(),
TreeSize: 0,
LogId: logID,
TreeRevision: 0,
}

signer, err := trees.Signer(ctx, tree)
if err != nil {
return status.Errorf(codes.FailedPrecondition, "Signer() :%v", err)
}

sig, err := signer.SignLogRoot(newRoot)
root, err := signer.SignLogRoot(&trillian.SignedLogRoot{
RootHash: hasher.EmptyRoot(),
TimestampNanos: t.timeSource.Now().UnixNano(),
TreeSize: 0,
LogId: logID,
TreeRevision: 0,
})
if err != nil {
return err
}
newRoot.Signature = sig
newRoot = root

if err := tx.StoreSignedLogRoot(ctx, *newRoot); err != nil {
return status.Errorf(codes.FailedPrecondition, "StoreSignedLogRoot(): %v", err)
Expand Down
7 changes: 3 additions & 4 deletions storage/tools/dump_tree/dumplib/dumplib.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,17 +202,16 @@ func createTree(as storage.AdminStorage, ls storage.LogStorage) (*trillian.Tree,
glog.Fatalf("Creating signer: %v", err)
}

sthZero := trillian.SignedLogRoot{
sthZero, err := tSigner.SignLogRoot(&trillian.SignedLogRoot{
LogId: createdTree.TreeId,
RootHash: hasher.EmptyRoot(),
}
sthZero.Signature, err = tSigner.SignLogRoot(&sthZero)
})
if err != nil {
glog.Fatalf("SignLogRoot: %v", err)
}

err = ls.ReadWriteTransaction(ctx, createdTree, func(ctx context.Context, tx storage.LogTreeTX) error {
if err := tx.StoreSignedLogRoot(ctx, sthZero); err != nil {
if err := tx.StoreSignedLogRoot(ctx, *sthZero); err != nil {
glog.Fatalf("StoreSignedLogRoot: %v", err)
}
return nil
Expand Down

0 comments on commit 0e6d950

Please sign in to comment.