/// <summary> /// Updates the revocation witness for a user, either adding or removing a revoked value. /// </summary> /// <param name="rap">The Revocation Authority parameters.</param> /// <param name="xid">The revocation attribute value <c>xid</c>.</param> /// <param name="revoked">The attribute value to added to the accumulator, or <c>null</c>.</param> /// <param name="unrevoked">The attribute value to deleted to the accumulator, or <c>null</c>.</param> /// <param name="oldAccumulator">The old accumulator value <c>V</c>. If <c>null</c>, then the accumulator is freshly calculated.</param> /// <param name="updatedAccumulator">The old accumulator value <c>V'</c>.</param> /// <param name="oldWitness">The old witness values. If <c>null</c>, then the witness is freshly calculated.</param> /// <returns></returns> public static RevocationWitness UpdateWitness(RAParameters rap, FieldZqElement xid, FieldZqElement revoked, FieldZqElement unrevoked, GroupElement oldAccumulator, GroupElement updatedAccumulator, RevocationWitness oldWitness) { // TODO: implement batch updates if (revoked != null && unrevoked != null) { throw new ArgumentException("only one of revoked and unrevoked can be non-null"); } FieldZqElement one = rap.group.FieldZq.One; if (oldAccumulator == null) { // set the accumulator value for an empty revocation set oldAccumulator = rap.gt; } if (oldWitness == null) { oldWitness = new RevocationWitness(rap.group.FieldZq.One, rap.group.Identity, rap.group.Identity); } if (revoked == null && unrevoked == null) { // nothing to do return(oldWitness); } FieldZqElement dPrime = null; GroupElement WPrime = null; GroupElement QPrime = null; FieldZqElement xDiff = one; // add values to witness if (revoked != null) { xDiff = (revoked - xid); dPrime = oldWitness.d * xDiff; WPrime = oldAccumulator * oldWitness.W.Exponentiate(xDiff); } xDiff = one; // remove values from witness if (unrevoked != null) { xDiff = (unrevoked - xid).Invert(); dPrime = oldWitness.d * xDiff; WPrime = updatedAccumulator.Exponentiate(one.Negate()) * oldWitness.W.Exponentiate(xDiff); } // update QPrime value QPrime = updatedAccumulator * WPrime.Exponentiate(xid.Negate()) * rap.gt.Exponentiate(dPrime.Negate()); return(new RevocationWitness(dPrime, WPrime, QPrime)); }
/// <summary> /// Computes the non-revocation proof. /// </summary> /// <param name="ip">The Issuer parameters associated with the presented U-Prove token.</param> /// <param name="rap">The Revocation Authority parameters.</param> /// <param name="witness">The user non-revocation witness.</param> /// <param name="commitmentIndex">The 0-based index of the revocation commitment in the attribute commitments.</param> /// <param name="presentationProof">The presentation proof generated with the U-Prove token.</param> /// <param name="cpv">The commitment private values generated when presenting the U-Prove token.</param> /// <param name="revocationIndex">The 1-based index of the revocation attribute in the U-Prove token.</param> /// <param name="attributes">The token attributes.</param> /// <returns>A non-revocation proof.</returns> public static NonRevocationProof GenerateNonRevocationProof(IssuerParameters ip, RAParameters rap, RevocationWitness witness, int commitmentIndex, PresentationProof presentationProof, CommitmentPrivateValues cpv, int revocationIndex, byte[][] attributes) { if (revocationIndex <= 0) { throw new ArgumentException("revocationIndex must be positive: " + revocationIndex); } GroupElement tildeCid = presentationProof.Commitments[commitmentIndex].TildeC; FieldZqElement xid = ProtocolHelper.ComputeXi(ip, revocationIndex - 1, attributes[revocationIndex - 1]); FieldZqElement tildeOid = cpv.TildeO[commitmentIndex]; return(GenerateNonRevocationProof(rap, witness, tildeCid, xid, tildeOid)); }
/// <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)); }