Skip to content

Commit b167513

Browse files
authored
Move DigitallySigned to its own proto package. (#379)
* Move DigitallySigned to its own proto package. This allows external libraries to depend on it and enforces better decoupling in the code base. * reviewer comments * mv proto/signature to crypto/sigpb * rename hashAlgo to hash
1 parent 242ba24 commit b167513

28 files changed

+476
-355
lines changed

crypto/hashers.go

Lines changed: 0 additions & 40 deletions
This file was deleted.

crypto/key_manager.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525
"io/ioutil"
2626

2727
"github.com/golang/glog"
28-
"github.com/google/trillian"
28+
"github.com/google/trillian/crypto/sigpb"
2929
)
3030

3131
// KeyManager loads and holds our private and public keys. Should support ECDSA and RSA keys.
@@ -38,9 +38,9 @@ type KeyManager interface {
3838
// manager.
3939
Signer() (crypto.Signer, error)
4040
// SignatureAlgorithm returns the value that identifies the signature algorithm.
41-
SignatureAlgorithm() trillian.SignatureAlgorithm
41+
SignatureAlgorithm() sigpb.DigitallySigned_SignatureAlgorithm
4242
// HashAlgorithm returns the type of hash that will be used for signing with this key.
43-
HashAlgorithm() trillian.HashAlgorithm
43+
HashAlgorithm() crypto.Hash
4444
// GetPublicKey returns the public key previously loaded. It is an error to call this
4545
// before a public key has been loaded
4646
GetPublicKey() (crypto.PublicKey, error)
@@ -54,7 +54,7 @@ type KeyManager interface {
5454
// PEM file.
5555
type PEMKeyManager struct {
5656
serverPrivateKey crypto.PrivateKey
57-
signatureAlgorithm trillian.SignatureAlgorithm
57+
signatureAlgorithm sigpb.DigitallySigned_SignatureAlgorithm
5858
serverPublicKey crypto.PublicKey
5959
rawPublicKey []byte
6060
}
@@ -71,15 +71,15 @@ func (k PEMKeyManager) NewPEMKeyManager(key crypto.PrivateKey) *PEMKeyManager {
7171
}
7272

7373
// SignatureAlgorithm identifies the signature algorithm used by this key manager.
74-
func (k PEMKeyManager) SignatureAlgorithm() trillian.SignatureAlgorithm {
74+
func (k PEMKeyManager) SignatureAlgorithm() sigpb.DigitallySigned_SignatureAlgorithm {
7575
return k.signatureAlgorithm
7676
}
7777

7878
// HashAlgorithm identifies the hash algorithm used to sign objects.
79-
func (k PEMKeyManager) HashAlgorithm() trillian.HashAlgorithm {
79+
func (k PEMKeyManager) HashAlgorithm() crypto.Hash {
8080
// TODO: Save the hash algorithm in the key serialization.
8181
// Return a default hash algorithm for now.
82-
return trillian.HashAlgorithm_SHA256
82+
return crypto.SHA256
8383
}
8484

8585
// LoadPrivateKey loads a private key from a PEM encoded string, decrypting it if necessary
@@ -172,29 +172,29 @@ func (k PEMKeyManager) GetRawPublicKey() ([]byte, error) {
172172
return k.rawPublicKey, nil
173173
}
174174

175-
func parsePrivateKey(key []byte) (crypto.PrivateKey, trillian.SignatureAlgorithm, error) {
175+
func parsePrivateKey(key []byte) (crypto.PrivateKey, sigpb.DigitallySigned_SignatureAlgorithm, error) {
176176
// Our two ways of reading keys are ParsePKCS1PrivateKey and ParsePKCS8PrivateKey.
177177
// And ParseECPrivateKey. Our three ways of parsing keys are ... I'll come in again.
178178
if key, err := x509.ParsePKCS1PrivateKey(key); err == nil {
179-
return key, trillian.SignatureAlgorithm_RSA, nil
179+
return key, sigpb.DigitallySigned_RSA, nil
180180
}
181181
if key, err := x509.ParsePKCS8PrivateKey(key); err == nil {
182182
switch key := key.(type) {
183183
case *ecdsa.PrivateKey:
184-
return key, trillian.SignatureAlgorithm_ECDSA, nil
184+
return key, sigpb.DigitallySigned_ECDSA, nil
185185
case *rsa.PrivateKey:
186-
return key, trillian.SignatureAlgorithm_RSA, nil
186+
return key, sigpb.DigitallySigned_RSA, nil
187187
default:
188-
return nil, trillian.SignatureAlgorithm_ANONYMOUS, fmt.Errorf("unknown private key type: %T", key)
188+
return nil, sigpb.DigitallySigned_ANONYMOUS, fmt.Errorf("unknown private key type: %T", key)
189189
}
190190
}
191191
var err error
192192
if key, err := x509.ParseECPrivateKey(key); err == nil {
193-
return key, trillian.SignatureAlgorithm_ECDSA, nil
193+
return key, sigpb.DigitallySigned_ECDSA, nil
194194
}
195195

196196
glog.Warningf("error parsing EC key: %s", err)
197-
return nil, trillian.SignatureAlgorithm_ANONYMOUS, errors.New("could not parse private key")
197+
return nil, sigpb.DigitallySigned_ANONYMOUS, errors.New("could not parse private key")
198198
}
199199

200200
// LoadPasswordProtectedPrivateKey initializes and returns a new KeyManager using a PEM encoded

crypto/mock_key_manager.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ package crypto
66
import (
77
crypto "crypto"
88
gomock "github.com/golang/mock/gomock"
9-
trillian "github.com/google/trillian"
9+
sigpb "github.com/google/trillian/crypto/sigpb"
1010
)
1111

1212
// Mock of KeyManager interface
@@ -52,19 +52,19 @@ func (_mr *_MockKeyManagerRecorder) GetRawPublicKey() *gomock.Call {
5252
return _mr.mock.ctrl.RecordCall(_mr.mock, "GetRawPublicKey")
5353
}
5454

55-
func (_m *MockKeyManager) HashAlgorithm() trillian.HashAlgorithm {
55+
func (_m *MockKeyManager) HashAlgorithm() crypto.Hash {
5656
ret := _m.ctrl.Call(_m, "HashAlgorithm")
57-
ret0, _ := ret[0].(trillian.HashAlgorithm)
57+
ret0, _ := ret[0].(crypto.Hash)
5858
return ret0
5959
}
6060

6161
func (_mr *_MockKeyManagerRecorder) HashAlgorithm() *gomock.Call {
6262
return _mr.mock.ctrl.RecordCall(_mr.mock, "HashAlgorithm")
6363
}
6464

65-
func (_m *MockKeyManager) SignatureAlgorithm() trillian.SignatureAlgorithm {
65+
func (_m *MockKeyManager) SignatureAlgorithm() sigpb.DigitallySigned_SignatureAlgorithm {
6666
ret := _m.ctrl.Call(_m, "SignatureAlgorithm")
67-
ret0, _ := ret[0].(trillian.SignatureAlgorithm)
67+
ret0, _ := ret[0].(sigpb.DigitallySigned_SignatureAlgorithm)
6868
return ret0
6969
}
7070

crypto/signer.go

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/benlaurie/objecthash/go/objecthash"
2525
"github.com/golang/glog"
2626
"github.com/google/trillian"
27+
"github.com/google/trillian/crypto/sigpb"
2728
)
2829

2930
// Constants used as map keys when building input for ObjectHash. They must not be changed
@@ -34,48 +35,62 @@ const (
3435
mapKeyTreeSize string = "TreeSize"
3536
)
3637

38+
var (
39+
signerHashLookup = map[sigpb.DigitallySigned_HashAlgorithm]crypto.Hash{
40+
sigpb.DigitallySigned_SHA256: crypto.SHA256,
41+
}
42+
reverseSignerHashLookup = map[crypto.Hash]sigpb.DigitallySigned_HashAlgorithm{
43+
crypto.SHA256: sigpb.DigitallySigned_SHA256,
44+
}
45+
)
46+
3747
// Signer is responsible for signing log-related data and producing the appropriate
3848
// application specific signature objects.
3949
type Signer struct {
40-
hasher crypto.Hash
50+
hash crypto.Hash
4151
signer crypto.Signer
42-
sigAlgorithm trillian.SignatureAlgorithm
52+
sigAlgorithm sigpb.DigitallySigned_SignatureAlgorithm
4353
}
4454

4555
// NewSigner creates a new Signer wrapping up a hasher and a signer. For the moment
4656
// we only support SHA256 hashing and either ECDSA or RSA signing but this is not enforced
4757
// here.
48-
func NewSigner(hashAlgo trillian.HashAlgorithm, sigAlgo trillian.SignatureAlgorithm, signer crypto.Signer) *Signer {
49-
h, ok := hashLookup[hashAlgo]
58+
func NewSigner(hash crypto.Hash, sigAlgo sigpb.DigitallySigned_SignatureAlgorithm, signer crypto.Signer) *Signer {
59+
_, ok := reverseSignerHashLookup[hash]
5060
if !ok {
5161
// TODO(gbelvin): return error from Signer.
5262
panic("unsupported hash algorithm")
5363
}
5464

55-
return &Signer{h, signer, sigAlgo}
65+
return &Signer{
66+
hash: hash,
67+
signer: signer,
68+
sigAlgorithm: sigAlgo,
69+
}
5670
}
5771

5872
// Sign obtains a signature after first hashing the input data.
59-
func (s Signer) Sign(data []byte) (trillian.DigitallySigned, error) {
60-
h := s.hasher.New()
73+
func (s Signer) Sign(data []byte) (sigpb.DigitallySigned, error) {
74+
h := s.hash.New()
6175
h.Write(data)
6276
digest := h.Sum(nil)
6377

64-
if len(digest) != s.hasher.Size() {
65-
return trillian.DigitallySigned{}, fmt.Errorf("hasher returned unexpected digest length: %d, %d",
66-
len(digest), s.hasher.Size())
78+
if len(digest) != s.hash.Size() {
79+
return sigpb.DigitallySigned{}, fmt.Errorf("hasher returned unexpected digest length: %d, %d",
80+
len(digest), s.hash.Size())
6781
}
6882

69-
sig, err := s.signer.Sign(rand.Reader, digest, s.hasher)
83+
sig, err := s.signer.Sign(rand.Reader, digest, s.hash)
7084

7185
if err != nil {
72-
return trillian.DigitallySigned{}, err
86+
return sigpb.DigitallySigned{}, err
7387
}
7488

75-
return trillian.DigitallySigned{
89+
return sigpb.DigitallySigned{
7690
SignatureAlgorithm: s.sigAlgorithm,
77-
HashAlgorithm: reverseHashLookup[s.hasher],
78-
Signature: sig}, nil
91+
HashAlgorithm: reverseSignerHashLookup[s.hash],
92+
Signature: sig,
93+
}, nil
7994
}
8095

8196
func (s Signer) hashRoot(root trillian.SignedLogRoot) []byte {
@@ -95,13 +110,13 @@ func (s Signer) hashRoot(root trillian.SignedLogRoot) []byte {
95110

96111
// SignLogRoot updates a log root to include a signature from the crypto signer this object
97112
// was created with. Signatures use objecthash on a fixed JSON format of the root.
98-
func (s Signer) SignLogRoot(root trillian.SignedLogRoot) (trillian.DigitallySigned, error) {
113+
func (s Signer) SignLogRoot(root trillian.SignedLogRoot) (sigpb.DigitallySigned, error) {
99114
objectHash := s.hashRoot(root)
100115
signature, err := s.Sign(objectHash[:])
101116

102117
if err != nil {
103118
glog.Warningf("Signer failed to sign root: %v", err)
104-
return trillian.DigitallySigned{}, err
119+
return sigpb.DigitallySigned{}, err
105120
}
106121

107122
return signature, nil

crypto/signer_test.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"github.com/golang/mock/gomock"
2626
"github.com/google/trillian"
27+
"github.com/google/trillian/crypto/sigpb"
2728
"github.com/google/trillian/testonly"
2829
)
2930

@@ -67,10 +68,10 @@ func TestSigner(t *testing.T) {
6768
t.Fatalf("Failed to sign: %s", err)
6869
}
6970

70-
if got, want := sig.HashAlgorithm, trillian.HashAlgorithm_SHA256; got != want {
71+
if got, want := sig.HashAlgorithm, sigpb.DigitallySigned_SHA256; got != want {
7172
t.Fatalf("Hash alg incorrect, got %v expected %d", got, want)
7273
}
73-
if got, want := sig.SignatureAlgorithm, trillian.SignatureAlgorithm_RSA; got != want {
74+
if got, want := sig.SignatureAlgorithm, sigpb.DigitallySigned_RSA; got != want {
7475
t.Fatalf("Sig alg incorrect, got %v expected %v", got, want)
7576
}
7677
if got, want := []byte(result), sig.Signature; !bytes.Equal(got, want) {
@@ -141,14 +142,15 @@ func TestSignLogRoot(t *testing.T) {
141142
t.Fatalf("Got %v, but expected unmodified signed root %v", root, expected)
142143
}
143144
// And signature is correct
144-
expectedSignature := trillian.DigitallySigned{SignatureAlgorithm: trillian.SignatureAlgorithm_RSA,
145-
HashAlgorithm: trillian.HashAlgorithm_SHA256,
146-
Signature: []byte("echo")}
145+
expectedSignature := sigpb.DigitallySigned{
146+
SignatureAlgorithm: sigpb.DigitallySigned_RSA,
147+
HashAlgorithm: sigpb.DigitallySigned_SHA256,
148+
Signature: []byte("echo")}
147149
if !reflect.DeepEqual(signature, expectedSignature) {
148150
t.Fatalf("Got %v, but expected %v", signature, expectedSignature)
149151
}
150152
}
151153

152154
func createTestSigner(mock *MockSigner) *Signer {
153-
return NewSigner(trillian.HashAlgorithm_SHA256, trillian.SignatureAlgorithm_RSA, mock)
155+
return NewSigner(crypto.SHA256, sigpb.DigitallySigned_RSA, mock)
154156
}

crypto/sigpb/gen.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2016 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package sigpb
16+
17+
//go:generate protoc -I=. --go_out=:. sigpb.proto

0 commit comments

Comments
 (0)