github.com/Hnampk/my-fabric@v0.0.0-20201028083322-75069da399c0/idemix/credrequest.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/hyperledger/fabric-amcl/amcl" 11 "github.com/hyperledger/fabric-amcl/amcl/FP256BN" 12 "github.com/pkg/errors" 13 ) 14 15 // credRequestLabel is the label used in zero-knowledge proof (ZKP) to identify that this ZKP is a credential request 16 const credRequestLabel = "credRequest" 17 18 // Credential issuance is an interactive protocol between a user and an issuer 19 // The issuer takes its secret and public keys and user attribute values as input 20 // The user takes the issuer public key and user secret as input 21 // The issuance protocol consists of the following steps: 22 // 1) The issuer sends a random nonce to the user 23 // 2) The user creates a Credential Request using the public key of the issuer, user secret, and the nonce as input 24 // The request consists of a commitment to the user secret (can be seen as a public key) and a zero-knowledge proof 25 // of knowledge of the user secret key 26 // The user sends the credential request to the issuer 27 // 3) The issuer verifies the credential request by verifying the zero-knowledge proof 28 // If the request is valid, the issuer issues a credential to the user by signing the commitment to the secret key 29 // together with the attribute values and sends the credential back to the user 30 // 4) The user verifies the issuer's signature and stores the credential that consists of 31 // the signature value, a randomness used to create the signature, the user secret, and the attribute values 32 33 // NewCredRequest creates a new Credential Request, the first message of the interactive credential issuance protocol 34 // (from user to issuer) 35 func NewCredRequest(sk *FP256BN.BIG, IssuerNonce []byte, ipk *IssuerPublicKey, rng *amcl.RAND) *CredRequest { 36 // Set Nym as h_{sk}^{sk} 37 HSk := EcpFromProto(ipk.HSk) 38 Nym := HSk.Mul(sk) 39 40 // generate a zero-knowledge proof of knowledge (ZK PoK) of the secret key 41 42 // Sample the randomness needed for the proof 43 rSk := RandModOrder(rng) 44 45 // Step 1: First message (t-values) 46 t := HSk.Mul(rSk) // t = h_{sk}^{r_{sk}}, cover Nym 47 48 // Step 2: Compute the Fiat-Shamir hash, forming the challenge of the ZKP. 49 // proofData is the data being hashed, it consists of: 50 // the credential request label 51 // 3 elements of G1 each taking 2*FieldBytes+1 bytes 52 // hash of the issuer public key of length FieldBytes 53 // issuer nonce of length FieldBytes 54 proofData := make([]byte, len([]byte(credRequestLabel))+3*(2*FieldBytes+1)+2*FieldBytes) 55 index := 0 56 index = appendBytesString(proofData, index, credRequestLabel) 57 index = appendBytesG1(proofData, index, t) 58 index = appendBytesG1(proofData, index, HSk) 59 index = appendBytesG1(proofData, index, Nym) 60 index = appendBytes(proofData, index, IssuerNonce) 61 copy(proofData[index:], ipk.Hash) 62 proofC := HashModOrder(proofData) 63 64 // Step 3: reply to the challenge message (s-values) 65 proofS := Modadd(FP256BN.Modmul(proofC, sk, GroupOrder), rSk, GroupOrder) // s = r_{sk} + C \cdot sk 66 67 // Done 68 return &CredRequest{ 69 Nym: EcpToProto(Nym), 70 IssuerNonce: IssuerNonce, 71 ProofC: BigToBytes(proofC), 72 ProofS: BigToBytes(proofS)} 73 } 74 75 // Check cryptographically verifies the credential request 76 func (m *CredRequest) Check(ipk *IssuerPublicKey) error { 77 Nym := EcpFromProto(m.GetNym()) 78 IssuerNonce := m.GetIssuerNonce() 79 ProofC := FP256BN.FromBytes(m.GetProofC()) 80 ProofS := FP256BN.FromBytes(m.GetProofS()) 81 82 HSk := EcpFromProto(ipk.HSk) 83 84 if Nym == nil || IssuerNonce == nil || ProofC == nil || ProofS == nil { 85 return errors.Errorf("one of the proof values is undefined") 86 } 87 88 // Verify Proof 89 90 // Recompute t-values using s-values 91 t := HSk.Mul(ProofS) 92 t.Sub(Nym.Mul(ProofC)) // t = h_{sk}^s / Nym^C 93 94 // Recompute challenge 95 proofData := make([]byte, len([]byte(credRequestLabel))+3*(2*FieldBytes+1)+2*FieldBytes) 96 index := 0 97 index = appendBytesString(proofData, index, credRequestLabel) 98 index = appendBytesG1(proofData, index, t) 99 index = appendBytesG1(proofData, index, HSk) 100 index = appendBytesG1(proofData, index, Nym) 101 index = appendBytes(proofData, index, IssuerNonce) 102 copy(proofData[index:], ipk.Hash) 103 104 if *ProofC != *HashModOrder(proofData) { 105 return errors.Errorf("zero knowledge proof is invalid") 106 } 107 108 return nil 109 }