public static ASNLSignatureType Generate(List <byte[]> x, List <Cryptography.ECC.ECPoint> P1, List <Cryptography.ECC.ECPoint> P2, List <int> indices) { List <byte[]> s1 = new List <byte[]>(); ASNLSignatureType asnlSig = new ASNLSignatureType(); asnlSig.InitSField(); for (int i = 0; i < AMOUNT_SIZE; i++) { SchnorrSignatureType schnorrSig = SchnorrNonLinkable.Generate(x[i], P1[i], P2[i], indices[i]); if (!SchnorrNonLinkable.Verify(P1[i], P2[i], schnorrSig)) { throw new Exception("Schnorr Sign Error!"); } asnlSig.L1.Add(schnorrSig.L1); s1.Add(schnorrSig.s1); asnlSig.s2.Add(schnorrSig.s2); asnlSig.s = ScalarFunctions.Add(asnlSig.s, s1[i]); } return(asnlSig.Exports()); }
public static BorromeanSignatureType Generate(List <byte[]> x, List <Cryptography.ECC.ECPoint> P1, List <Cryptography.ECC.ECPoint> P2, List <int> indices) { List <byte[]> s1 = new List <byte[]>(); List <byte[]> alpha = new List <byte[]>(); List <ECPoint>[] L = new List <ECPoint> [2]; L[0] = new List <ECPoint>(); L[1] = new List <ECPoint>(); BorromeanSignatureType boroSig = new BorromeanSignatureType(); boroSig.InitSField(); for (int i = 0; i < AMOUNT_SIZE; i++) { int naught = indices[i]; int prime = (naught + 1) % 2; byte[] a = SchnorrNonLinkable.GenerateRandomScalar(); ECPoint L1 = Cryptography.ECC.ECCurve.Secp256r1.G * a; L[naught].Add(L1); alpha.Add(a); if (naught == 0) { byte[] s2 = SchnorrNonLinkable.GenerateRandomScalar(); byte[] c2 = Crypto.Default.Hash256(L1.EncodePoint(true)); ECPoint L2 = Cryptography.ECC.ECCurve.Secp256r1.G * s2 + P2[i] * c2; L[prime].Add(L2); boroSig.s1.Add(s2); } else { boroSig.s1.Add(new byte[32]); } boroSig.ee = ScalarFunctions.Add(boroSig.ee, Crypto.Default.Hash256(L[1][i].EncodePoint(true))); //Check This Part } for (int i = 0; i < AMOUNT_SIZE; i++) { if (indices[i] == 0) { boroSig.s0.Add(ScalarFunctions.MulSub(boroSig.ee, x[i], alpha[i])); } else { byte[] s2 = SchnorrNonLinkable.GenerateRandomScalar(); ECPoint LL = Cryptography.ECC.ECCurve.Secp256r1.G * s2 + P1[i] * boroSig.ee; byte[] cc = Crypto.Default.Hash256(LL.EncodePoint(true)); boroSig.s1[i] = ScalarFunctions.MulSub(cc, x[i], alpha[i]); boroSig.s0.Add(s2); } } return(boroSig.Exports()); }
/// <summary> /// Generate gives C, and mask such that \sumCi = C /// c.f. http://eprint.iacr.org/2015/1098 section 5.1 /// and Ci is a commitment to either 0 or 2^i, i=0,...,63 /// thus this proves that "amount" is in [0, 2^64] /// mask is a such that C = aG + bH, and b = amount /// </summary> /// <returns></returns> public static RangeProveType Generate(Fixed8 amount) { Initialize(); byte[] mask = new byte[32]; ECPoint C = new ECPoint(); List <int> binaryAmount = amount.ToBinaryFormat(); List <byte[]> ai = new List <byte[]>(); List <ECPoint> CiH = new List <ECPoint>(); RangeProveType rangeProver = new RangeProveType(); for (int i = 0; i < ASNLRingSignature.AMOUNT_SIZE; i++) { byte[] ai_i = new byte[32]; ai.Add(ai_i); if (binaryAmount[i] == 0) { rangeProver.rangeSig.Ci.Add(ECCurve.Secp256r1.G * ai_i); } else if (binaryAmount[i] == 1) { rangeProver.rangeSig.Ci.Add(ECCurve.Secp256r1.G * ai_i + H2[i]); } else { throw new Exception("Range Prove => Binary Format Error!"); } CiH.Add(rangeProver.rangeSig.Ci[i] - H2[i]); mask = ScalarFunctions.Add(mask, ai[i]); if (i == 0) { C = rangeProver.rangeSig.Ci[i]; } else { C = C + rangeProver.rangeSig.Ci[i]; } } rangeProver.C = C; rangeProver.mask = mask; rangeProver.rangeSig.AsnlSig = ASNLRingSignature.Generate(ai, rangeProver.rangeSig.Ci, CiH, binaryAmount); if (!ASNLRingSignature.Verify(rangeProver.rangeSig.Ci, CiH, rangeProver.rangeSig.AsnlSig)) { throw new Exception("Range prove error => ASNL verify error!"); } return(rangeProver.Export()); }
public static EcdhTuple EcdhDecode(this EcdhTuple mask, byte[] recieverSK) { EcdhTuple unmask = mask; byte[] sharedSec1 = Cryptography.Crypto.Default.Hash256(ScalarFunctions.MulWithPoint(mask.senderPK, recieverSK)); byte[] sharedSec2 = Cryptography.Crypto.Default.Hash256(sharedSec1); unmask.mask = ScalarFunctions.Sub(mask.mask, sharedSec1); unmask.amount = ScalarFunctions.Sub(mask.amount, sharedSec2); return(unmask); }
public static EcdhTuple EcdhEncode(this EcdhTuple unmask, ECPoint receiverPk) { EcdhTuple ret = new EcdhTuple(); byte[] esk = SchnorrNonLinkable.GenerateRandomScalar(); ret.senderPK = ECCurve.Secp256r1.G * esk; byte[] sharedSec1 = Cryptography.Crypto.Default.Hash256(ScalarFunctions.MulWithPoint(receiverPk, esk)); byte[] sharedSec2 = Cryptography.Crypto.Default.Hash256(sharedSec1); ret.mask = ScalarFunctions.Add(unmask.mask, sharedSec1); ret.amount = ScalarFunctions.Add(unmask.amount, sharedSec2); return(ret); }
public static bool Verify(List <ECPoint> P1, List <ECPoint> P2, BorromeanSignatureType sig) { byte[] ee = new byte [32]; ECPoint LHS; ECPoint RHS = ECCurve.Secp256r1.G * sig.ee; for (int i = 0; i < AMOUNT_SIZE; i++) { ECPoint L2 = ECCurve.Secp256r1.G * sig.s0[i] + P1[i] * sig.ee; byte[] c1 = Crypto.Default.Hash256(L2.EncodePoint(true)); ECPoint L1 = ECCurve.Secp256r1.G * sig.s1[i] + P2[i] * c1; ee = ScalarFunctions.Add(ee, Crypto.Default.Hash256(L1.EncodePoint(true))); } return(sig.ee.ToHexString().Equals(ee.ToHexString())); }
public static SchnorrSignatureType Generate(byte[] x, Cryptography.ECC.ECPoint P1, Cryptography.ECC.ECPoint P2, int index) { byte[] a = GenerateRandomScalar(); if (index == 0) { Cryptography.ECC.ECPoint L1 = Cryptography.ECC.ECCurve.Secp256r1.G * a; byte[] s2 = GenerateRandomScalar(); byte[] c2 = Crypto.Default.Hash256(L1.EncodePoint(true)); Cryptography.ECC.ECPoint L2 = Cryptography.ECC.ECCurve.Secp256r1.G * s2 + P2 * c2; byte[] c1 = Crypto.Default.Hash256(L2.EncodePoint(true)); byte[] s1 = ScalarFunctions.MulSub(c1, x, a); SchnorrSignatureType retSig = new SchnorrSignatureType(L1, s1, s2); return(retSig); } else if (index == 1) { Cryptography.ECC.ECPoint L2 = Cryptography.ECC.ECCurve.Secp256r1.G * a; byte[] s1 = GenerateRandomScalar(); byte[] c1 = Crypto.Default.Hash256(L2.EncodePoint(true)); Cryptography.ECC.ECPoint L1 = Cryptography.ECC.ECCurve.Secp256r1.G * s1 + P1 * c1; byte[] c2 = Crypto.Default.Hash256(L1.EncodePoint(true)); byte[] s2 = ScalarFunctions.MulSub(c2, x, a); SchnorrSignatureType retSig = new SchnorrSignatureType(L1, s1, s2); return(retSig); } else { throw new Exception("SchnorrNonLinkable Index Overload Error!"); } }
public static bool Verify(List <List <ECPoint> > PK, MLSAGSignatureType sig) { int rows = PK[0].Count; int cols = PK.Count; if (cols < 2) { throw new Exception("Error! What is c if cols = 1!"); } int i = 0; byte[] c_old = new byte[32]; Buffer.BlockCopy(sig.cc, 0, c_old, 0, sig.cc.Length); List <ECPoint> Li = new List <ECPoint>(); List <byte[]> Ri = new List <byte[]>(); while (i < cols) { Li.Clear(); Ri.Clear(); for (int j = 0; j < rows; j++) { ECPoint L = ECCurve.Secp256r1.G * sig.ss[i][j] + PK[i][j] * c_old; byte[] Hi = Crypto.Default.Hash256(PK[i][j].ToString().HexToBytes()); byte[] R = ScalarFunctions.Add(ScalarFunctions.Mul(sig.ss[i][j], Hi), ScalarFunctions.Mul(c_old, sig.II[j])); Li.Add(L); Ri.Add(R); } c_old = MakeHash(PK[i], Li, Ri); i = i + 1; } return(sig.cc.ToHexString() == c_old.ToHexString()); }
public static MLSAGSignatureType Generate(List <List <ECPoint> > PK, List <byte[]> X, int index) { MLSAGSignatureType sig = new MLSAGSignatureType(); int rows = PK[0].Count; int cols = PK.Count; #region Initialize for (int j = 0; j < cols; j++) { sig.ss.Add(new List <byte[]>()); } #endregion if (cols < 2) { throw new Exception("Error! What is c if cols = 1!"); } List <byte[]> alpha = new List <byte[]>(); List <ECPoint> aG = new List <ECPoint>(); List <byte[]> aHP = new List <byte[]>(); List <ECPoint> Li = new List <ECPoint>(); List <byte[]> Ri = new List <byte[]>(); for (int j = 0; j < rows; j++) { byte[] a = SchnorrNonLinkable.GenerateRandomScalar(); alpha.Add(a); aG.Add(ECCurve.Secp256r1.G * a); byte[] Hi = Crypto.Default.Hash256(PK[index][j].ToString().HexToBytes()); aHP.Add(ScalarFunctions.Mul(a, Hi)); sig.II.Add(ScalarFunctions.Mul(X[j], Hi)); } byte[] c_old = MakeHash(PK[index], aG, aHP); int i = (index + 1) % cols; if (i == 0) { Buffer.BlockCopy(c_old, 0, sig.cc, 0, c_old.Length); } while (i != index) { for (int j = 0; j < rows; j++) { sig.ss[i].Add(SchnorrNonLinkable.GenerateRandomScalar()); } byte[] c = new byte[32]; Li.Clear(); Ri.Clear(); for (int j = 0; j < rows; j++) { ECPoint L = ECCurve.Secp256r1.G * sig.ss[i][j] + PK[i][j] * c_old; byte[] Hi = Crypto.Default.Hash256(PK[i][j].ToString().HexToBytes()); byte[] R = ScalarFunctions.Add(ScalarFunctions.Mul(sig.ss[i][j], Hi), ScalarFunctions.Mul(c_old, sig.II[j])); Li.Add(L); Ri.Add(R); } c_old = MakeHash(PK[i], Li, Ri); i = (i + 1) % cols; if (i == 0) { Buffer.BlockCopy(c_old, 0, sig.cc, 0, c_old.Length); } } for (int j = 0; j < rows; j++) { sig.ss[index].Add(ScalarFunctions.MulSub(c_old, X[j], alpha[j])); } return(sig); }
/// <summary> /// Tag-Linkable Ring-CT with Multiple Inputs and One-time Keys /// c.f. http://eprint.iacr.org/2015/1098 section 4. definition 10. /// This does the MG sig on the "dest" part of the given key matrix, and /// the last row is the sum of input commitments from that column - sum output commitments /// this shows that sum inputs = sum outputs /// </summary> /// <param name="pubs">Public keys using from Ring CT -> {P(i,j), C(i,j)}</param> /// <param name="inSK">Private keys for public keys</param> /// <param name="outSK">C_out sk</param> /// <param name="outPK">C_out PK</param> /// <param name="index">Signer's index</param> /// <returns></returns> public static MLSAGSignatureType ProveRctMG(List <List <CTKey> > pubs, List <CTCommitment> inSK, List <CTCommitment> outSK, List <CTKey> outPK, Fixed8 vPub, int index) { int rows = pubs[0].Count; int cols = pubs.Count; List <byte[]> sk = new List <byte[]>(); List <byte[]> tmp = new List <byte[]>(); for (int i = 0; i < rows + 1; i++) { byte[] sk_i = new byte[32]; sk.Add(sk_i); } List <List <ECPoint> > M = new List <List <ECPoint> >(); for (int i = 0; i < cols; i++) { List <ECPoint> M_i = new List <ECPoint>(); ECPoint M_row = new ECPoint(); for (int j = 0; j < rows; j++) { M_i.Add(pubs[i][j].dest); M_row = M_row + pubs[i][j].mask; } M_i.Add(M_row); M.Add(M_i); } for (int i = 0; i < cols; i++) { for (int j = 0; j < outPK.Count; j++) { M[i][rows] = M[i][rows] - outPK[j].mask; } if (vPub > Fixed8.Zero) { byte[] b_vPub = vPub.ToBinaryFormat().ToBinary(); M[i][rows] = M[i][rows] - RangeSignature.H * b_vPub; } else if (vPub < Fixed8.Zero) { byte[] b_vPub = (-vPub).ToBinaryFormat().ToBinary(); M[i][rows] = M[i][rows] + RangeSignature.H * b_vPub; } } byte[] sk_row = inSK[0].mask; for (int i = 0; i < rows; i++) { sk[i] = inSK[i].dest; if (i > 0) { sk_row = ScalarFunctions.Add(sk_row, inSK[i].mask); } } sk[rows] = sk_row; for (int i = 0; i < outPK.Count; i++) { sk[rows] = ScalarFunctions.Sub(sk[rows], outSK[i].mask); } return(MLSAGSignature.Generate(M, sk, index)); }