github.com/lzy4123/fabric@v2.1.1+incompatible/bccsp/idemix/handlers/revocation_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  package handlers_test
     7  
     8  import (
     9  	"crypto/ecdsa"
    10  	"crypto/elliptic"
    11  	"crypto/rand"
    12  	"crypto/sha256"
    13  	"crypto/x509"
    14  	"encoding/pem"
    15  	"math/big"
    16  
    17  	"github.com/hyperledger/fabric/bccsp/idemix/handlers"
    18  
    19  	"github.com/hyperledger/fabric/bccsp"
    20  	"github.com/hyperledger/fabric/bccsp/idemix/handlers/mock"
    21  	. "github.com/onsi/ginkgo"
    22  	. "github.com/onsi/gomega"
    23  	"github.com/pkg/errors"
    24  )
    25  
    26  var _ = Describe("Revocation", func() {
    27  
    28  	Describe("when creating a revocation key-pair", func() {
    29  		var (
    30  			RevocationKeyGen *handlers.RevocationKeyGen
    31  
    32  			fakeRevocation          *mock.Revocation
    33  			fakeRevocationSecretKey bccsp.Key
    34  		)
    35  
    36  		BeforeEach(func() {
    37  			fakeRevocation = &mock.Revocation{}
    38  
    39  			RevocationKeyGen = &handlers.RevocationKeyGen{}
    40  			RevocationKeyGen.Revocation = fakeRevocation
    41  		})
    42  
    43  		Context("and the underlying cryptographic algorithm succeed", func() {
    44  			var (
    45  				sk                  bccsp.Key
    46  				idemixRevocationKey *ecdsa.PrivateKey
    47  				SKI                 []byte
    48  				pkBytes             []byte
    49  			)
    50  			BeforeEach(func() {
    51  				idemixRevocationKey = &ecdsa.PrivateKey{
    52  					PublicKey: ecdsa.PublicKey{
    53  						Curve: elliptic.P256(),
    54  						X:     big.NewInt(1), Y: big.NewInt(1)},
    55  					D: big.NewInt(1)}
    56  
    57  				raw := elliptic.Marshal(idemixRevocationKey.Curve, idemixRevocationKey.PublicKey.X, idemixRevocationKey.PublicKey.Y)
    58  				hash := sha256.New()
    59  				hash.Write(raw)
    60  				SKI = hash.Sum(nil)
    61  
    62  				var err error
    63  				pkBytes, err = x509.MarshalPKIXPublicKey(&idemixRevocationKey.PublicKey)
    64  				Expect(err).NotTo(HaveOccurred())
    65  
    66  				fakeRevocation.NewKeyReturns(idemixRevocationKey, nil)
    67  
    68  				fakeRevocationSecretKey = handlers.NewRevocationSecretKey(idemixRevocationKey, false)
    69  			})
    70  
    71  			AfterEach(func() {
    72  				Expect(sk.Private()).To(BeTrue())
    73  				Expect(sk.Symmetric()).To(BeFalse())
    74  				Expect(sk.SKI()).NotTo(BeNil())
    75  				Expect(sk.SKI()).To(BeEquivalentTo(SKI))
    76  
    77  				pk, err := sk.PublicKey()
    78  				Expect(err).NotTo(HaveOccurred())
    79  
    80  				Expect(pk.Private()).To(BeFalse())
    81  				Expect(pk.Symmetric()).To(BeFalse())
    82  				Expect(pk.SKI()).NotTo(BeNil())
    83  				Expect(pk.SKI()).To(BeEquivalentTo(SKI))
    84  				raw, err := pk.Bytes()
    85  				Expect(err).NotTo(HaveOccurred())
    86  				Expect(raw).NotTo(BeNil())
    87  				Expect(raw).To(BeEquivalentTo(pkBytes))
    88  
    89  				pk2, err := pk.PublicKey()
    90  				Expect(err).NotTo(HaveOccurred())
    91  				Expect(pk).To(BeEquivalentTo(pk2))
    92  			})
    93  
    94  			Context("and the secret key is exportable", func() {
    95  				BeforeEach(func() {
    96  					RevocationKeyGen.Exportable = true
    97  					fakeRevocationSecretKey = handlers.NewRevocationSecretKey(idemixRevocationKey, true)
    98  				})
    99  
   100  				It("returns no error and a key", func() {
   101  					var err error
   102  					sk, err = RevocationKeyGen.KeyGen(&bccsp.IdemixRevocationKeyGenOpts{})
   103  					Expect(err).NotTo(HaveOccurred())
   104  					Expect(sk).To(BeEquivalentTo(fakeRevocationSecretKey))
   105  
   106  					raw, err := sk.Bytes()
   107  					Expect(err).NotTo(HaveOccurred())
   108  					Expect(raw).NotTo(BeNil())
   109  					Expect(raw).To(BeEquivalentTo(idemixRevocationKey.D.Bytes()))
   110  				})
   111  			})
   112  
   113  			Context("and the secret key is not exportable", func() {
   114  				BeforeEach(func() {
   115  					RevocationKeyGen.Exportable = false
   116  					fakeRevocationSecretKey = handlers.NewRevocationSecretKey(idemixRevocationKey, false)
   117  				})
   118  
   119  				It("returns no error and a key", func() {
   120  					sk, err := RevocationKeyGen.KeyGen(&bccsp.IdemixRevocationKeyGenOpts{})
   121  					Expect(err).NotTo(HaveOccurred())
   122  					Expect(sk).To(BeEquivalentTo(fakeRevocationSecretKey))
   123  
   124  					raw, err := sk.Bytes()
   125  					Expect(err).To(MatchError("not exportable"))
   126  					Expect(raw).To(BeNil())
   127  				})
   128  
   129  			})
   130  		})
   131  
   132  		Context("and the underlying cryptographic algorithm fails", func() {
   133  			BeforeEach(func() {
   134  				fakeRevocation.NewKeyReturns(nil, errors.New("new-key error"))
   135  			})
   136  
   137  			It("returns an error", func() {
   138  				keyPair, err := RevocationKeyGen.KeyGen(&bccsp.IdemixRevocationKeyGenOpts{})
   139  				Expect(err).To(MatchError("new-key error"))
   140  				Expect(keyPair).To(BeNil())
   141  			})
   142  		})
   143  
   144  	})
   145  
   146  	Context("when importing a revocation public key", func() {
   147  		var (
   148  			RevocationPublicKeyImporter *handlers.RevocationPublicKeyImporter
   149  		)
   150  
   151  		BeforeEach(func() {
   152  			RevocationPublicKeyImporter = &handlers.RevocationPublicKeyImporter{}
   153  		})
   154  
   155  		Context("and the underlying cryptographic algorithm succeed", func() {
   156  			var (
   157  				raw      []byte
   158  				pemBytes []byte
   159  			)
   160  
   161  			BeforeEach(func() {
   162  				key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
   163  				Expect(err).NotTo(HaveOccurred())
   164  
   165  				raw, err = x509.MarshalPKIXPublicKey(key.Public())
   166  				Expect(err).NotTo(HaveOccurred())
   167  
   168  				pemBytes = pem.EncodeToMemory(
   169  					&pem.Block{
   170  						Type:  "PUBLIC KEY",
   171  						Bytes: raw,
   172  					},
   173  				)
   174  			})
   175  
   176  			It("import is successful", func() {
   177  				k, err := RevocationPublicKeyImporter.KeyImport(pemBytes, nil)
   178  				Expect(err).NotTo(HaveOccurred())
   179  
   180  				bytes, err := k.Bytes()
   181  				Expect(err).NotTo(HaveOccurred())
   182  				Expect(bytes).To(BeEquivalentTo(raw))
   183  			})
   184  		})
   185  
   186  		Context("and the underlying cryptographic algorithm fails", func() {
   187  
   188  			It("returns an error on nil raw", func() {
   189  				k, err := RevocationPublicKeyImporter.KeyImport(nil, nil)
   190  				Expect(err).To(MatchError("invalid raw, expected byte array"))
   191  				Expect(k).To(BeNil())
   192  			})
   193  
   194  			It("returns an error on empty raw", func() {
   195  				k, err := RevocationPublicKeyImporter.KeyImport([]byte{}, nil)
   196  				Expect(err).To(MatchError("invalid raw, it must not be nil"))
   197  				Expect(k).To(BeNil())
   198  			})
   199  
   200  			It("returns an error on invalid raw", func() {
   201  				k, err := RevocationPublicKeyImporter.KeyImport(RevocationPublicKeyImporter, nil)
   202  				Expect(err).To(MatchError("invalid raw, expected byte array"))
   203  				Expect(k).To(BeNil())
   204  			})
   205  
   206  			It("returns an error", func() {
   207  				k, err := RevocationPublicKeyImporter.KeyImport([]byte("fake-raw"), nil)
   208  				Expect(err).To(MatchError("Failed to decode revocation ECDSA public key"))
   209  				Expect(k).To(BeNil())
   210  			})
   211  
   212  		})
   213  
   214  	})
   215  
   216  })
   217  
   218  var _ = Describe("CRI", func() {
   219  
   220  	Describe("when creating a CRI", func() {
   221  
   222  		var (
   223  			CriSigner      *handlers.CriSigner
   224  			fakeRevocation *mock.Revocation
   225  		)
   226  
   227  		BeforeEach(func() {
   228  			fakeRevocation = &mock.Revocation{}
   229  			CriSigner = &handlers.CriSigner{Revocation: fakeRevocation}
   230  		})
   231  
   232  		Context("and the underlying cryptographic algorithm succeed", func() {
   233  			var (
   234  				fakeSignature []byte
   235  			)
   236  			BeforeEach(func() {
   237  				fakeSignature = []byte("fake signature")
   238  				fakeRevocation.SignReturns(fakeSignature, nil)
   239  			})
   240  
   241  			It("returns no error and a signature", func() {
   242  				signature, err := CriSigner.Sign(
   243  					handlers.NewRevocationSecretKey(nil, false),
   244  					nil,
   245  					&bccsp.IdemixCRISignerOpts{},
   246  				)
   247  				Expect(err).NotTo(HaveOccurred())
   248  				Expect(signature).To(BeEquivalentTo(fakeSignature))
   249  
   250  			})
   251  		})
   252  
   253  		Context("and the underlying cryptographic algorithm fails", func() {
   254  			BeforeEach(func() {
   255  				fakeRevocation.SignReturns(nil, errors.New("sign error"))
   256  			})
   257  
   258  			It("returns an error", func() {
   259  				signature, err := CriSigner.Sign(
   260  					handlers.NewRevocationSecretKey(nil, false),
   261  					nil,
   262  					&bccsp.IdemixCRISignerOpts{},
   263  				)
   264  				Expect(err).To(MatchError("sign error"))
   265  				Expect(signature).To(BeNil())
   266  			})
   267  		})
   268  
   269  		Context("and the parameters are not well formed", func() {
   270  
   271  			Context("and the revocation secret key is nil", func() {
   272  				It("returns error", func() {
   273  					signature, err := CriSigner.Sign(
   274  						nil,
   275  						nil,
   276  						nil,
   277  					)
   278  					Expect(err).To(MatchError("invalid key, expected *revocationSecretKey"))
   279  					Expect(signature).To(BeNil())
   280  				})
   281  			})
   282  
   283  			Context("and the revocation secret key is not of type *revocationSecretKey", func() {
   284  				It("returns error", func() {
   285  					signature, err := CriSigner.Sign(
   286  						handlers.NewIssuerPublicKey(nil),
   287  						nil,
   288  						nil,
   289  					)
   290  					Expect(err).To(MatchError("invalid key, expected *revocationSecretKey"))
   291  					Expect(signature).To(BeNil())
   292  				})
   293  			})
   294  
   295  			Context("and the underlying cryptographic algorithm fails", func() {
   296  				BeforeEach(func() {
   297  				})
   298  
   299  				It("returns an error", func() {
   300  					signature, err := CriSigner.Sign(
   301  						handlers.NewRevocationSecretKey(nil, false),
   302  						nil,
   303  						nil,
   304  					)
   305  					Expect(err).To(MatchError("invalid options, expected *IdemixCRISignerOpts"))
   306  					Expect(signature).To(BeNil())
   307  				})
   308  			})
   309  
   310  		})
   311  	})
   312  
   313  	Describe("when verifying a CRI", func() {
   314  
   315  		var (
   316  			CriVerifier    *handlers.CriVerifier
   317  			fakeRevocation *mock.Revocation
   318  		)
   319  
   320  		BeforeEach(func() {
   321  			fakeRevocation = &mock.Revocation{}
   322  			CriVerifier = &handlers.CriVerifier{Revocation: fakeRevocation}
   323  		})
   324  
   325  		Context("and the underlying cryptographic algorithm succeed", func() {
   326  			BeforeEach(func() {
   327  				fakeRevocation.VerifyReturns(nil)
   328  			})
   329  
   330  			It("returns no error and valid signature", func() {
   331  				valid, err := CriVerifier.Verify(
   332  					handlers.NewRevocationPublicKey(nil),
   333  					[]byte("fake signature"),
   334  					nil,
   335  					&bccsp.IdemixCRISignerOpts{},
   336  				)
   337  				Expect(err).NotTo(HaveOccurred())
   338  				Expect(valid).To(BeTrue())
   339  			})
   340  		})
   341  
   342  		Context("and the underlying cryptographic algorithm fails", func() {
   343  			BeforeEach(func() {
   344  				fakeRevocation.VerifyReturns(errors.New("verify error"))
   345  			})
   346  
   347  			It("returns an error", func() {
   348  				valid, err := CriVerifier.Verify(
   349  					handlers.NewRevocationPublicKey(nil),
   350  					[]byte("fake signature"),
   351  					nil,
   352  					&bccsp.IdemixCRISignerOpts{},
   353  				)
   354  				Expect(err).To(MatchError("verify error"))
   355  				Expect(valid).To(BeFalse())
   356  			})
   357  		})
   358  
   359  		Context("and the parameters are not well formed", func() {
   360  
   361  			Context("and the user secret key is nil", func() {
   362  				It("returns error", func() {
   363  					valid, err := CriVerifier.Verify(
   364  						nil,
   365  						[]byte("fake signature"),
   366  						nil,
   367  						&bccsp.IdemixCRISignerOpts{},
   368  					)
   369  					Expect(err).To(MatchError("invalid key, expected *revocationPublicKey"))
   370  					Expect(valid).To(BeFalse())
   371  				})
   372  			})
   373  
   374  			Context("and the user secret key is not of type *revocationPublicKey", func() {
   375  				It("returns error", func() {
   376  					valid, err := CriVerifier.Verify(
   377  						handlers.NewIssuerPublicKey(nil),
   378  						[]byte("fake signature"),
   379  						nil,
   380  						&bccsp.IdemixCRISignerOpts{},
   381  					)
   382  					Expect(err).To(MatchError("invalid key, expected *revocationPublicKey"))
   383  					Expect(valid).To(BeFalse())
   384  				})
   385  			})
   386  
   387  			Context("and the signature is empty", func() {
   388  				It("returns error", func() {
   389  					valid, err := CriVerifier.Verify(
   390  						handlers.NewRevocationPublicKey(nil),
   391  						nil,
   392  						nil,
   393  						&bccsp.IdemixCRISignerOpts{},
   394  					)
   395  					Expect(err).To(MatchError("invalid signature, it must not be empty"))
   396  					Expect(valid).To(BeFalse())
   397  				})
   398  			})
   399  
   400  			Context("and the option is empty", func() {
   401  				It("returns error", func() {
   402  					valid, err := CriVerifier.Verify(
   403  						handlers.NewRevocationPublicKey(nil),
   404  						[]byte("fake signature"),
   405  						nil,
   406  						nil,
   407  					)
   408  					Expect(err).To(MatchError("invalid options, expected *IdemixCRISignerOpts"))
   409  					Expect(valid).To(BeFalse())
   410  				})
   411  			})
   412  
   413  			Context("and the option is not of type *IdemixCRISignerOpts", func() {
   414  				It("returns error", func() {
   415  					valid, err := CriVerifier.Verify(
   416  						handlers.NewRevocationPublicKey(nil),
   417  						[]byte("fake signature"),
   418  						nil,
   419  						&bccsp.IdemixCredentialRequestSignerOpts{},
   420  					)
   421  					Expect(err).To(MatchError("invalid options, expected *IdemixCRISignerOpts"))
   422  					Expect(valid).To(BeFalse())
   423  				})
   424  			})
   425  
   426  		})
   427  	})
   428  })