github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-config/configtx/signer_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package configtx
     8  
     9  import (
    10  	"crypto"
    11  	"crypto/elliptic"
    12  	"crypto/rand"
    13  	"crypto/rsa"
    14  	"encoding/asn1"
    15  	"github.com/hellobchain/newcryptosm"
    16  	"github.com/hellobchain/newcryptosm/ecdsa"
    17  	"github.com/hellobchain/newcryptosm/x509"
    18  	"github.com/hellobchain/newcryptosm/x509/pkix"
    19  	"io"
    20  	"math/big"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/golang/protobuf/proto"
    25  	cb "github.com/hyperledger/fabric-protos-go/common"
    26  	. "github.com/onsi/gomega"
    27  )
    28  
    29  func TestSign(t *testing.T) {
    30  	t.Parallel()
    31  
    32  	cert, privateKey := generateCACertAndPrivateKey(t, "org1.example.com")
    33  
    34  	tests := []struct {
    35  		spec        string
    36  		privateKey  crypto.PrivateKey
    37  		reader      io.Reader
    38  		msg         []byte
    39  		expectedErr string
    40  	}{
    41  		{
    42  			spec:        "success",
    43  			privateKey:  privateKey,
    44  			reader:      rand.Reader,
    45  			msg:         []byte("banana"),
    46  			expectedErr: "",
    47  		},
    48  		{
    49  			spec:        "unsupported rsa private key",
    50  			privateKey:  &rsa.PrivateKey{},
    51  			reader:      rand.Reader,
    52  			msg:         []byte("banana"),
    53  			expectedErr: "signing with private key of type *rsa.PrivateKey not supported",
    54  		},
    55  	}
    56  
    57  	for _, tc := range tests {
    58  		tc := tc
    59  		t.Run(tc.spec, func(t *testing.T) {
    60  			t.Parallel()
    61  			gt := NewGomegaWithT(t)
    62  
    63  			signingIdentity := &SigningIdentity{
    64  				Certificate: cert,
    65  				PrivateKey:  tc.privateKey,
    66  				MSPID:       "test-msp",
    67  			}
    68  
    69  			signature, err := signingIdentity.Sign(tc.reader, tc.msg, nil)
    70  			if tc.expectedErr == "" {
    71  				gt.Expect(err).NotTo(HaveOccurred())
    72  				gt.Expect(signature).NotTo(BeNil())
    73  				sig := &ecdsaSignature{}
    74  				_, err := asn1.Unmarshal(signature, sig)
    75  				gt.Expect(err).NotTo(HaveOccurred())
    76  				hash := newcryptosm.SHA256.New()
    77  				if ecdsa.IsSM2(cert.PublicKey.(*ecdsa.PublicKey).Params()) {
    78  					hash = newcryptosm.SM3.New()
    79  				}
    80  				hash.Write(tc.msg)
    81  				digest := hash.Sum(nil)
    82  				valid := ecdsa.Verify(cert.PublicKey.(*ecdsa.PublicKey), digest, sig.R, sig.S)
    83  				gt.Expect(valid).To(BeTrue())
    84  			} else {
    85  				gt.Expect(err).To(MatchError(tc.expectedErr))
    86  				gt.Expect(signature).To(BeNil())
    87  			}
    88  		})
    89  	}
    90  }
    91  
    92  func TestPublic(t *testing.T) {
    93  	gt := NewGomegaWithT(t)
    94  
    95  	cert, privateKey := generateCACertAndPrivateKey(t, "org1.example.com")
    96  	signingIdentity := &SigningIdentity{
    97  		Certificate: cert,
    98  		PrivateKey:  privateKey,
    99  	}
   100  	gt.Expect(signingIdentity.Public()).To(Equal(cert.PublicKey))
   101  }
   102  
   103  func TestCreateSignature(t *testing.T) {
   104  	t.Parallel()
   105  
   106  	gt := NewGomegaWithT(t)
   107  
   108  	cert, privateKey := generateCACertAndPrivateKey(t, "org1.example.com")
   109  	signingIdentity := SigningIdentity{
   110  		Certificate: cert,
   111  		PrivateKey:  privateKey,
   112  		MSPID:       "test-msp",
   113  	}
   114  
   115  	configSignature, err := signingIdentity.CreateConfigSignature([]byte("config"))
   116  	gt.Expect(err).NotTo(HaveOccurred())
   117  
   118  	sh, err := signingIdentity.signatureHeader()
   119  	gt.Expect(err).NotTo(HaveOccurred())
   120  	expectedCreator := sh.Creator
   121  	signatureHeader := &cb.SignatureHeader{}
   122  	err = proto.Unmarshal(configSignature.SignatureHeader, signatureHeader)
   123  	gt.Expect(err).NotTo(HaveOccurred())
   124  	gt.Expect(signatureHeader.Creator).To(Equal(expectedCreator))
   125  }
   126  
   127  func TestSignEnvelope(t *testing.T) {
   128  	t.Parallel()
   129  	gt := NewGomegaWithT(t)
   130  
   131  	// create signingIdentity
   132  	cert, privateKey := generateCACertAndPrivateKey(t, "org1.example.com")
   133  	signingIdentity := SigningIdentity{
   134  		Certificate: cert,
   135  		PrivateKey:  privateKey,
   136  		MSPID:       "test-msp",
   137  	}
   138  
   139  	// create detached config signature
   140  	configUpdate := &cb.ConfigUpdate{
   141  		ChannelId: "testchannel",
   142  	}
   143  	marshaledUpdate, err := proto.Marshal(configUpdate)
   144  	gt.Expect(err).NotTo(HaveOccurred())
   145  	configSignature, err := signingIdentity.CreateConfigSignature(marshaledUpdate)
   146  	gt.Expect(err).NotTo(HaveOccurred())
   147  
   148  	// create signed config envelope
   149  	env, err := NewEnvelope(marshaledUpdate, configSignature)
   150  	gt.Expect(err).NotTo(HaveOccurred())
   151  	err = signingIdentity.SignEnvelope(env)
   152  	gt.Expect(err).NotTo(HaveOccurred())
   153  
   154  	payload := &cb.Payload{}
   155  	err = proto.Unmarshal(env.Payload, payload)
   156  	gt.Expect(err).NotTo(HaveOccurred())
   157  	// check header channel ID equal
   158  	channelHeader := &cb.ChannelHeader{}
   159  	err = proto.Unmarshal(payload.GetHeader().GetChannelHeader(), channelHeader)
   160  	gt.Expect(err).NotTo(HaveOccurred())
   161  	gt.Expect(channelHeader.ChannelId).To(Equal(configUpdate.ChannelId))
   162  	// check config update envelope signatures are equal
   163  	configEnv := &cb.ConfigUpdateEnvelope{}
   164  	err = proto.Unmarshal(payload.Data, configEnv)
   165  	gt.Expect(err).NotTo(HaveOccurred())
   166  	gt.Expect(len(configEnv.Signatures)).To(Equal(1))
   167  	expectedSignatures := configEnv.Signatures[0]
   168  	gt.Expect(expectedSignatures.SignatureHeader).To(Equal(configSignature.SignatureHeader))
   169  	gt.Expect(expectedSignatures.Signature).To(Equal(configSignature.Signature))
   170  }
   171  
   172  func TestSignEnvelopeWithAnchorPeers(t *testing.T) {
   173  	t.Parallel()
   174  	gt := NewGomegaWithT(t)
   175  
   176  	baseApplicationConf, _ := baseApplication(t)
   177  
   178  	applicationGroup, err := newApplicationGroup(baseApplicationConf)
   179  	gt.Expect(err).NotTo(HaveOccurred())
   180  
   181  	config := &cb.Config{
   182  		ChannelGroup: &cb.ConfigGroup{
   183  			Groups: map[string]*cb.ConfigGroup{
   184  				ApplicationGroupKey: applicationGroup,
   185  			},
   186  			Values:   map[string]*cb.ConfigValue{},
   187  			Policies: map[string]*cb.ConfigPolicy{},
   188  		},
   189  	}
   190  
   191  	c := New(config)
   192  
   193  	newOrg1AnchorPeer := Address{
   194  		Host: "host3",
   195  		Port: 123,
   196  	}
   197  
   198  	newOrg2AnchorPeer := Address{
   199  		Host: "host4",
   200  		Port: 123,
   201  	}
   202  
   203  	err = c.Application().Organization("Org1").AddAnchorPeer(newOrg1AnchorPeer)
   204  	gt.Expect(err).NotTo(HaveOccurred())
   205  
   206  	err = c.Application().Organization("Org2").AddAnchorPeer(newOrg2AnchorPeer)
   207  	gt.Expect(err).NotTo(HaveOccurred())
   208  
   209  	// create signingIdentity
   210  	cert, privateKey := generateCACertAndPrivateKey(t, "org1.example.com")
   211  	signingIdentity := SigningIdentity{
   212  		Certificate: cert,
   213  		PrivateKey:  privateKey,
   214  		MSPID:       "test-msp",
   215  	}
   216  
   217  	configUpdate, err := c.ComputeMarshaledUpdate("fake-channel")
   218  	gt.Expect(err).NotTo(HaveOccurred())
   219  
   220  	configSignature, err := signingIdentity.CreateConfigSignature(configUpdate)
   221  	gt.Expect(err).NotTo(HaveOccurred())
   222  
   223  	// create signed config envelope
   224  	env, err := NewEnvelope(configUpdate, configSignature)
   225  	gt.Expect(err).NotTo(HaveOccurred())
   226  	err = signingIdentity.SignEnvelope(env)
   227  	gt.Expect(err).NotTo(HaveOccurred())
   228  
   229  	// check envelope signature is valid
   230  	// env.Signature
   231  	sig := &ecdsaSignature{}
   232  	_, err = asn1.Unmarshal(env.Signature, sig)
   233  	gt.Expect(err).NotTo(HaveOccurred())
   234  	hash := newcryptosm.SHA256.New()
   235  	if ecdsa.IsSM2(cert.PublicKey.(*ecdsa.PublicKey).Params()) {
   236  		hash = newcryptosm.SM3.New()
   237  	}
   238  	hash.Write(env.Payload)
   239  	digest := hash.Sum(nil)
   240  	valid := ecdsa.Verify(cert.PublicKey.(*ecdsa.PublicKey), digest, sig.R, sig.S)
   241  	gt.Expect(valid).To(BeTrue())
   242  
   243  	payload := &cb.Payload{}
   244  	err = proto.Unmarshal(env.Payload, payload)
   245  	gt.Expect(err).NotTo(HaveOccurred())
   246  
   247  	configUpdateEnvelope := &cb.ConfigUpdateEnvelope{}
   248  	err = proto.Unmarshal(payload.Data, configUpdateEnvelope)
   249  	gt.Expect(err).NotTo(HaveOccurred())
   250  	gt.Expect(configUpdateEnvelope.Signatures).To(HaveLen(1))
   251  
   252  	sig = &ecdsaSignature{}
   253  	configSig := configUpdateEnvelope.Signatures[0]
   254  	_, err = asn1.Unmarshal(configSig.Signature, sig)
   255  	gt.Expect(err).NotTo(HaveOccurred())
   256  	hash = newcryptosm.SHA256.New()
   257  	if ecdsa.IsSM2(cert.PublicKey.(*ecdsa.PublicKey).Params()) {
   258  		hash = newcryptosm.SM3.New()
   259  	}
   260  	hash.Write(concatenateBytes(configSig.SignatureHeader, configUpdateEnvelope.ConfigUpdate))
   261  	digest = hash.Sum(nil)
   262  	valid = ecdsa.Verify(cert.PublicKey.(*ecdsa.PublicKey), digest, sig.R, sig.S)
   263  	gt.Expect(valid).To(BeTrue())
   264  }
   265  
   266  func TestToLowS(t *testing.T) {
   267  	t.Parallel()
   268  
   269  	curve := elliptic.P256()
   270  	halfOrder := new(big.Int).Div(curve.Params().N, big.NewInt(2))
   271  
   272  	for _, test := range []struct {
   273  		name        string
   274  		sig         ecdsaSignature
   275  		expectedSig ecdsaSignature
   276  	}{
   277  		{
   278  			name: "HighS",
   279  			sig: ecdsaSignature{
   280  				R: big.NewInt(1),
   281  				// set S to halfOrder + 1
   282  				S: new(big.Int).Add(halfOrder, big.NewInt(1)),
   283  			},
   284  			// expected signature should be (sig.R, -sig.S mod N)
   285  			expectedSig: ecdsaSignature{
   286  				R: big.NewInt(1),
   287  				S: new(big.Int).Mod(new(big.Int).Neg(new(big.Int).Add(halfOrder, big.NewInt(1))), curve.Params().N),
   288  			},
   289  		},
   290  		{
   291  			name: "LowS",
   292  			sig: ecdsaSignature{
   293  				R: big.NewInt(1),
   294  				// set S to halfOrder - 1
   295  				S: new(big.Int).Sub(halfOrder, big.NewInt(1)),
   296  			},
   297  			// expected signature should be sig
   298  			expectedSig: ecdsaSignature{
   299  				R: big.NewInt(1),
   300  				S: new(big.Int).Sub(halfOrder, big.NewInt(1)),
   301  			},
   302  		},
   303  		{
   304  			name: "HalfOrder",
   305  			sig: ecdsaSignature{
   306  				R: big.NewInt(1),
   307  				// set S to halfOrder
   308  				S: halfOrder,
   309  			},
   310  			// expected signature should be sig
   311  			expectedSig: ecdsaSignature{
   312  				R: big.NewInt(1),
   313  				S: halfOrder,
   314  			},
   315  		},
   316  	} {
   317  		t.Run(test.name, func(t *testing.T) {
   318  			t.Parallel()
   319  
   320  			gt := NewGomegaWithT(t)
   321  			curve := elliptic.P256()
   322  			key := ecdsa.PublicKey{
   323  				Curve: curve,
   324  			}
   325  			gt.Expect(toLowS(key, test.sig), test.expectedSig)
   326  		})
   327  	}
   328  }
   329  
   330  // generateCACertAndPrivateKey returns CA cert and private key.
   331  func generateCACertAndPrivateKey(t *testing.T, orgName string) (*x509.Certificate, *ecdsa.PrivateKey) {
   332  	serialNumber := generateSerialNumber(t)
   333  	template := &x509.Certificate{
   334  		SerialNumber: serialNumber,
   335  		Subject: pkix.Name{
   336  			CommonName:   "ca." + orgName,
   337  			Organization: []string{orgName},
   338  		},
   339  		NotBefore:             time.Now(),
   340  		NotAfter:              time.Now().Add(365 * 24 * time.Hour),
   341  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
   342  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
   343  		BasicConstraintsValid: true,
   344  		IsCA:                  true,
   345  	}
   346  	return generateCertAndPrivateKey(t, template, template, nil)
   347  }
   348  
   349  func generateIntermediateCACertAndPrivateKey(t *testing.T, orgName string, rootCACert *x509.Certificate, rootPrivKey *ecdsa.PrivateKey) (*x509.Certificate, *ecdsa.PrivateKey) {
   350  	serialNumber := generateSerialNumber(t)
   351  	template := &x509.Certificate{
   352  		SerialNumber: serialNumber,
   353  		Subject: pkix.Name{
   354  			CommonName:   "intermediateca." + orgName,
   355  			Organization: []string{orgName},
   356  		},
   357  		NotBefore:             time.Now(),
   358  		NotAfter:              time.Now().Add(365 * 24 * time.Hour),
   359  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
   360  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
   361  		BasicConstraintsValid: true,
   362  		IsCA:                  true,
   363  	}
   364  	return generateCertAndPrivateKey(t, template, rootCACert, rootPrivKey)
   365  }
   366  
   367  // generateCertAndPrivateKeyFromCACert returns a cert and private key signed by the given CACert.
   368  func generateCertAndPrivateKeyFromCACert(t *testing.T, orgName string, caCert *x509.Certificate, privateKey *ecdsa.PrivateKey) (*x509.Certificate, *ecdsa.PrivateKey) {
   369  	serialNumber := generateSerialNumber(t)
   370  	template := &x509.Certificate{
   371  		SerialNumber: serialNumber,
   372  		Subject: pkix.Name{
   373  			CommonName:   "user." + orgName,
   374  			Organization: []string{orgName},
   375  		},
   376  		NotBefore:             time.Now(),
   377  		NotAfter:              time.Now().Add(365 * 24 * time.Hour),
   378  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
   379  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
   380  		BasicConstraintsValid: true,
   381  	}
   382  	return generateCertAndPrivateKey(t, template, caCert, privateKey)
   383  }
   384  
   385  func generateCertAndPrivateKey(t *testing.T, template, parent *x509.Certificate, parentPriv *ecdsa.PrivateKey) (*x509.Certificate, *ecdsa.PrivateKey) {
   386  	gt := NewGomegaWithT(t)
   387  
   388  	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   389  	gt.Expect(err).NotTo(HaveOccurred())
   390  
   391  	if parentPriv == nil {
   392  		// create self-signed cert
   393  		parentPriv = priv
   394  	}
   395  	derBytes, err := x509.CreateCertificate(rand.Reader, template, parent, &priv.PublicKey, parentPriv)
   396  	gt.Expect(err).NotTo(HaveOccurred())
   397  
   398  	cert, err := x509.ParseCertificate(derBytes)
   399  	gt.Expect(err).NotTo(HaveOccurred())
   400  
   401  	return cert, priv
   402  }
   403  
   404  // generateSerialNumber returns a random serialNumber
   405  func generateSerialNumber(t *testing.T) *big.Int {
   406  	gt := NewGomegaWithT(t)
   407  
   408  	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
   409  	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
   410  	gt.Expect(err).NotTo(HaveOccurred())
   411  
   412  	return serialNumber
   413  }
   414  
   415  // generateCert returns cert.
   416  func generateCert(t *testing.T, orgName string) *x509.Certificate {
   417  	serialNumber := generateSerialNumber(t)
   418  	template := &x509.Certificate{
   419  		SerialNumber: serialNumber,
   420  		Subject: pkix.Name{
   421  			CommonName:   orgName,
   422  			Organization: []string{orgName},
   423  		},
   424  		NotBefore:             time.Now(),
   425  		NotAfter:              time.Now().Add(365 * 24 * time.Hour),
   426  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
   427  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
   428  		BasicConstraintsValid: true,
   429  		IsCA:                  false,
   430  	}
   431  	cert, _ := generateCertAndPrivateKey(t, template, template, nil)
   432  	return cert
   433  }