forked from hyperledger/fabric
-
Notifications
You must be signed in to change notification settings - Fork 6
/
idemixca.go
98 lines (83 loc) · 3.33 KB
/
idemixca.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package idemixca
import (
"crypto/ecdsa"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric-amcl/amcl/FP256BN"
m "github.com/hyperledger/fabric-protos-go/msp"
"github.com/hyperledger/fabric/idemix"
"github.com/hyperledger/fabric/msp"
"github.com/pkg/errors"
)
// GenerateIssuerKey invokes Idemix library to generate an issuer (CA) signing key pair.
// Currently four attributes are supported by the issuer:
// AttributeNameOU is the organization unit name
// AttributeNameRole is the role (member or admin) name
// AttributeNameEnrollmentId is the enrollment id
// AttributeNameRevocationHandle contains the revocation handle, which can be used to revoke this user
// Generated keys are serialized to bytes.
func GenerateIssuerKey() ([]byte, []byte, error) {
rng, err := idemix.GetRand()
if err != nil {
return nil, nil, err
}
AttributeNames := []string{msp.AttributeNameOU, msp.AttributeNameRole, msp.AttributeNameEnrollmentId, msp.AttributeNameRevocationHandle}
key, err := idemix.NewIssuerKey(AttributeNames, rng)
if err != nil {
return nil, nil, errors.WithMessage(err, "cannot generate CA key")
}
ipkSerialized, err := proto.Marshal(key.Ipk)
return key.Isk, ipkSerialized, err
}
// GenerateSignerConfig creates a new signer config.
// It generates a fresh user secret and issues a credential
// with four attributes (described above) using the CA's key pair.
func GenerateSignerConfig(roleMask int, ouString string, enrollmentId string, revocationHandle int, key *idemix.IssuerKey, revKey *ecdsa.PrivateKey) ([]byte, error) {
attrs := make([]*FP256BN.BIG, 4)
if ouString == "" {
return nil, errors.Errorf("the OU attribute value is empty")
}
if enrollmentId == "" {
return nil, errors.Errorf("the enrollment id value is empty")
}
attrs[msp.AttributeIndexOU] = idemix.HashModOrder([]byte(ouString))
attrs[msp.AttributeIndexRole] = FP256BN.NewBIGint(roleMask)
attrs[msp.AttributeIndexEnrollmentId] = idemix.HashModOrder([]byte(enrollmentId))
attrs[msp.AttributeIndexRevocationHandle] = FP256BN.NewBIGint(revocationHandle)
rng, err := idemix.GetRand()
if err != nil {
return nil, errors.WithMessage(err, "Error getting PRNG")
}
sk := idemix.RandModOrder(rng)
ni := idemix.BigToBytes(idemix.RandModOrder(rng))
msg := idemix.NewCredRequest(sk, ni, key.Ipk, rng)
cred, err := idemix.NewCredential(key, msg, attrs, rng)
if err != nil {
return nil, errors.WithMessage(err, "failed to generate a credential")
}
credBytes, err := proto.Marshal(cred)
if err != nil {
return nil, errors.WithMessage(err, "failed to marshal credential")
}
// NOTE currently, idemixca creates CRI's with "ALG_NO_REVOCATION"
cri, err := idemix.CreateCRI(revKey, []*FP256BN.BIG{FP256BN.NewBIGint(revocationHandle)}, 0, idemix.ALG_NO_REVOCATION, rng)
if err != nil {
return nil, err
}
criBytes, err := proto.Marshal(cri)
if err != nil {
return nil, errors.WithMessage(err, "failed to marshal CRI")
}
signer := &m.IdemixMSPSignerConfig{
Cred: credBytes,
Sk: idemix.BigToBytes(sk),
OrganizationalUnitIdentifier: ouString,
Role: int32(roleMask),
EnrollmentId: enrollmentId,
CredentialRevocationInformation: criBytes,
}
return proto.Marshal(signer)
}