github.com/anjalikarhana/fabric@v2.1.1+incompatible/idemix/nymsignature.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 // NewSignature creates a new idemix pseudonym signature 16 func NewNymSignature(sk *FP256BN.BIG, Nym *FP256BN.ECP, RNym *FP256BN.BIG, ipk *IssuerPublicKey, msg []byte, rng *amcl.RAND) (*NymSignature, error) { 17 // Validate inputs 18 if sk == nil || Nym == nil || RNym == nil || ipk == nil || rng == nil { 19 return nil, errors.Errorf("cannot create NymSignature: received nil input") 20 } 21 22 Nonce := RandModOrder(rng) 23 24 HRand := EcpFromProto(ipk.HRand) 25 HSk := EcpFromProto(ipk.HSk) 26 27 // The rest of this function constructs the non-interactive zero knowledge proof proving that 28 // the signer 'owns' this pseudonym, i.e., it knows the secret key and randomness on which it is based. 29 // Recall that (Nym,RNym) is the output of MakeNym. Therefore, Nym = h_{sk}^sk \cdot h_r^r 30 31 // Sample the randomness needed for the proof 32 rSk := RandModOrder(rng) 33 rRNym := RandModOrder(rng) 34 35 // Step 1: First message (t-values) 36 t := HSk.Mul2(rSk, HRand, rRNym) // t = h_{sk}^{r_sk} \cdot h_r^{r_{RNym} 37 38 // Step 2: Compute the Fiat-Shamir hash, forming the challenge of the ZKP. 39 // proofData will hold the data being hashed, it consists of: 40 // - the signature label 41 // - 2 elements of G1 each taking 2*FieldBytes+1 bytes 42 // - one bigint (hash of the issuer public key) of length FieldBytes 43 // - disclosed attributes 44 // - message being signed 45 proofData := make([]byte, len([]byte(signLabel))+2*(2*FieldBytes+1)+FieldBytes+len(msg)) 46 index := 0 47 index = appendBytesString(proofData, index, signLabel) 48 index = appendBytesG1(proofData, index, t) 49 index = appendBytesG1(proofData, index, Nym) 50 copy(proofData[index:], ipk.Hash) 51 index = index + FieldBytes 52 copy(proofData[index:], msg) 53 c := HashModOrder(proofData) 54 // combine the previous hash and the nonce and hash again to compute the final Fiat-Shamir value 'ProofC' 55 index = 0 56 proofData = proofData[:2*FieldBytes] 57 index = appendBytesBig(proofData, index, c) 58 index = appendBytesBig(proofData, index, Nonce) 59 ProofC := HashModOrder(proofData) 60 61 // Step 3: reply to the challenge message (s-values) 62 ProofSSk := Modadd(rSk, FP256BN.Modmul(ProofC, sk, GroupOrder), GroupOrder) // s_{sk} = r_{sk} + C \cdot sk 63 ProofSRNym := Modadd(rRNym, FP256BN.Modmul(ProofC, RNym, GroupOrder), GroupOrder) // s_{RNym} = r_{RNym} + C \cdot RNym 64 65 // The signature consists of the Fiat-Shamir hash (ProofC), the s-values (ProofSSk, ProofSRNym), and the nonce. 66 return &NymSignature{ 67 ProofC: BigToBytes(ProofC), 68 ProofSSk: BigToBytes(ProofSSk), 69 ProofSRNym: BigToBytes(ProofSRNym), 70 Nonce: BigToBytes(Nonce)}, nil 71 } 72 73 // Ver verifies an idemix NymSignature 74 func (sig *NymSignature) Ver(nym *FP256BN.ECP, ipk *IssuerPublicKey, msg []byte) error { 75 ProofC := FP256BN.FromBytes(sig.GetProofC()) 76 ProofSSk := FP256BN.FromBytes(sig.GetProofSSk()) 77 ProofSRNym := FP256BN.FromBytes(sig.GetProofSRNym()) 78 Nonce := FP256BN.FromBytes(sig.GetNonce()) 79 80 HRand := EcpFromProto(ipk.HRand) 81 HSk := EcpFromProto(ipk.HSk) 82 83 // Verify Proof 84 85 // Recompute t-values using s-values 86 t := HSk.Mul2(ProofSSk, HRand, ProofSRNym) 87 t.Sub(nym.Mul(ProofC)) // t = h_{sk}^{s_{sk} \ cdot h_r^{s_{RNym} 88 89 // Recompute challenge 90 proofData := make([]byte, len([]byte(signLabel))+2*(2*FieldBytes+1)+FieldBytes+len(msg)) 91 index := 0 92 index = appendBytesString(proofData, index, signLabel) 93 index = appendBytesG1(proofData, index, t) 94 index = appendBytesG1(proofData, index, nym) 95 copy(proofData[index:], ipk.Hash) 96 index = index + FieldBytes 97 copy(proofData[index:], msg) 98 c := HashModOrder(proofData) 99 index = 0 100 proofData = proofData[:2*FieldBytes] 101 index = appendBytesBig(proofData, index, c) 102 index = appendBytesBig(proofData, index, Nonce) 103 104 if *ProofC != *HashModOrder(proofData) { 105 return errors.Errorf("pseudonym signature invalid: zero-knowledge proof is invalid") 106 } 107 108 return nil 109 }