forked from hyperledger/fabric
-
Notifications
You must be signed in to change notification settings - Fork 0
/
idemixca.go
88 lines (75 loc) · 2.51 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
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package idemixca
import (
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/idemix"
"github.com/hyperledger/fabric/msp"
m "github.com/hyperledger/fabric/protos/msp"
amcl "github.com/manudrijvers/amcl/go"
"github.com/pkg/errors"
)
// GenerateIssuerKey invokes Idemix library to generate an issuer (CA) signing key pair
// currently two attributes are supported by the issuer:
// AttributeNameOU is the organization unit name
// AttributeNameRole is the role (member or admin) name
// 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}
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
}
// GenerateMSPConfig creates a new MSP config
// If the new MSP config contains a signer then
// it generates a fresh user secret and issues a credential
// with two attributes (described above)
// using the CA's key pair from the file
// If the new MSP config does not contain a signer
// (meaning it is used only for verification)
// then only a public key of the CA (issuer) is added to the MSP config (besides the name)
func GenerateSignerConfig(isAdmin bool, ouString string, key *idemix.IssuerKey) ([]byte, error) {
attrs := make([]*amcl.BIG, 2)
if ouString == "" {
return nil, errors.Errorf("the OU attribute value is empty")
}
role := m.MSPRole_MEMBER
if isAdmin {
role = m.MSPRole_ADMIN
}
attrs[0] = idemix.HashModOrder([]byte(ouString))
attrs[1] = amcl.NewBIGint(int(role))
rng, err := idemix.GetRand()
if err != nil {
return nil, errors.WithMessage(err, "Error getting PRNG")
}
sk := idemix.RandModOrder(rng)
randCred := idemix.RandModOrder(rng)
ni := idemix.RandModOrder(rng)
msg := idemix.NewCredRequest(sk, randCred, 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")
}
cred.Complete(randCred)
credBytes, err := proto.Marshal(cred)
if err != nil {
return nil, errors.WithMessage(err, "failed to marshal credential")
}
signer := &m.IdemixMSPSignerConfig{
credBytes,
idemix.BigToBytes(sk),
ouString,
isAdmin,
}
return proto.Marshal(signer)
}