github.com/kaituanwang/hyperledger@v2.0.1+incompatible/idemix/issuerkey.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package idemix 8 9 import ( 10 "github.com/golang/protobuf/proto" 11 "github.com/hyperledger/fabric-amcl/amcl" 12 "github.com/hyperledger/fabric-amcl/amcl/FP256BN" 13 "github.com/pkg/errors" 14 ) 15 16 // The Issuer secret ISk and public IPk keys are used to issue credentials and 17 // to verify signatures created using the credentials 18 19 // The Issuer Secret Key is a random exponent (generated randomly from Z*_p) 20 21 // The Issuer Public Key consists of several elliptic curve points (ECP), 22 // where index 1 corresponds to group G1 and 2 to group G2) 23 // HSk, HRand, BarG1, BarG2, an ECP array HAttrs, and an ECP2 W, 24 // and a proof of knowledge of the corresponding secret key 25 26 // NewIssuerKey creates a new issuer key pair taking an array of attribute names 27 // that will be contained in credentials certified by this issuer (a credential specification) 28 // See http://eprint.iacr.org/2016/663.pdf Sec. 4.3, for references. 29 func NewIssuerKey(AttributeNames []string, rng *amcl.RAND) (*IssuerKey, error) { 30 // validate inputs 31 32 // check for duplicated attributes 33 attributeNamesMap := map[string]bool{} 34 for _, name := range AttributeNames { 35 if attributeNamesMap[name] { 36 return nil, errors.Errorf("attribute %s appears multiple times in AttributeNames", name) 37 } 38 attributeNamesMap[name] = true 39 } 40 41 key := new(IssuerKey) 42 43 // generate issuer secret key 44 ISk := RandModOrder(rng) 45 key.Isk = BigToBytes(ISk) 46 47 // generate the corresponding public key 48 key.Ipk = new(IssuerPublicKey) 49 key.Ipk.AttributeNames = AttributeNames 50 51 W := GenG2.Mul(ISk) 52 key.Ipk.W = Ecp2ToProto(W) 53 54 // generate bases that correspond to the attributes 55 key.Ipk.HAttrs = make([]*ECP, len(AttributeNames)) 56 for i := 0; i < len(AttributeNames); i++ { 57 key.Ipk.HAttrs[i] = EcpToProto(GenG1.Mul(RandModOrder(rng))) 58 } 59 60 // generate base for the secret key 61 HSk := GenG1.Mul(RandModOrder(rng)) 62 key.Ipk.HSk = EcpToProto(HSk) 63 64 // generate base for the randomness 65 HRand := GenG1.Mul(RandModOrder(rng)) 66 key.Ipk.HRand = EcpToProto(HRand) 67 68 BarG1 := GenG1.Mul(RandModOrder(rng)) 69 key.Ipk.BarG1 = EcpToProto(BarG1) 70 71 BarG2 := BarG1.Mul(ISk) 72 key.Ipk.BarG2 = EcpToProto(BarG2) 73 74 // generate a zero-knowledge proof of knowledge (ZK PoK) of the secret key which 75 // is in W and BarG2. 76 77 // Sample the randomness needed for the proof 78 r := RandModOrder(rng) 79 80 // Step 1: First message (t-values) 81 t1 := GenG2.Mul(r) // t1 = g_2^r, cover W 82 t2 := BarG1.Mul(r) // t2 = (\bar g_1)^r, cover BarG2 83 84 // Step 2: Compute the Fiat-Shamir hash, forming the challenge of the ZKP. 85 proofData := make([]byte, 18*FieldBytes+3) 86 index := 0 87 index = appendBytesG2(proofData, index, t1) 88 index = appendBytesG1(proofData, index, t2) 89 index = appendBytesG2(proofData, index, GenG2) 90 index = appendBytesG1(proofData, index, BarG1) 91 index = appendBytesG2(proofData, index, W) 92 index = appendBytesG1(proofData, index, BarG2) 93 94 proofC := HashModOrder(proofData) 95 key.Ipk.ProofC = BigToBytes(proofC) 96 97 // Step 3: reply to the challenge message (s-values) 98 proofS := Modadd(FP256BN.Modmul(proofC, ISk, GroupOrder), r, GroupOrder) // // s = r + C \cdot ISk 99 key.Ipk.ProofS = BigToBytes(proofS) 100 101 // Hash the public key 102 serializedIPk, err := proto.Marshal(key.Ipk) 103 if err != nil { 104 return nil, errors.Wrap(err, "failed to marshal issuer public key") 105 } 106 key.Ipk.Hash = BigToBytes(HashModOrder(serializedIPk)) 107 108 // We are done 109 return key, nil 110 } 111 112 // Check checks that this issuer public key is valid, i.e. 113 // that all components are present and a ZK proofs verifies 114 func (IPk *IssuerPublicKey) Check() error { 115 // Unmarshall the public key 116 NumAttrs := len(IPk.GetAttributeNames()) 117 HSk := EcpFromProto(IPk.GetHSk()) 118 HRand := EcpFromProto(IPk.GetHRand()) 119 HAttrs := make([]*FP256BN.ECP, len(IPk.GetHAttrs())) 120 for i := 0; i < len(IPk.GetHAttrs()); i++ { 121 HAttrs[i] = EcpFromProto(IPk.GetHAttrs()[i]) 122 } 123 BarG1 := EcpFromProto(IPk.GetBarG1()) 124 BarG2 := EcpFromProto(IPk.GetBarG2()) 125 W := Ecp2FromProto(IPk.GetW()) 126 ProofC := FP256BN.FromBytes(IPk.GetProofC()) 127 ProofS := FP256BN.FromBytes(IPk.GetProofS()) 128 129 // Check that the public key is well-formed 130 if NumAttrs < 0 || 131 HSk == nil || 132 HRand == nil || 133 BarG1 == nil || 134 BarG1.Is_infinity() || 135 BarG2 == nil || 136 HAttrs == nil || 137 len(IPk.HAttrs) < NumAttrs { 138 return errors.Errorf("some part of the public key is undefined") 139 } 140 for i := 0; i < NumAttrs; i++ { 141 if IPk.HAttrs[i] == nil { 142 return errors.Errorf("some part of the public key is undefined") 143 } 144 } 145 146 // Verify Proof 147 148 // Recompute challenge 149 proofData := make([]byte, 18*FieldBytes+3) 150 index := 0 151 152 // Recompute t-values using s-values 153 t1 := GenG2.Mul(ProofS) 154 t1.Add(W.Mul(FP256BN.Modneg(ProofC, GroupOrder))) // t1 = g_2^s \cdot W^{-C} 155 156 t2 := BarG1.Mul(ProofS) 157 t2.Add(BarG2.Mul(FP256BN.Modneg(ProofC, GroupOrder))) // t2 = {\bar g_1}^s \cdot {\bar g_2}^C 158 159 index = appendBytesG2(proofData, index, t1) 160 index = appendBytesG1(proofData, index, t2) 161 index = appendBytesG2(proofData, index, GenG2) 162 index = appendBytesG1(proofData, index, BarG1) 163 index = appendBytesG2(proofData, index, W) 164 index = appendBytesG1(proofData, index, BarG2) 165 166 // Verify that the challenge is the same 167 if *ProofC != *HashModOrder(proofData) { 168 return errors.Errorf("zero knowledge proof in public key invalid") 169 } 170 171 return IPk.SetHash() 172 } 173 174 // SetHash appends a hash of a serialized public key 175 func (IPk *IssuerPublicKey) SetHash() error { 176 IPk.Hash = nil 177 serializedIPk, err := proto.Marshal(IPk) 178 if err != nil { 179 return errors.Wrap(err, "Failed to marshal issuer public key") 180 } 181 IPk.Hash = BigToBytes(HashModOrder(serializedIPk)) 182 return nil 183 }