-
Notifications
You must be signed in to change notification settings - Fork 0
/
signaturescheme.go
142 lines (126 loc) · 3.92 KB
/
signaturescheme.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package bridge
import (
"crypto/ecdsa"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric-amcl/amcl"
"github.com/hyperledger/fabric-amcl/amcl/FP256BN"
"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/idemix/handlers"
cryptolib "github.com/hyperledger/fabric/idemix"
"github.com/pkg/errors"
)
// SignatureScheme encapsulates the idemix algorithms to sign and verify using an idemix credential.
type SignatureScheme struct {
NewRand func() *amcl.RAND
}
// Sign produces an idemix-signature with the respect to the passed serialised credential (cred),
// user secret key (sk), pseudonym public key (Nym) and secret key (RNym), issuer public key (ipk),
// and attributes to be disclosed.
func (s *SignatureScheme) Sign(cred []byte, sk handlers.Big, Nym handlers.Ecp, RNym handlers.Big, ipk handlers.IssuerPublicKey, attributes []bccsp.IdemixAttribute,
msg []byte, rhIndex int, criRaw []byte) (res []byte, err error) {
defer func() {
if r := recover(); r != nil {
res = nil
err = errors.Errorf("failure [%s]", r)
}
}()
isk, ok := sk.(*Big)
if !ok {
return nil, errors.Errorf("invalid user secret key, expected *Big, got [%T]", sk)
}
inym, ok := Nym.(*Ecp)
if !ok {
return nil, errors.Errorf("invalid nym public key, expected *Ecp, got [%T]", Nym)
}
irnym, ok := RNym.(*Big)
if !ok {
return nil, errors.Errorf("invalid nym secret key, expected *Big, got [%T]", RNym)
}
iipk, ok := ipk.(*IssuerPublicKey)
if !ok {
return nil, errors.Errorf("invalid issuer public key, expected *IssuerPublicKey, got [%T]", ipk)
}
credential := &cryptolib.Credential{}
err = proto.Unmarshal(cred, credential)
if err != nil {
return nil, errors.Wrap(err, "failed unmarshalling credential")
}
cri := &cryptolib.CredentialRevocationInformation{}
err = proto.Unmarshal(criRaw, cri)
if err != nil {
return nil, errors.Wrap(err, "failed unmarshalling credential revocation information")
}
disclosure := make([]byte, len(attributes))
for i := 0; i < len(attributes); i++ {
if attributes[i].Type == bccsp.IdemixHiddenAttribute {
disclosure[i] = 0
} else {
disclosure[i] = 1
}
}
sig, err := cryptolib.NewSignature(
credential,
isk.E,
inym.E,
irnym.E,
iipk.PK,
disclosure,
msg,
rhIndex,
cri,
s.NewRand())
if err != nil {
return nil, errors.WithMessage(err, "failed creating new signature")
}
return proto.Marshal(sig)
}
// Verify checks that an idemix signature is valid with the respect to the passed issuer public key, digest, attributes,
// revocation index (rhIndex), revocation public key, and epoch.
func (*SignatureScheme) Verify(ipk handlers.IssuerPublicKey, signature, digest []byte, attributes []bccsp.IdemixAttribute, rhIndex int, revocationPublicKey *ecdsa.PublicKey, epoch int) (err error) {
defer func() {
if r := recover(); r != nil {
err = errors.Errorf("failure [%s]", r)
}
}()
iipk, ok := ipk.(*IssuerPublicKey)
if !ok {
return errors.Errorf("invalid issuer public key, expected *IssuerPublicKey, got [%T]", ipk)
}
sig := &cryptolib.Signature{}
err = proto.Unmarshal(signature, sig)
if err != nil {
return err
}
disclosure := make([]byte, len(attributes))
attrValues := make([]*FP256BN.BIG, len(attributes))
for i := 0; i < len(attributes); i++ {
switch attributes[i].Type {
case bccsp.IdemixHiddenAttribute:
disclosure[i] = 0
attrValues[i] = nil
case bccsp.IdemixBytesAttribute:
disclosure[i] = 1
attrValues[i] = cryptolib.HashModOrder(attributes[i].Value.([]byte))
case bccsp.IdemixIntAttribute:
disclosure[i] = 1
attrValues[i] = FP256BN.NewBIGint(attributes[i].Value.(int))
default:
err = errors.Errorf("attribute type not allowed or supported [%v] at position [%d]", attributes[i].Type, i)
}
}
if err != nil {
return
}
return sig.Ver(
disclosure,
iipk.PK,
digest,
attrValues,
rhIndex,
revocationPublicKey,
epoch)
}