Beispiel #1
0
        /// <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));
        }
Beispiel #2
0
        /// <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");
            }
        }
Beispiel #3
0
        /// <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));
        }
Beispiel #4
0
        /// <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));
        }
Beispiel #5
0
 /// <summary>
 /// Constructs a RevocationAuthority instance.
 /// </summary>
 /// <param name="raParams">The public parameters.</param>
 /// <param name="privateKey">The private key.</param>
 /// <param name="accumulator">The optional current accumulator. If not present, then the accumulator is reset and the revocation list is considered empty.</param>
 public RevocationAuthority(RAParameters raParams, FieldZqElement privateKey, GroupElement accumulator = null)
 {
     RAParameters = raParams;
     PrivateKey   = privateKey;
     Accumulator  = accumulator;
 }