diff --git a/service/sign.go b/service/sign.go index f3714833..654c4a9c 100644 --- a/service/sign.go +++ b/service/sign.go @@ -56,3 +56,17 @@ func DataSignature(src SignedDataSource, key *ecdsa.PrivateKey) ([]byte, error) return crypto.Sign(key, data) } + +// AddSignatureWithKey calculates the data signature and adds it to accumulator with public key. +// +// Returns signing errors only. +func AddSignatureWithKey(v SignatureKeyAccumulator, key *ecdsa.PrivateKey) error { + sign, err := DataSignature(v, key) + if err != nil { + return err + } + + v.AddSignKey(sign, &key.PublicKey) + + return nil +} diff --git a/service/sign_test.go b/service/sign_test.go index be5f4b7f..5ac7c6c4 100644 --- a/service/sign_test.go +++ b/service/sign_test.go @@ -1,6 +1,7 @@ package service import ( + "crypto/ecdsa" "crypto/rand" "errors" "io" @@ -23,6 +24,21 @@ type testSignedDataReader struct { d []byte } +type testKeySigAccum struct { + d []byte + f func([]byte, *ecdsa.PublicKey) +} + +func (s testKeySigAccum) SignedData() ([]byte, error) { + return s.d, nil +} + +func (s testKeySigAccum) AddSignKey(sig []byte, key *ecdsa.PublicKey) { + if s.f != nil { + s.f(sig, key) + } +} + func testData(t *testing.T, sz int) []byte { d := make([]byte, sz) _, err := rand.Read(d) @@ -110,3 +126,22 @@ func TestDataSignature(t *testing.T) { require.NoError(t, crypto.Verify(&sk.PublicKey, src.d, sig)) }) } + +func TestAddSignatureWithKey(t *testing.T) { + // create test data + data := testData(t, 10) + + // create test private key + sk := test.DecodeKey(0) + + // create test signature accumulator + var s SignatureKeyAccumulator = &testKeySigAccum{ + d: data, + f: func(sig []byte, key *ecdsa.PublicKey) { + require.Equal(t, &sk.PublicKey, key) + require.NoError(t, crypto.Verify(key, data, sig)) + }, + } + + require.NoError(t, AddSignatureWithKey(s, sk)) +} diff --git a/service/types.go b/service/types.go index 06ea4e27..80a4a493 100644 --- a/service/types.go +++ b/service/types.go @@ -1,5 +1,9 @@ package service +import ( + "crypto/ecdsa" +) + // NodeRole to identify in Bootstrap service. type NodeRole int32 @@ -187,3 +191,9 @@ type SignedDataReader interface { // Must behave like Read method of io.Reader and differ only in the reading of the signed data. ReadSignedData([]byte) (int, error) } + +// SignatureKeyAccumulator is an interface of the accumulator of data signatures with keys. +type SignatureKeyAccumulator interface { + SignedDataSource + AddSignKey([]byte, *ecdsa.PublicKey) +}