Skip to content

Commit

Permalink
Extend SigningIdentity with config update signing functions (hyperled…
Browse files Browse the repository at this point in the history
…ger#1089)

FAB-17741

Signed-off-by: Will Lahti <wtlahti@us.ibm.com>
  • Loading branch information
wlahti authored Apr 15, 2020
1 parent d8da1e4 commit e507869
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 171 deletions.
4 changes: 2 additions & 2 deletions integration/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,11 @@ var _ = Describe("Config", func() {
PrivateKey: parsePeerPrivateKey(network, peer, "Admin"),
MSPID: network.Organization(peer.Organization).MSPID,
}
signature, err := config.SignConfigUpdate(configUpdate, signingIdentity)
signature, err := signingIdentity.SignConfigUpdate(configUpdate)
Expect(err).NotTo(HaveOccurred())

By("creating a signed config update envelope with the detached signature")
configUpdateEnvelope, err := config.CreateSignedConfigUpdateEnvelope(configUpdate, signingIdentity, signature)
configUpdateEnvelope, err := signingIdentity.SignConfigUpdateEnvelope(configUpdate, signature)
Expect(err).NotTo(HaveOccurred())
configUpdateBytes, err := proto.Marshal(configUpdateEnvelope)
Expect(err).NotTo(HaveOccurred())
Expand Down
162 changes: 1 addition & 161 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@ SPDX-License-Identifier: Apache-2.0
package config

import (
"bytes"
"crypto/rand"
"encoding/pem"
"errors"
"fmt"
"strconv"
"strings"
"time"

"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes"
Expand Down Expand Up @@ -210,98 +206,6 @@ func NewCreateChannelTx(channelConfig Channel, channelID string) (*cb.Envelope,
return env, nil
}

// SignConfigUpdate signs the given configuration update with a
// specified signing identity and returns a config signature.
func SignConfigUpdate(configUpdate *cb.ConfigUpdate, signingIdentity SigningIdentity) (*cb.ConfigSignature, error) {
signatureHeader, err := signatureHeader(signingIdentity)
if err != nil {
return nil, fmt.Errorf("failed to create signature header: %v", err)
}

header, err := proto.Marshal(signatureHeader)
if err != nil {
return nil, fmt.Errorf("marshaling signature header: %v", err)
}

configSignature := &cb.ConfigSignature{
SignatureHeader: header,
}

configUpdateBytes, err := proto.Marshal(configUpdate)
if err != nil {
return nil, fmt.Errorf("marshaling config update: %v", err)
}

configSignature.Signature, err = signingIdentity.Sign(
rand.Reader,
concatenateBytes(configSignature.SignatureHeader, configUpdateBytes),
nil,
)
if err != nil {
return nil, fmt.Errorf("failed to sign config update: %v", err)
}

return configSignature, nil
}

// CreateSignedConfigUpdateEnvelope creates a signed configuration update envelope.
func CreateSignedConfigUpdateEnvelope(configUpdate *cb.ConfigUpdate, signingIdentity SigningIdentity,
signatures ...*cb.ConfigSignature) (*cb.Envelope, error) {
update, err := proto.Marshal(configUpdate)
if err != nil {
return nil, fmt.Errorf("marshaling config update: %v", err)
}

configUpdateEnvelope := &cb.ConfigUpdateEnvelope{
ConfigUpdate: update,
Signatures: signatures,
}

signedEnvelope, err := createSignedEnvelopeWithTLSBinding(cb.HeaderType_CONFIG_UPDATE, configUpdate.ChannelId,
signingIdentity, configUpdateEnvelope)
if err != nil {
return nil, fmt.Errorf("failed to create signed config update envelope: %v", err)
}

return signedEnvelope, nil
}

func signatureHeader(signingIdentity SigningIdentity) (*cb.SignatureHeader, error) {
buffer := bytes.NewBuffer(nil)

err := pem.Encode(buffer, &pem.Block{Type: "CERTIFICATE", Bytes: signingIdentity.Certificate.Raw})
if err != nil {
return nil, fmt.Errorf("pem encode: %v", err)
}

idBytes, err := proto.Marshal(&mb.SerializedIdentity{Mspid: signingIdentity.MSPID, IdBytes: buffer.Bytes()})
if err != nil {
return nil, fmt.Errorf("marshaling serialized identity: %v", err)
}

nonce, err := newNonce()
if err != nil {
return nil, err
}

return &cb.SignatureHeader{
Creator: idBytes,
Nonce: nonce,
}, nil
}

// newNonce generates a 24-byte nonce using the crypto/rand package.
func newNonce() ([]byte, error) {
nonce := make([]byte, 24)

_, err := rand.Read(nonce)
if err != nil {
return nil, fmt.Errorf("failed to get random bytes: %v", err)
}

return nonce, nil
}

// newChannelGroup defines the root of the channel configuration.
func newChannelGroup(channelConfig Channel) (*cb.ConfigGroup, error) {
var err error
Expand Down Expand Up @@ -538,7 +442,7 @@ func newEnvelope(
return env, nil
}

// makeChannelHeader creates a ChannelHeader.
// channelHeader creates a ChannelHeader.
func channelHeader(headerType cb.HeaderType, version int32, channelID string, epoch uint64) *cb.ChannelHeader {
return &cb.ChannelHeader{
Type: int32(headerType),
Expand Down Expand Up @@ -580,70 +484,6 @@ func concatenateBytes(data ...[]byte) []byte {
return res
}

// createSignedEnvelopeWithTLSBinding creates a signed envelope of the desired
// type, with marshaled dataMsg and signs it. It also includes a TLS cert hash
// into the channel header
func createSignedEnvelopeWithTLSBinding(
txType cb.HeaderType,
channelID string,
signingIdentity SigningIdentity,
envelope proto.Message,
) (*cb.Envelope, error) {
channelHeader := &cb.ChannelHeader{
Type: int32(txType),
Timestamp: &timestamp.Timestamp{
Seconds: time.Now().Unix(),
Nanos: 0,
},
ChannelId: channelID,
}

signatureHeader, err := signatureHeader(signingIdentity)
if err != nil {
return nil, fmt.Errorf("creating signature header: %v", err)
}

cHeader, err := proto.Marshal(channelHeader)
if err != nil {
return nil, fmt.Errorf("marshaling channel header: %s", err)
}

sHeader, err := proto.Marshal(signatureHeader)
if err != nil {
return nil, fmt.Errorf("marshaling signature header: %s", err)
}

data, err := proto.Marshal(envelope)
if err != nil {
return nil, fmt.Errorf("marshaling config update envelope: %s", err)
}

payload := &cb.Payload{
Header: &cb.Header{
ChannelHeader: cHeader,
SignatureHeader: sHeader,
},
Data: data,
}

payloadBytes, err := proto.Marshal(payload)
if err != nil {
return nil, fmt.Errorf("marshaling payload: %s", err)
}

sig, err := signingIdentity.Sign(rand.Reader, payloadBytes, nil)
if err != nil {
return nil, fmt.Errorf("signing envelope's payload: %v", err)
}

env := &cb.Envelope{
Payload: payloadBytes,
Signature: sig,
}

return env, nil
}

// unmarshalConfigValueAtKey unmarshals the value for the specified key in a config group
// into the designated proto message.
func unmarshalConfigValueAtKey(group *cb.ConfigGroup, key string, msg proto.Message) error {
Expand Down
12 changes: 6 additions & 6 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ func TestSignConfigUpdate(t *testing.T) {
MSPID: "test-msp",
}

configSignature, err := SignConfigUpdate(&cb.ConfigUpdate{}, signingIdentity)
configSignature, err := signingIdentity.SignConfigUpdate(&cb.ConfigUpdate{})
gt.Expect(err).NotTo(HaveOccurred())

sh, err := signatureHeader(signingIdentity)
sh, err := signingIdentity.signatureHeader()
gt.Expect(err).NotTo(HaveOccurred())
expectedCreator := sh.Creator
signatureHeader := &cb.SignatureHeader{}
Expand Down Expand Up @@ -425,11 +425,11 @@ func TestCreateSignedConfigUpdateEnvelope(t *testing.T) {
configUpdate := &cb.ConfigUpdate{
ChannelId: "testchannel",
}
configSignature, err := SignConfigUpdate(configUpdate, signingIdentity)
configSignature, err := signingIdentity.SignConfigUpdate(configUpdate)
gt.Expect(err).NotTo(HaveOccurred())

// create signed config envelope
signedEnv, err := CreateSignedConfigUpdateEnvelope(configUpdate, signingIdentity, configSignature)
signedEnv, err := signingIdentity.SignConfigUpdateEnvelope(configUpdate, configSignature)
gt.Expect(err).NotTo(HaveOccurred())

payload := &cb.Payload{}
Expand Down Expand Up @@ -466,7 +466,7 @@ func TestCreateSignedConfigUpdateEnvelopeFailures(t *testing.T) {
configUpdate := &cb.ConfigUpdate{
ChannelId: "testchannel",
}
configSignature, err := SignConfigUpdate(configUpdate, signingIdentity)
configSignature, err := signingIdentity.SignConfigUpdate(configUpdate)

gt.Expect(err).NotTo(HaveOccurred())

Expand All @@ -493,7 +493,7 @@ func TestCreateSignedConfigUpdateEnvelopeFailures(t *testing.T) {
gt := NewGomegaWithT(t)

// create signed config envelope
signedEnv, err := CreateSignedConfigUpdateEnvelope(tc.configUpdate, tc.signingIdentity, tc.configSignature...)
signedEnv, err := tc.signingIdentity.SignConfigUpdateEnvelope(tc.configUpdate, tc.configSignature...)
gt.Expect(err).To(MatchError(tc.expectedErr))
gt.Expect(signedEnv).To(BeNil())
})
Expand Down
4 changes: 2 additions & 2 deletions pkg/config/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func Example_systemChannel() {

for _, si := range signingIdentities {
// Sign the config update with the specified signer identity
configSignature, err := config.SignConfigUpdate(configUpdate, si)
configSignature, err := si.SignConfigUpdate(configUpdate)
if err != nil {
panic(err)
}
Expand All @@ -159,7 +159,7 @@ func Example_systemChannel() {
}

// Sign the envelope with the list of signatures
envelope, err := config.CreateSignedConfigUpdateEnvelope(configUpdate, peer1SigningIdentity, configSignatures...)
envelope, err := peer1SigningIdentity.SignConfigUpdateEnvelope(configUpdate, configSignatures...)
if err != nil {
panic(err)
}
Expand Down
Loading

0 comments on commit e507869

Please sign in to comment.