/** * Verify this signature * * @param disclosure an array indicating which attributes it expects to be disclosed * @param ipk the issuer public key * @param msg the message that should be signed in this signature * @param attributeValues BIG array where attributeValues[i] contains the desired attribute value for the i-th attribute if its disclosed * @param rhIndex index of the attribute that represents the revocation-handle * @param revPk the long term public key used to authenticate CRIs * @param epoch monotonically increasing counter representing a time window * @return true iff valid */ // ReSharper disable once ParameterHidesMember public bool Verify(bool[] disclosure, IdemixIssuerPublicKey ipk, byte[] msg, BIG[] attributeValues, int rhIndex, KeyPair revPk, int epoch) { if (disclosure == null || ipk == null || msg == null || attributeValues == null || attributeValues.Length != ipk.AttributeNames.Length || disclosure.Length != ipk.AttributeNames.Length) { return(false); } for (int i = 0; i < ipk.AttributeNames.Length; i++) { if (disclosure[i] && attributeValues[i] == null) { return(false); } } int[] hiddenIndices = HiddenIndices(disclosure); if (proofSAttrs.Length != hiddenIndices.Length) { return(false); } if (aPrime.IsInfinity()) { return(false); } if (nonRevocationProof.RevocationAlg >= Enum.GetValues(typeof(RevocationAlgorithm)).Length) { throw new ArgumentException("CRI specifies unknown revocation algorithm"); } RevocationAlgorithm revocationAlgorithm = (RevocationAlgorithm)nonRevocationProof.RevocationAlg; if (disclosure[rhIndex]) { throw new ArgumentException("Attribute " + rhIndex + " is disclosed but also used a revocation handle attribute, which should remain hidden"); } // Verify EpochPK if (!RevocationAuthority.VerifyEpochPK(revPk, revocationPk, revocationPKSig, epoch, revocationAlgorithm)) { // Signature is based on an invalid revocation epoch public key return(false); } FP12 temp1 = PAIR.Ate(ipk.W, aPrime); FP12 temp2 = PAIR.Ate(IdemixUtils.GenG2, aBar); temp2.Inverse(); temp1.mul(temp2); if (!PAIR.FExp(temp1).IsUnity()) { return(false); } ECP t1 = aPrime.Mul2(proofSE, ipk.HRand, proofSR2); ECP temp = new ECP(); temp.Copy(aBar); temp.Sub(bPrime); t1.Sub(PAIR.G1Mul(temp, proofC)); ECP t2 = PAIR.G1Mul(ipk.HRand, proofSSPrime); t2.Add(bPrime.Mul2(proofSR3, ipk.Hsk, proofSSk)); for (int i = 0; i < hiddenIndices.Length / 2; i++) { t2.Add(ipk.HAttrs[hiddenIndices[2 * i]].Mul2(proofSAttrs[2 * i], ipk.HAttrs[hiddenIndices[2 * i + 1]], proofSAttrs[2 * i + 1])); } if (hiddenIndices.Length % 2 != 0) { t2.Add(PAIR.G1Mul(ipk.HAttrs[hiddenIndices[hiddenIndices.Length - 1]], proofSAttrs[hiddenIndices.Length - 1])); } temp = new ECP(); temp.Copy(IdemixUtils.GenG1); for (int i = 0; i < disclosure.Length; i++) { if (disclosure[i]) { temp.Add(PAIR.G1Mul(ipk.HAttrs[i], attributeValues[i])); } } t2.Add(PAIR.G1Mul(temp, proofC)); ECP t3 = ipk.Hsk.Mul2(proofSSk, ipk.HRand, proofSRNym); t3.Sub(nym.Mul(proofC)); // Check with non-revoked-verifier INonRevocationVerifier nonRevokedVerifier = NonRevocationVerifier.GetNonRevocationVerifier(revocationAlgorithm); int hiddenRHIndex = Array.IndexOf(hiddenIndices, rhIndex); if (hiddenRHIndex < 0) { // rhIndex is not present, set to last index position hiddenRHIndex = hiddenIndices.Length; } BIG proofSRh = proofSAttrs[hiddenRHIndex]; byte[] nonRevokedProofBytes = nonRevokedVerifier.RecomputeFSContribution(nonRevocationProof, proofC, revocationPk.ToECP2(), proofSRh); if (nonRevokedProofBytes == null) { return(false); } // create proofData such that it can contain the sign label, 7 elements in G1 (each of size 2*FIELD_BYTES+1), // the ipk hash, the disclosure array, and the message byte[] proofData = new byte[0]; proofData = proofData.Append(SIGN_LABEL.ToBytes()); proofData = proofData.Append(t1.ToBytes()); proofData = proofData.Append(t2.ToBytes()); proofData = proofData.Append(t3.ToBytes()); proofData = proofData.Append(aPrime.ToBytes()); proofData = proofData.Append(aBar.ToBytes()); proofData = proofData.Append(bPrime.ToBytes()); proofData = proofData.Append(nym.ToBytes()); proofData = proofData.Append(ipk.Hash); proofData = proofData.Append(disclosure); proofData = proofData.Append(msg); BIG cvalue = proofData.HashModOrder(); byte[] finalProofData = new byte[0]; finalProofData = finalProofData.Append(cvalue.ToBytes()); finalProofData = finalProofData.Append(nonce.ToBytes()); byte[] hashedProofData = finalProofData.HashModOrder().ToBytes(); return(Enumerable.SequenceEqual(proofC.ToBytes(), hashedProofData)); }
/* final exponentiation - keep separate for multi-pairings and to avoid thrashing stack */ public static FP12 FExp(FP12 m) { FP2 f = new FP2(new BIG(ROM.Fra), new BIG(ROM.Frb)); BIG x = new BIG(ROM.CURVE_Bnx); FP12 r = new FP12(m); /* Easy part of final exp */ FP12 lv = new FP12(r); lv.Inverse(); r.Conj(); r.mul(lv); lv.Copy(r); r.Frob(f); r.Frob(f); r.mul(lv); /* Hard part of final exp */ if (ECP.CURVE_PAIRING_TYPE == ECP.BN) { FP12 x0, x1, x2, x3, x4, x5; lv.Copy(r); lv.Frob(f); x0 = new FP12(lv); x0.Frob(f); lv.mul(r); x0.mul(lv); x0.Frob(f); x1 = new FP12(r); x1.Conj(); x4 = r.Pow(x); if (ECP.SIGN_OF_X == ECP.POSITIVEX) { x4.Conj(); } x3 = new FP12(x4); x3.Frob(f); x2 = x4.Pow(x); if (ECP.SIGN_OF_X == ECP.POSITIVEX) { x2.Conj(); } x5 = new FP12(x2); x5.Conj(); lv = x2.Pow(x); if (ECP.SIGN_OF_X == ECP.POSITIVEX) { lv.Conj(); } x2.Frob(f); r.Copy(x2); r.Conj(); x4.mul(r); x2.Frob(f); r.Copy(lv); r.Frob(f); lv.mul(r); lv.USqr(); lv.mul(x4); lv.mul(x5); r.Copy(x3); r.mul(x5); r.mul(lv); lv.mul(x2); r.USqr(); r.mul(lv); r.USqr(); lv.Copy(r); lv.mul(x1); r.mul(x0); lv.USqr(); r.mul(lv); r.Reduce(); } else { FP12 y0, y1, y2, y3; // Ghamman & Fouotsa Method y0 = new FP12(r); y0.USqr(); y1 = y0.Pow(x); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { y1.Conj(); } x.FShr(1); y2 = y1.Pow(x); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { y2.Conj(); } x.FShl(1); y3 = new FP12(r); y3.Conj(); y1.mul(y3); y1.Conj(); y1.mul(y2); y2 = y1.Pow(x); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { y2.Conj(); } y3 = y2.Pow(x); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { y3.Conj(); } y1.Conj(); y3.mul(y1); y1.Conj(); y1.Frob(f); y1.Frob(f); y1.Frob(f); y2.Frob(f); y2.Frob(f); y1.mul(y2); y2 = y3.Pow(x); if (ECP.SIGN_OF_X == ECP.NEGATIVEX) { y2.Conj(); } y2.mul(y0); y2.mul(r); y1.mul(y2); y2.Copy(y3); y2.Frob(f); y1.mul(y2); r.Copy(y1); r.Reduce(); } return(r); }