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 })