/** * Takes input BIGs a, b, m and returns a+b modulo m * * @param a the first BIG to add * @param b the second BIG to add * @param m the modulus * @return Returns a+b (mod m) */ public static BIG ModAdd(this BIG a, BIG b, BIG m) { BIG c = a.Plus(b); c.Mod(m); return(c); }
/** * hashModOrder hashes bytes to an amcl.BIG * in 0, ..., GROUP_ORDER * * @param data the data to be hashed * @return a BIG in 0, ..., GROUP_ORDER-1 that is the hash of the data */ public static BIG HashModOrder(this byte[] data) { HASH256 hash = new HASH256(); foreach (byte b in data) { hash.Process(b); } byte[] hasheddata = (byte[])(Array)hash.Hash(); BIG ret = BIG.FromBytes(hasheddata); ret.Mod(GROUP_ORDER); return(ret); }
/** * Constructor creating a new credential * * @param key the issuer key pair * @param m a credential request * @param attrs an array of attribute values as BIG */ public IdemixCredential(IdemixIssuerKey key, IdemixCredRequest m, BIG[] attrs) { if (key == null || key.Ipk == null || m == null || attrs == null) { throw new ArgumentException("Cannot create idemix credential from null input"); } if (attrs.Length != key.Ipk.AttributeNames.Length) { throw new ArgumentException("Amount of attribute values does not match amount of attributes in issuer public key"); } RAND rng = IdemixUtils.GetRand(); // Place a BBS+ signature on the user key and the attribute values // (For BBS+, see "Constant-Size Dynamic k-TAA" by Man Ho Au, Willy Susilo, Yi Mu) E = rng.RandModOrder(); S = rng.RandModOrder(); B = new ECP(); B.Copy(IdemixUtils.GenG1); B.Add(m.Nym); B.Add(key.Ipk.HRand.Mul(S)); for (int i = 0; i < attrs.Length / 2; i++) { B.Add(key.Ipk.HAttrs[2 * i].Mul2(attrs[2 * i], key.Ipk.HAttrs[2 * i + 1], attrs[2 * i + 1])); } if (attrs.Length % 2 != 0) { B.Add(key.Ipk.HAttrs[attrs.Length - 1].Mul(attrs[attrs.Length - 1])); } BIG exp = new BIG(key.Isk).Plus(E); exp.Mod(IdemixUtils.GROUP_ORDER); exp.InvModp(IdemixUtils.GROUP_ORDER); A = B.Mul(exp); Attrs = new byte[attrs.Length][]; for (int i = 0; i < attrs.Length; i++) { byte[] b = new byte[IdemixUtils.FIELD_BYTES]; attrs[i].ToBytes(b); Attrs[i] = b; } }
public FP4 ComPow(BIG e, BIG r) { FP12 g1 = new FP12(0); FP12 g2 = new FP12(0); FP2 f = new FP2(new BIG(ROM.Fra), new BIG(ROM.Frb)); BIG q = new BIG(ROM.Modulus); BIG m = new BIG(q); m.Mod(r); BIG a = new BIG(e); a.Mod(m); BIG b = new BIG(e); b.Div(m); g1.Copy(this); g2.Copy(this); FP4 c = g1.Trace(); if (b.IsZilch()) { c = c.Xtr_Pow(e); return(c); } g2.Frob(f); FP4 cp = g2.Trace(); g1.Conj(); g2.mul(g1); FP4 cpm1 = g2.Trace(); g2.mul(g1); FP4 cpm2 = g2.Trace(); c = c.Xtr_Pow2(cp, cpm1, cpm2, a, b); return(c); }
/** * Constructor * * @param sk the secret key of the user * @param issuerNonce a nonce * @param ipk the issuer public key */ public IdemixCredRequest(BIG sk, BIG issuerNonce, IdemixIssuerPublicKey ipk) { if (sk == null) { throw new ArgumentException("Cannot create idemix credrequest from null Secret Key input"); } if (issuerNonce == null) { throw new ArgumentException("Cannot create idemix credrequest from null issuer nonce input"); } if (ipk == null) { throw new ArgumentException("Cannot create idemix credrequest from null Issuer Public Key input"); } RAND rng = IdemixUtils.GetRand(); Nym = ipk.Hsk.Mul(sk); this.issuerNonce = new BIG(issuerNonce); // Create Zero Knowledge Proof BIG rsk = rng.RandModOrder(); ECP t = ipk.Hsk.Mul(rsk); // Make proofData: total 3 elements of G1, each 2*FIELD_BYTES+1 (ECP), // plus length of String array, // plus one BIG byte[] proofData = new byte[0]; proofData = proofData.Append(CREDREQUEST_LABEL.ToBytes()); proofData = proofData.Append(t.ToBytes()); proofData = proofData.Append(ipk.Hsk.ToBytes()); proofData = proofData.Append(Nym.ToBytes()); proofData = proofData.Append(issuerNonce.ToBytes()); proofData = proofData.Append(ipk.Hash); proofC = proofData.HashModOrder(); // Compute proofS = ... proofS = BIG.ModMul(proofC, sk, IdemixUtils.GROUP_ORDER).Plus(rsk); proofS.Mod(IdemixUtils.GROUP_ORDER); }
/** * 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); }
/** * 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); }
/* reduce this mod Modulus */ public void Reduce() { x.Mod(new BIG(ROM.Modulus)); XES = 1; }
/** * Constructor * * @param attributeNames the names of attributes as String array (must not contain duplicates) * @param isk the issuer secret key */ public IdemixIssuerPublicKey(string[] attributeNames, BIG isk) { // check null input if (attributeNames == null || isk == null) { throw new ArgumentException("Cannot create IdemixIssuerPublicKey from null input"); } // Checking if attribute names are unique HashSet <string> map = new HashSet <string>(); foreach (string item in attributeNames) { if (map.Contains(item)) { throw new ArgumentException("Attribute " + item + " appears multiple times in attributeNames"); } map.Add(item); } RAND rng = IdemixUtils.GetRand(); // Attaching Attribute Names array correctly AttributeNames = attributeNames; // Computing W value W = IdemixUtils.GenG2.Mul(isk); // Filling up HAttributes correctly in Issuer Public Key, length // preserving HAttrs = new ECP[attributeNames.Length]; for (int i = 0; i < attributeNames.Length; i++) { HAttrs[i] = IdemixUtils.GenG1.Mul(rng.RandModOrder()); } // Generating Hsk value Hsk = IdemixUtils.GenG1.Mul(rng.RandModOrder()); // Generating HRand value HRand = IdemixUtils.GenG1.Mul(rng.RandModOrder()); // Generating BarG1 value BarG1 = IdemixUtils.GenG1.Mul(rng.RandModOrder()); // Generating BarG2 value BarG2 = BarG1.Mul(isk); // Zero Knowledge Proofs // Computing t1 and t2 values with random local variable r for later use BIG r = rng.RandModOrder(); ECP2 t1 = IdemixUtils.GenG2.Mul(r); ECP t2 = BarG1.Mul(r); // Generating proofData that will contain 3 elements in G1 (of size 2*FIELD_BYTES+1)and 3 elements in G2 (of size 4 * FIELD_BYTES) byte[] proofData = new byte[0]; proofData = proofData.Append(t1.ToBytes()); proofData = proofData.Append(t2.ToBytes()); proofData = proofData.Append(IdemixUtils.GenG2.ToBytes()); proofData = proofData.Append(BarG1.ToBytes()); proofData = proofData.Append(W.ToBytes()); proofData = proofData.Append(BarG2.ToBytes()); // Hashing proofData to proofC ProofC = proofData.HashModOrder(); // Computing ProofS = (ProofC*isk) + r mod GROUP_ORDER ProofS = BIG.ModMul(ProofC, isk, IdemixUtils.GROUP_ORDER).Plus(r); ProofS.Mod(IdemixUtils.GROUP_ORDER); // Compute Hash of IdemixIssuerPublicKey byte[] serializedIpk = ToProto().ToByteArray(); Hash = serializedIpk.HashModOrder().ToBytes(); }