Skip to content

Commit

Permalink
[FAB-830] - Helper functions to sign KVS data
Browse files Browse the repository at this point in the history
This change set introduces helper functions (and respective tests) to sign
messages at the chaincode level using the previously checked-in encshim
extension.

Change-Id: Ib41ea63c200ca16b705f92d6b61760141249decf
Signed-off-by: Alessandro Sorniotti <ale.linux@sopit.net>
  • Loading branch information
ale-linux committed Aug 28, 2017
1 parent d0a1064 commit 07f1c8e
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 0 deletions.
76 changes: 76 additions & 0 deletions core/chaincode/shim/ext/entities/message.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package entities

import (
"encoding/json"
"fmt"
)

// SignedMessage is a simple struct that contains space
// for a payload and a signature over it, and convenience
// functions to sign, verify, marshal and unmarshal
type SignedMessage struct {
// ID contains a description of the entity signing this message
ID []byte `json:"id"`

// Payload contains the message that is signed
Payload []byte `json:"payload"`

// Sig contains a signature over ID and Payload
Sig []byte `json:"sig"`
}

// Sign signs the SignedMessage and stores the signature in the Sig field
func (m *SignedMessage) Sign(signer Signer) error {
if signer == nil {
return fmt.Errorf("nil signer")
}

m.Sig = nil
bytes, err := json.Marshal(m)
if err != nil {
return fmt.Errorf("sign error: json.Marshal returned %s", err)
}
sig, err := signer.Sign(bytes)
if err != nil {
return fmt.Errorf("sign error: signer.Sign returned %s", err)
}
m.Sig = sig

return nil
}

// Verify verifies the signature over Payload stored in Sig
func (m *SignedMessage) Verify(verifier Signer) (bool, error) {
if verifier == nil {
return false, fmt.Errorf("nil verifier")
}

sig := m.Sig
m.Sig = nil
defer func() {
m.Sig = sig
}()

bytes, err := json.Marshal(m)
if err != nil {
return false, fmt.Errorf("sign error: json.Marshal returned %s", err)
}

return verifier.Verify(sig, bytes)
}

// ToBytes serializes the intance to bytes
func (m *SignedMessage) ToBytes() ([]byte, error) {
return json.Marshal(m)
}

// FromBytes populates the instance from the supplied byte array
func (m *SignedMessage) FromBytes(d []byte) error {
return json.Unmarshal(d, m)
}
49 changes: 49 additions & 0 deletions core/chaincode/shim/ext/entities/message_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package entities

import (
"reflect"
"testing"

"github.com/stretchr/testify/assert"
)

func TestSignedMessage(t *testing.T) {
ent, err := GetEncrypterSignerEntityForTest("TEST")
assert.NoError(t, err)
assert.NotNil(t, ent)

m := &SignedMessage{Payload: []byte("message"), ID: []byte(ent.ID())}

err = m.Sign(ent)
assert.NoError(t, err)
v, err := m.Verify(ent)
assert.NoError(t, err)
assert.True(t, v)
}

func TestSignedMessageErr(t *testing.T) {
ent, err := GetEncrypterSignerEntityForTest("TEST")
assert.NoError(t, err)
assert.NotNil(t, ent)

m := &SignedMessage{Payload: []byte("message"), ID: []byte(ent.ID())}

err = m.Sign(nil)
assert.Error(t, err)
_, err = m.Verify(nil)
assert.Error(t, err)

m = &SignedMessage{Payload: []byte("message"), Sig: []byte("barf")}
_, err = m.Verify(nil)
assert.Error(t, err)
}

func TestSignedMessageMarshaller(t *testing.T) {
m1 := &SignedMessage{Payload: []byte("message"), Sig: []byte("sig"), ID: []byte("ID")}
m2 := &SignedMessage{}
b, err := m1.ToBytes()
assert.NoError(t, err)
err = m2.FromBytes(b)
assert.NoError(t, err)
assert.True(t, reflect.DeepEqual(m1, m2))
}

0 comments on commit 07f1c8e

Please sign in to comment.