Skip to content

Commit

Permalink
[FAB-12602] Idemix Credential Revocation Information
Browse files Browse the repository at this point in the history
This change-set does the following:
- introduces opts to geenrate and verify the CRI
- introduces a BCCSP signer and verifier for the CRI
- tests

Change-Id: I69becce66a69345034dbcf288af3529532835b42
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
  • Loading branch information
adecaro committed Nov 14, 2018
1 parent b2ea980 commit e223d27
Show file tree
Hide file tree
Showing 5 changed files with 488 additions and 2 deletions.
16 changes: 15 additions & 1 deletion bccsp/idemix/idemix.go
Expand Up @@ -80,9 +80,23 @@ type Credential interface {
Verify(sk Big, ipk IssuerPublicKey, credential []byte, attributes []bccsp.IdemixAttribute) error
}

// Revocation handles idemix revocation-related operations
// Revocation is a local interface to decouple from the idemix implementation
// the revocation-related operations
type Revocation interface {

// NewKey generates a long term signing key that will be used for revocation
NewKey() (*ecdsa.PrivateKey, error)

// Sign creates the Credential Revocation Information for a certain time period (epoch).
// Users can use the CRI to prove that they are not revoked.
// Note that when not using revocation (i.e., alg = ALG_NO_REVOCATION), the entered unrevokedHandles are not used,
// and the resulting CRI can be used by any signer.
Sign(key *ecdsa.PrivateKey, unrevokedHandles [][]byte, epoch int, alg bccsp.RevocationAlgorithm) ([]byte, error)

// Verify verifies that the revocation PK for a certain epoch is valid,
// by checking that it was signed with the long term revocation key.
// Note that even if we use no revocation (i.e., alg = ALG_NO_REVOCATION), we need
// to verify the signature to make sure the issuer indeed signed that no revocation
// is used in this epoch.
Verify(pk *ecdsa.PublicKey, cri []byte, epoch int, alg bccsp.RevocationAlgorithm) error
}
150 changes: 150 additions & 0 deletions bccsp/idemix/mock/revocation.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 63 additions & 1 deletion bccsp/idemix/revocation.go
Expand Up @@ -72,6 +72,10 @@ type revocationPublicKey struct {
pubKey *ecdsa.PublicKey
}

func NewRevocationPublicKey(pubKey *ecdsa.PublicKey) *revocationPublicKey {
return &revocationPublicKey{pubKey: pubKey}
}

// Bytes converts this key to its byte representation,
// if this operation is allowed.
func (k *revocationPublicKey) Bytes() (raw []byte, err error) {
Expand Down Expand Up @@ -120,7 +124,7 @@ type RevocationKeyGen struct {
Revocation Revocation
}

func (g *RevocationKeyGen) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error) {
func (g *RevocationKeyGen) KeyGen(opts bccsp.KeyGenOpts) (bccsp.Key, error) {
// Create a new key pair
key, err := g.Revocation.NewKey()
if err != nil {
Expand All @@ -129,3 +133,61 @@ func (g *RevocationKeyGen) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error

return &revocationSecretKey{exportable: g.Exportable, privKey: key}, nil
}

type CriSigner struct {
Revocation Revocation
}

func (s *CriSigner) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) ([]byte, error) {
revocationSecretKey, ok := k.(*revocationSecretKey)
if !ok {
return nil, errors.New("invalid key, expected *revocationSecretKey")
}
criOpts, ok := opts.(*bccsp.IdemixCRISignerOpts)
if !ok {
return nil, errors.New("invalid options, expected *IdemixCRISignerOpts")
}
if len(digest) != 0 {
return nil, errors.New("invalid digest, it must be empty")
}

return s.Revocation.Sign(
revocationSecretKey.privKey,
criOpts.UnrevokedHandles,
criOpts.Epoch,
criOpts.RevocationAlgorithm,
)
}

type CriVerifier struct {
Revocation Revocation
}

func (v *CriVerifier) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (bool, error) {
revocationPublicKey, ok := k.(*revocationPublicKey)
if !ok {
return false, errors.New("invalid key, expected *revocationPublicKey")
}
criOpts, ok := opts.(*bccsp.IdemixCRISignerOpts)
if !ok {
return false, errors.New("invalid options, expected *IdemixCRISignerOpts")
}
if len(digest) != 0 {
return false, errors.New("invalid digest, it must be empty")
}
if len(signature) == 0 {
return false, errors.New("invalid signature, it must not be empty")
}

err := v.Revocation.Verify(
revocationPublicKey.pubKey,
signature,
criOpts.Epoch,
criOpts.RevocationAlgorithm,
)
if err != nil {
return false, err
}

return true, nil
}

0 comments on commit e223d27

Please sign in to comment.