in UProveCrypto/CollaborativeIssuance.cs [451:568]
public static GroupElement VerifyProof(IssuerPreIssuanceParameters ipip, PreIssuanceProof proof, byte[] message)
{
// Validate paramters first
ipip.Validate();
IssuerParameters ip = ipip.IP;
FieldZq Zq = ip.Zq;
Group Gq = ip.Gq;
List<GroupElement> bases = new List<GroupElement>();
List<FieldZqElement> exponents = new List<FieldZqElement>();
GroupElement[] C = null;
GroupElement[] CPrime = null;
FieldZqElement c = Zq.GetElementFromDigest(proof.c);
if (ipip.HasCarryOverAttributes)
{
// validate presentation proof
int[] disclosed = new int[] {};
VerifierPresentationProtocolParameters vppp = new VerifierPresentationProtocolParameters(ipip.SourceIP, disclosed, message, ipip.Tokens);
vppp.Committed = ipip.Corig;
try
{
proof.presentation.Verify(vppp);
}
catch (InvalidUProveArtifactException e)
{
throw new InvalidUProveArtifactException("Failed to verify pre-Issuance proof, presentation proof " + 0 + " failed to verify ("+e.ToString()+")");
}
// extract the commitments
C = new GroupElement[ipip.C.Length];
CPrime = new GroupElement[ipip.C.Length];
for (int i = 0; i < C.Length; i++)
{
C[i] = proof.presentation.Commitments[i].TildeC;
// Compute the CPrime[i] values.
bases = new List<GroupElement>();
exponents = new List<FieldZqElement>();
bases.Add(C[i]);
exponents.Add(c);
bases.Add(Gq.G);
exponents.Add(proof.GetResponse("sx" + ipip.C[i]));
bases.Add(ip.G[1]);
exponents.Add(proof.GetResponse("sR" + i));
CPrime[i] = Gq.MultiExponentiate(bases.ToArray(), exponents.ToArray());
//Debug.WriteLine("CPrime[i] = " + BitConverter.ToString(CPrime[i].GetEncoded()));
}
}
// Compute D'
FieldZqElement sd = proof.GetResponse("sD");
GroupElement DPrime = Gq.MultiExponentiate(proof.Ch0, proof.h0, c, c.Negate()); // TODO: add Inverse() to group element to simplify this
DPrime = DPrime.Multiply(Gq.G.Exponentiate(sd));
//Debug.WriteLine("DPrime = " + BitConverter.ToString(DPrime.GetEncoded()));
// Compute T'
FieldZqElement sBeta0 = proof.GetResponse("sBeta0");
GroupElement TPrime = Gq.MultiExponentiate(proof.Ch0, proof.CGamma, c, sBeta0);
//Debug.WriteLine("TPrime = " + BitConverter.ToString(TPrime.GetEncoded()));
// Compute gammaK (product of known attributes)
bases = new List<GroupElement>();
exponents = new List<FieldZqElement>();
int t = ip.G.Length-1;
FieldZqElement xt = ProtocolHelper.ComputeXt(ip, ipip.TI, ipip.DeviceProtected);
bases.Add(ip.G[0]);
exponents.Add(ip.Zq.One);
bases.Add(ip.G[t]);
exponents.Add(xt); // gammaK = g0*(gt^xt)
for (int i = 1; i < ip.G.Length - 1; i++)
{
if (ipip.K.Contains(i))
{
FieldZqElement xi = ProtocolHelper.ComputeXi(ip, i-1, ipip.Attributes[i-1]);
bases.Add(ip.G[i]);
exponents.Add(xi);
}
}
GroupElement gammaK = Gq.MultiExponentiate(bases.ToArray(), exponents.ToArray());
// Compute Cgamma'
bases = new List<GroupElement>();
exponents = new List<FieldZqElement>();
bases.Add(proof.CGamma);
exponents.Add(c);
bases.Add(gammaK);
exponents.Add(c.Negate()); // TODO: do with one exp; i.e., (CGamma/gammaK)^c
for (int i = 1; i < ip.G.Length - 1; i++)
{
if (!ipip.K.Contains(i))
{
FieldZqElement sxi = proof.GetResponse("sx" + i);
bases.Add(ip.G[i]);
exponents.Add(sxi);
}
}
bases.Add(Gq.G);
exponents.Add(proof.GetResponse("sRho"));
GroupElement CgammaPrime = Gq.MultiExponentiate(bases.ToArray(), exponents.ToArray());
// TODO: if deviceprotected multiply device base/response.
//Debug.WriteLine("CgammaPrime = " + BitConverter.ToString(CgammaPrime.GetEncoded()));
// Recompute challenge
byte[] cPrime = ComputeChallenge(ip, proof.h0, proof.CGamma, proof.Ch0, C, DPrime, CgammaPrime, TPrime, CPrime, message);
//Debug.WriteLine("c' = " + BitConverter.ToString(cPrime));
if (!cPrime.SequenceEqual<byte>(proof.c))
{
throw new InvalidUProveArtifactException("invalid proof");
}
return proof.h0;
}