/// <summary> /// Verifies a non-revocation proof. /// </summary> /// <param name="ip">The issuer parameters associated with the proof.</param> /// <param name="revocationCommitmentIndex">The 0-based index corresponding to the revocation commitment in the proof.</param> /// <param name="proof">The presentation proof.</param> /// <param name="nrProof">The non-revocation proof.</param> /// <exception cref="InvalidUProveArtifactException">Thrown if the proof is invalid.</exception> public void VerifyNonRevocationProof(IssuerParameters ip, int revocationCommitmentIndex, PresentationProof proof, NonRevocationProof nrProof) { Group Gq = ip.Gq; FieldZq Zq = Gq.FieldZq; GroupElement tildeCid = proof.Commitments[revocationCommitmentIndex].TildeC; // T1 = (V Y^-1 Cd^-1)^c' * X^s1 * (tildeCid K)^-s2 * g1^s3 GroupElement T1 = Gq.MultiExponentiate( new GroupElement[] { Accumulator *nrProof.Y.Exponentiate(Zq.NegativeOne) * nrProof.Cd.Exponentiate(Zq.NegativeOne), // TODO: is there a better way to calculate this nrProof.X, tildeCid * RAParameters.K, RAParameters.g1 }, new FieldZqElement[] { nrProof.cPrime, nrProof.s[0], // s1 nrProof.s[1].Negate(), // s2 nrProof.s[2] // s3 }); // T2 = tildeCid^c' g^s1 g1^s4 GroupElement T2 = Gq.MultiExponentiate( new GroupElement[] { tildeCid, RAParameters.g, RAParameters.g1 }, new FieldZqElement[] { nrProof.cPrime, nrProof.s[0], // s1 nrProof.s[3], // s4 }); // T3 = gt^c' Cd^s5 g1^s6 GroupElement T3 = Gq.MultiExponentiate( new GroupElement[] { RAParameters.gt, nrProof.Cd, RAParameters.g1 }, new FieldZqElement[] { nrProof.cPrime, nrProof.s[4], // s5 nrProof.s[5], // s6 }); if (!nrProof.cPrime.Equals(Zq.GetElementFromDigest(RAParameters.ComputeChallenge(tildeCid, nrProof.X, nrProof.Y, nrProof.Cd, T1, T2, T3))) || !nrProof.Y.Equals(nrProof.X.Exponentiate(PrivateKey))) { throw new InvalidUProveArtifactException("Invalid non-revocation proof"); } }
/// <summary> /// Generates a non-revocation proof. /// </summary> /// <param name="rap">The Revocation Authority parameters.</param> /// <param name="rw">The user's revocation witness.</param> /// <param name="tildeCid">The revocation attribute commitment.</param> /// <param name="xid">The revocation attribute.</param> /// <param name="tildeOid">The revocation attribute commitment's opening value.</param> /// <param name="preGenRandom">The optional pre-generated random values for the proof, or <c>null</c>.</param> /// <returns></returns> public static NonRevocationProof GenerateNonRevocationProof(RAParameters rap, RevocationWitness rw, GroupElement tildeCid, FieldZqElement xid, FieldZqElement tildeOid, NonRevocationProofGenerationRandomData preGenRandom = null) { if (rap == null || rw == null || tildeCid == null || xid == null || tildeOid == null) { throw new ArgumentNullException("null input to GenerateNonRevocationProof"); } Group Gq = rap.group; FieldZq Zq = Gq.FieldZq; NonRevocationProofGenerationRandomData rand = preGenRandom; if (rand == null) { rand = NonRevocationProofGenerationRandomData.Generate(Zq); } GroupElement X = rw.W * rap.g.Exponentiate(rand.t1); GroupElement Y = rw.Q * rap.K.Exponentiate(rand.t1); GroupElement Cd = rap.gt.Exponentiate(rw.d) * rap.g1.Exponentiate(rand.t2); FieldZqElement w = rw.d.Invert(); FieldZqElement z = rand.t1 * tildeOid - rand.t2; FieldZqElement zPrime = rand.t2.Negate() * w; GroupElement T1 = Gq.MultiExponentiate(new GroupElement[] { X, tildeCid * rap.K, rap.g1 }, new FieldZqElement[] { rand.k1, rand.k2.Negate(), rand.k3 }); GroupElement T2 = Gq.MultiExponentiate(new GroupElement[] { rap.g, rap.g1 }, new FieldZqElement[] { rand.k1, rand.k4 }); GroupElement T3 = Gq.MultiExponentiate(new GroupElement[] { Cd, rap.g1 }, new FieldZqElement[] { rand.k5, rand.k6 }); FieldZqElement cPrime = Zq.GetElementFromDigest(rap.ComputeChallenge(tildeCid, X, Y, Cd, T1, T2, T3)); FieldZqElement cPrimeNegate = cPrime.Negate(); FieldZqElement s1 = cPrimeNegate * xid + rand.k1; FieldZqElement s2 = cPrimeNegate * rand.t1 + rand.k2; FieldZqElement s3 = cPrimeNegate * z + rand.k3; FieldZqElement s4 = cPrimeNegate * tildeOid + rand.k4; FieldZqElement s5 = cPrimeNegate * w + rand.k5; FieldZqElement s6 = cPrimeNegate * zPrime + rand.k6; rand.Clear(); return(new NonRevocationProof(cPrime, new FieldZqElement[] { s1, s2, s3, s4, s5, s6 }, X, Y, Cd)); }