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 }