in UProveCrypto/PresentationProof.cs [687:831]
public void Verify(IssuerParameters ip, int[] disclosed, int[] committed, int pseudonymAttribIndex, GroupElement gs, byte[] message, byte[] messageD, UProveToken upt)
{
try
{
// make sure disclosed list is sorted
if (disclosed == null)
{
// can't be null later, so make it an empty array
disclosed = new int[] { };
}
Array.Sort(disclosed);
Group Gq = ip.Gq;
int n = ip.E.Length;
bool presentPseudonym = false;
if (gs != null && pseudonymAttribIndex != 0)
{
if (pseudonymAttribIndex < 1 || (pseudonymAttribIndex > n && pseudonymAttribIndex != DeviceAttributeIndex))
{
throw new ArgumentException("pseudonymAttribIndex must be between 1 and " + n + " (inclusive)");
}
if (disclosed.Contains(pseudonymAttribIndex))
{
throw new ArgumentException("pseudonymAttribIndex cannot be in the disclosed attribute array");
}
presentPseudonym = true;
}
else // no nym
{
pseudonymAttribIndex = 0;
}
bool verifyCommitments = (committed != null && committed.Length > 0);
if (verifyCommitments)
{
Array.Sort(committed);
}
ProtocolHelper.VerifyTokenSignature(ip, upt);
int dArraySize = disclosed.Length + 2;
GroupElement[] dBases = new GroupElement[dArraySize];
FieldZqElement[] dExponents = new FieldZqElement[dArraySize];
dBases[0] = ip.G[0]; dExponents[0] = ip.Zq.One; // g0^1
dBases[1] = ip.G[n + 1]; dExponents[1] = ProtocolHelper.ComputeXt(ip, upt.TI, upt.IsDeviceProtected); // gt^xt
FieldZqElement[] disclosedX = new FieldZqElement[disclosedAttributes.Length];
int aPreImageArraySize = 2 + (n - disclosed.Length) + (upt.IsDeviceProtected ? 1 : 0);
GroupElement[] aPreImageBases = new GroupElement[aPreImageArraySize];
FieldZqElement[] aPreImageExponents = new FieldZqElement[aPreImageArraySize];
// aPreImage arrays' index 0 values depend on the dArray values; they will be filled out later
aPreImageBases[1] = upt.H; aPreImageExponents[1] = this.r[0]; // h^r0
int dIndex = 0;
int uIndex = 1;
int cIndex = 0;
int pseudonymResponseIndex = 0;
int[] commitmentResponseIndices = verifyCommitments ? new int[committed.Length] : null;
for (int i = 1; i <= n; i++)
{
if (disclosed.Contains(i))
{
disclosedX[dIndex] = ProtocolHelper.ComputeXi(ip, i - 1, disclosedAttributes[dIndex]);
dBases[dIndex + 2] = ip.G[i];
dExponents[dIndex + 2] = disclosedX[dIndex];
dIndex++;
}
else
{
aPreImageBases[uIndex + 1] = ip.G[i]; aPreImageExponents[uIndex + 1] = this.r[uIndex]; // gi^ri
if (presentPseudonym)
{
if (pseudonymAttribIndex == i)
{
pseudonymResponseIndex = uIndex;
}
}
if (verifyCommitments)
{
if (committed.Contains(i))
{
// remember which response correspond to which commitment
commitmentResponseIndices[cIndex] = uIndex;
cIndex++;
}
}
uIndex++;
}
}
if (pseudonymAttribIndex == DeviceAttributeIndex)
{
pseudonymResponseIndex = this.r.Length - 1; // r_d is the last response in the array
}
byte[] unused; // verifier doesn't use the returned message for device
FieldZqElement c = ProtocolHelper.GenerateChallenge(ip, upt, this.a, pseudonymAttribIndex, this.ap, this.ps, message, messageD, disclosed, disclosedX, committed, this.Commitments, out unused);
aPreImageBases[0] = Gq.MultiExponentiate(dBases, dExponents); aPreImageExponents[0] = c.Negate(); // g0.gt^xt.Product[gi^xi]_(for disclosed i)
if (upt.IsDeviceProtected)
{
aPreImageBases[aPreImageArraySize - 1] = ip.Gd; aPreImageExponents[aPreImageArraySize - 1] = this.r[this.r.Length - 1]; // gd^rd
}
HashFunction hash = ip.HashFunction;
hash.Hash(Gq.MultiExponentiate(aPreImageBases, aPreImageExponents));
if (!this.a.SequenceEqual(hash.Digest))
{
throw new InvalidUProveArtifactException("Invalid presentation proof");
}
if (presentPseudonym)
{
hash.Hash(Gq.MultiExponentiate(new GroupElement[] { ps, gs }, new FieldZqElement[] { c, r[pseudonymResponseIndex] }));
if (!this.ap.SequenceEqual(hash.Digest))
{
throw new InvalidUProveArtifactException("Invalid pseudonym");
}
}
if (verifyCommitments)
{
GroupElement[] cBases = new GroupElement[3];
FieldZqElement[] cExponents = new FieldZqElement[3];
cBases[1] = Gq.G;
cBases[2] = ip.G[1];
cExponents[0] = c;
for (int i = 0; i < commitmentResponseIndices.Length; i++)
{
CommitmentValues commitment = this.Commitments[i];
cBases[0] = commitment.TildeC;
cExponents[1] = this.r[commitmentResponseIndices[i]];
cExponents[2] = commitment.TildeR;
hash.Hash(Gq.MultiExponentiate(cBases, cExponents));
if (!commitment.TildeA.SequenceEqual(hash.Digest))
{
throw new InvalidUProveArtifactException("Invalid commitment " + committed[i]);
}
}
}
}
catch (ArgumentException)
{
throw new InvalidUProveArtifactException("Invalid presentation proof");
}
catch (IndexOutOfRangeException)
{
throw new InvalidUProveArtifactException("Invalid presentation proof");
}
}