/* this+=b */ public void Add(FP b) { x.Add(b.x); XES += b.XES; if (XES > FEXCESS) { Reduce(); } }
/* this*=y */ /* Now uses Lazy reduction */ public void Mul(FP2 y) { if ((long)(a.XES + b.XES) * (y.a.XES + y.b.XES) > (long)FP.FEXCESS) { if (a.XES > 1) { a.Reduce(); } if (b.XES > 1) { b.Reduce(); } } DBIG pR = new DBIG(0); BIG C = new BIG(a.x); BIG D = new BIG(y.a.x); pR.UCopy(new BIG(ROM.Modulus)); DBIG A = BIG.Mul(a.x, y.a.x); DBIG B = BIG.Mul(b.x, y.b.x); C.Add(b.x); C.Norm(); D.Add(y.b.x); D.Norm(); DBIG E = BIG.Mul(C, D); DBIG F = new DBIG(A); F.Add(B); B.RSub(pR); A.Add(B); A.Norm(); E.Sub(F); E.Norm(); a.x.Copy(FP.Mod(A)); a.XES = 3; b.x.Copy(FP.Mod(E)); b.XES = 2; }
/** * Constructor * * @param sk the secret key * @param pseudonym the pseudonym with respect to which this signature can be verified * @param ipk the issuer public key * @param msg the message to be signed */ public IdemixPseudonymSignature(BIG sk, IdemixPseudonym pseudonym, IdemixIssuerPublicKey ipk, byte[] msg) { if (sk == null || pseudonym == null || pseudonym.Nym == null || pseudonym.RandNym == null || ipk == null || msg == null) { throw new ArgumentException("Cannot create IdemixPseudonymSignature from null input"); } RAND rng = IdemixUtils.GetRand(); nonce = rng.RandModOrder(); //Construct Zero Knowledge Proof BIG rsk = rng.RandModOrder(); BIG rRNym = rng.RandModOrder(); ECP t = ipk.Hsk.Mul2(rsk, ipk.HRand, rRNym); // create array for proof data that will contain the sign label, 2 ECPs (each of length 2* FIELD_BYTES + 1), the ipk hash and the message byte[] proofData = new byte[0]; proofData = proofData.Append(NYM_SIGN_LABEL.ToBytes()); proofData = proofData.Append(t.ToBytes()); proofData = proofData.Append(pseudonym.Nym.ToBytes()); proofData = proofData.Append(ipk.Hash); proofData = proofData.Append(msg); BIG cvalue = proofData.HashModOrder(); byte[] finalProofData = new byte[0]; finalProofData = finalProofData.Append(cvalue.ToBytes()); finalProofData = finalProofData.Append(nonce.ToBytes()); proofC = finalProofData.HashModOrder(); proofSSk = new BIG(rsk); proofSSk.Add(BIG.ModMul(proofC, sk, IdemixUtils.GROUP_ORDER)); proofSSk.Mod(IdemixUtils.GROUP_ORDER); proofSRNym = new BIG(rRNym); proofSRNym.Add(BIG.ModMul(proofC, pseudonym.RandNym, IdemixUtils.GROUP_ORDER)); proofSRNym.Mod(IdemixUtils.GROUP_ORDER); }
/* return this/c */ public virtual BIG Div(BIG c) { int d, k = 0; DBIG m = new DBIG(c); DBIG dr = new DBIG(0); BIG r = new BIG(0); BIG a = new BIG(0); BIG e = new BIG(1); Norm(); while (Comp(this, m) >= 0) { e.FShl(1); m.Shl(1); k++; } while (k > 0) { m.Shr(1); e.Shr(1); dr.Copy(this); dr.Sub(m); dr.Norm(); d = (int)(1 - ((dr.w[BIG.DNLEN - 1] >> (BIG.CHUNK - 1)) & 1)); CMove(dr, d); r.Copy(a); r.Add(e); r.Norm(); a.CMove(r, d); k--; } return(a); }
/** * Create a new IdemixSignature by proving knowledge of a credential * * @param c the credential used to create an idemix signature * @param sk the signer's secret key * @param pseudonym a pseudonym of the signer * @param ipk the issuer public key * @param disclosure a bool-array that steers the disclosure of attributes * @param msg the message to be signed * @param rhIndex the index of the attribute that represents the revocation handle * @param cri the credential revocation information that allows the signer to prove non-revocation */ public IdemixSignature(IdemixCredential c, BIG sk, IdemixPseudonym pseudonym, IdemixIssuerPublicKey ipk, bool[] disclosure, byte[] msg, int rhIndex, CredentialRevocationInformation cri) { if (c == null || sk == null || pseudonym == null || pseudonym.Nym == null || pseudonym.RandNym == null || ipk == null || disclosure == null || msg == null || cri == null) { throw new ArgumentException("Cannot construct idemix signature from null input"); } if (disclosure.Length != c.Attrs.Length) { throw new ArgumentException("Disclosure length must be the same as the number of attributes"); } if (cri.RevocationAlg >= Enum.GetValues(typeof(RevocationAlgorithm)).Length) { throw new ArgumentException("CRI specifies unknown revocation algorithm"); } if (cri.RevocationAlg != (int)RevocationAlgorithm.ALG_NO_REVOCATION && disclosure[rhIndex]) { throw new ArgumentException("Attribute " + rhIndex + " is disclosed but also used a revocation handle attribute, which should remain hidden"); } RevocationAlgorithm revocationAlgorithm = (RevocationAlgorithm)cri.RevocationAlg; int[] hiddenIndices = HiddenIndices(disclosure); RAND rng = IdemixUtils.GetRand(); // Start signature BIG r1 = rng.RandModOrder(); BIG r2 = rng.RandModOrder(); BIG r3 = new BIG(r1); r3.InvModp(IdemixUtils.GROUP_ORDER); nonce = rng.RandModOrder(); aPrime = PAIR.G1Mul(c.A, r1); aBar = PAIR.G1Mul(c.B, r1); aBar.Sub(PAIR.G1Mul(aPrime, c.E)); bPrime = PAIR.G1Mul(c.B, r1); bPrime.Sub(PAIR.G1Mul(ipk.HRand, r2)); BIG sPrime = new BIG(c.S); sPrime.Add(BIG.ModNeg(BIG.ModMul(r2, r3, IdemixUtils.GROUP_ORDER), IdemixUtils.GROUP_ORDER)); sPrime.Mod(IdemixUtils.GROUP_ORDER); //Construct Zero Knowledge Proof BIG rsk = rng.RandModOrder(); BIG re = rng.RandModOrder(); BIG rR2 = rng.RandModOrder(); BIG rR3 = rng.RandModOrder(); BIG rSPrime = rng.RandModOrder(); BIG rRNym = rng.RandModOrder(); BIG[] rAttrs = new BIG[hiddenIndices.Length]; for (int i = 0; i < hiddenIndices.Length; i++) { rAttrs[i] = rng.RandModOrder(); } // Compute non-revoked proof INonRevocationProver prover = NonRevocationProver.GetNonRevocationProver(revocationAlgorithm); int hiddenRHIndex = Array.IndexOf(hiddenIndices, rhIndex); if (hiddenRHIndex < 0) { // rhIndex is not present, set to last index position hiddenRHIndex = hiddenIndices.Length; } byte[] nonRevokedProofHashData = prover.GetFSContribution(BIG.FromBytes(c.Attrs[rhIndex]), rAttrs[hiddenRHIndex], cri); if (nonRevokedProofHashData == null) { throw new Exception("Failed to compute non-revoked proof"); } ECP t1 = aPrime.Mul2(re, ipk.HRand, rR2); ECP t2 = PAIR.G1Mul(ipk.HRand, rSPrime); t2.Add(bPrime.Mul2(rR3, ipk.Hsk, rsk)); for (int i = 0; i < hiddenIndices.Length / 2; i++) { t2.Add(ipk.HAttrs[hiddenIndices[2 * i]].Mul2(rAttrs[2 * i], ipk.HAttrs[hiddenIndices[2 * i + 1]], rAttrs[2 * i + 1])); } if (hiddenIndices.Length % 2 != 0) { t2.Add(PAIR.G1Mul(ipk.HAttrs[hiddenIndices[hiddenIndices.Length - 1]], rAttrs[hiddenIndices.Length - 1])); } ECP t3 = ipk.Hsk.Mul2(rsk, ipk.HRand, rRNym); // 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(pseudonym.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()); proofC = finalProofData.HashModOrder(); proofSSk = rsk.ModAdd(BIG.ModMul(proofC, sk, IdemixUtils.GROUP_ORDER), IdemixUtils.GROUP_ORDER); proofSE = re.ModSub(BIG.ModMul(proofC, c.E, IdemixUtils.GROUP_ORDER), IdemixUtils.GROUP_ORDER); proofSR2 = rR2.ModAdd(BIG.ModMul(proofC, r2, IdemixUtils.GROUP_ORDER), IdemixUtils.GROUP_ORDER); proofSR3 = rR3.ModSub(BIG.ModMul(proofC, r3, IdemixUtils.GROUP_ORDER), IdemixUtils.GROUP_ORDER); proofSSPrime = rSPrime.ModAdd(BIG.ModMul(proofC, sPrime, IdemixUtils.GROUP_ORDER), IdemixUtils.GROUP_ORDER); proofSRNym = rRNym.ModAdd(BIG.ModMul(proofC, pseudonym.RandNym, IdemixUtils.GROUP_ORDER), IdemixUtils.GROUP_ORDER); nym = new ECP(); nym.Copy(pseudonym.Nym); proofSAttrs = new BIG[hiddenIndices.Length]; for (int i = 0; i < hiddenIndices.Length; i++) { proofSAttrs[i] = new BIG(rAttrs[i]); proofSAttrs[i].Add(BIG.ModMul(proofC, BIG.FromBytes(c.Attrs[hiddenIndices[i]]), IdemixUtils.GROUP_ORDER)); proofSAttrs[i].Mod(IdemixUtils.GROUP_ORDER); } // include non-revocation proof in signature revocationPk = cri.EpochPk; revocationPKSig = cri.EpochPkSig.ToByteArray(); epoch = cri.Epoch; nonRevocationProof = prover.GetNonRevocationProof(proofC); }
/// <summary> ///************** 64-bit specific *********************** </summary> /* reduce a DBIG to a BIG using the appropriate form of the modulus */ public static BIG Mod(DBIG d) { if (MODTYPE == PSEUDO_MERSENNE) { BIG b; long v, tw; BIG t = d.Split(MODBITS); b = new BIG(d); v = t.PMul(unchecked ((int)ROM.MConst)); t.Add(b); t.Norm(); tw = t.w[BIG.NLEN - 1]; t.w[BIG.NLEN - 1] &= FP.TMASK; t.w[0] += (ROM.MConst * ((tw >> TBITS) + (v << (BIG.BASEBITS - TBITS)))); t.Norm(); return(t); } if (FP.MODTYPE == MONTGOMERY_FRIENDLY) { BIG b; long[] cr = new long[2]; for (int i = 0; i < BIG.NLEN; i++) { cr = BIG.MulAdd(d.w[i], ROM.MConst - 1, d.w[i], d.w[BIG.NLEN + i - 1]); d.w[BIG.NLEN + i] += cr[0]; d.w[BIG.NLEN + i - 1] = cr[1]; } b = new BIG(0); for (int i = 0; i < BIG.NLEN; i++) { b.w[i] = d.w[BIG.NLEN + i]; } b.Norm(); return(b); } if (MODTYPE == GENERALISED_MERSENNE) { // GoldiLocks Only BIG b; BIG t = d.Split(MODBITS); b = new BIG(d); b.Add(t); DBIG dd = new DBIG(t); dd.Shl(MODBITS / 2); BIG tt = dd.Split(MODBITS); BIG lo = new BIG(dd); b.Add(tt); b.Add(lo); b.Norm(); tt.Shl(MODBITS / 2); b.Add(tt); long carry = b.w[BIG.NLEN - 1] >> TBITS; b.w[BIG.NLEN - 1] &= FP.TMASK; b.w[0] += carry; b.w[224 / BIG.BASEBITS] += carry << (224 % BIG.BASEBITS); b.Norm(); return(b); } if (MODTYPE == NOT_SPECIAL) { return(BIG.Monty(new BIG(ROM.Modulus), ROM.MConst, d)); } return(new BIG(0)); }