예제 #1
0
        public void TestSimpleArithmetic()
        {
            for (var i = -100; i <= 100; ++i)
            {
                var x = GT.FromInt(i);
                Assert.AreEqual(GT.FromInt(-i), -x);
                for (var j = -100; j <= 100; ++j)
                {
                    var y = GT.FromInt(j);
                    Assert.AreEqual(GT.FromInt(i + j), x + y);
                    Assert.AreEqual(GT.FromInt(i * j), x * y);
                    Assert.AreEqual(GT.FromInt(i - j), x - y);
                    if (j == 0)
                    {
                        Assert.Throws <InvalidOperationException>(() =>
                        {
                            var unused = x * y / y;
                        });
                    }
                    else
                    {
                        Assert.AreEqual(GT.FromInt(i * j / j), x * y / y);
                    }

                    if (j > 0 && i >= -8 && i <= 8 && j <= 8)
                    {
                        Assert.AreEqual(GT.FromInt((int)Math.Pow(i, j)), GT.Pow(x, Fr.FromInt(j)));
                    }
                }
            }
        }
예제 #2
0
        public void TestPowersCalculation()
        {
            var powers = Enumerable.Range(0, 30)
                         .Select(i => Fr.FromInt(1 << i))
                         .ToArray();

            CollectionAssert.AreEqual(powers, MclBls12381.Powers(Fr.FromInt(2), 30));
        }
예제 #3
0
        public IEnumerable <PrivateKeyShare> GetPrivateShares()
        {
            var shares = new Fr[_parties];

            for (var i = 0; i < _parties; ++i)
            {
                shares[i] = MclBls12381.EvaluatePolynomial(_coeffs, Fr.FromInt(i + 1));
            }
            return(shares.Select(share => new PrivateKeyShare(share)));
        }
예제 #4
0
        public void EvalFrPolyConstantTest()
        {
            var poly = new Fr[] { Fr.GetRandom() };
            var v0   = MclBls12381.EvaluatePolynomial(poly, Fr.Zero);
            var v1   = MclBls12381.EvaluatePolynomial(poly, Fr.One);
            var v2   = MclBls12381.EvaluatePolynomial(poly, Fr.FromInt(319948));

            Assert.AreEqual(poly[0], v0);
            Assert.AreEqual(poly[0], v1);
            Assert.AreEqual(poly[0], v2);
        }
예제 #5
0
        public Signature AssembleSignature(IEnumerable <KeyValuePair <int, Signature> > shares)
        {
            var keyValuePairs = shares as KeyValuePair <int, Signature>[] ?? shares.ToArray();
            var xs            = keyValuePairs.Take(Threshold + 1).Select(pair => Fr.FromInt(pair.Key + 1)).ToArray();
            var ys            = keyValuePairs.Take(Threshold + 1).Select(pair => pair.Value.RawSignature).ToArray();

            if (xs.Length <= Threshold || ys.Length <= Threshold)
            {
                throw new ArgumentException("not enough shares for signature");
            }
            return(new Signature(MclBls12381.LagrangeInterpolate(xs, ys)));
        }
예제 #6
0
 public void TestSimpleArithmetic()
 {
     for (var i = -100; i <= 100; ++i)
     {
         var x = G2.Generator * Fr.FromInt(i);
         Assert.AreEqual(G2.Generator * Fr.FromInt(-i), -x);
         for (var j = -100; j <= 100; ++j)
         {
             var y = G2.Generator * Fr.FromInt(j);
             Assert.AreEqual(G2.Generator * Fr.FromInt(i + j), x + y);
             Assert.AreEqual(G2.Generator * Fr.FromInt(i - j), x - y);
             Assert.AreEqual(G2.Generator * Fr.FromInt(i * j), x * Fr.FromInt(j));
         }
     }
 }
예제 #7
0
        public G1 Evaluate(int x, int y)
        {
            var result = G1.Zero;
            var powX   = MclBls12381.Powers(Fr.FromInt(x), Degree + 1);
            var powY   = MclBls12381.Powers(Fr.FromInt(y), Degree + 1);

            for (var i = 0; i <= Degree; ++i)
            {
                for (var j = 0; j <= Degree; ++j)
                {
                    result += _coefficients[Index(i, j)] * powX[i] * powY[j];
                }
            }

            return(result);
        }
예제 #8
0
 public void TestGenerator()
 {
     Assert.IsTrue(G2.Generator.IsValid());
     Assert.IsFalse(G2.Generator.IsZero());
     Assert.AreEqual(G2.Generator, G2.Generator);
     Assert.AreNotEqual(G2.Zero, G2.Generator); // TODO: WTF?
     Assert.IsTrue(G2.Zero != G2.Generator);
     Assert.AreNotEqual(G2.Generator, G2.Generator * Fr.FromInt(2));
     Assert.AreEqual(G2.Generator - G2.Generator, G2.Zero);
     Assert.AreEqual(G2.Generator.Double(), G2.Generator + G2.Generator);
     Assert.AreEqual(G2.Generator.Double(), G2.Generator * Fr.FromInt(2));
     Assert.AreEqual(
         "G2(f1437606f337b000f00d69507434dbbd3b2abfa8a291d88551d92309fe3c222e0790fc847e849eb984bb807cba59170a0a63480e9457a375705ea2aba224a711e717ecddb224feeb738630945581bda24389f8fecf7865724361aec550e44919)",
         G2.Generator.ToString()
         );
     Assert.AreNotEqual(G1.Generator, G2.Generator);
 }
예제 #9
0
 public void TestGenerator()
 {
     Assert.IsTrue(G1.Generator.IsValid());
     Assert.IsFalse(G1.Generator.IsZero());
     Assert.AreEqual(G1.Generator, G1.Generator);
     Assert.AreNotEqual(G1.Zero, G1.Generator);
     Assert.AreNotEqual(G1.Generator, G1.Generator * Fr.FromInt(2));
     Assert.IsTrue(G1.Zero != G1.Generator);
     Assert.AreEqual(G1.Generator - G1.Generator, G1.Zero);
     Assert.AreEqual(G1.Generator.Double(), G1.Generator + G1.Generator);
     Assert.AreEqual(G1.Generator.Double(), G1.Generator * Fr.FromInt(2));
     Assert.AreEqual(
         "G1(e9328f8eb8185341f22adaf2bf41f66258d97b2b5b2dbd2c27a77c81d9b5d76dd119bf7b1cd5d57b1273f9c4a654540e)",
         G1.Generator.ToString()
         );
     Assert.AreNotEqual(G1.Generator, G2.Generator);
 }
예제 #10
0
        public IEnumerable <Fr> Evaluate(int x)
        {
            var row = Enumerable.Range(0, _degree + 1).Select(_ => Fr.Zero).ToArray();
            var frX = Fr.FromInt(x);

            for (var i = 0; i <= _degree; ++i)
            {
                var xPowJ = Fr.One;
                for (var j = 0; j <= _degree; ++j)
                {
                    row[i] += _coefficients[Index(i, j)] * xPowJ;
                    xPowJ  *= frX;
                }
            }

            return(row);
        }
예제 #11
0
        public void TestPolyInterpolationG2()
        {
            const int degree = 100;
            var       coeffs = Enumerable.Range(0, degree)
                               .Select(i => G2.Generator * Fr.GetRandom())
                               .ToArray();
            var xs = Enumerable.Range(1, degree)
                     .Select(i => Fr.GetRandom())
                     .ToArray();
            var ys = xs
                     .Select(x => MclBls12381.EvaluatePolynomial(coeffs, x))
                     .ToArray();
            var intercept = MclBls12381.EvaluatePolynomial(coeffs, Fr.FromInt(0));

            Assert.AreEqual(intercept, MclBls12381.LagrangeInterpolate(xs, ys));
            Assert.Throws <ArgumentException>(() => MclBls12381.LagrangeInterpolate(xs, ys.Take(degree - 1).ToArray()));
        }
예제 #12
0
        public void Test_Mcl_Serializations()
        {
            Assert.AreEqual(
                "0x0000000000000000000000000000000000000000000000000000000000000000",
                Fr.FromInt(0).ToHex()
                );
            Assert.AreEqual(
                "0x0100000000000000000000000000000000000000000000000000000000000000",
                Fr.FromInt(1).ToHex()
                );
            var fr = Fr.GetRandom();

            Assert.AreEqual(fr, Fr.FromBytes(fr.ToBytes()));

            Assert.AreEqual(
                "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
                G1.Zero.ToHex()
                );
            Assert.AreEqual(
                "0xe9328f8eb8185341f22adaf2bf41f66258d97b2b5b2dbd2c27a77c81d9b5d76dd119bf7b1cd5d57b1273f9c4a654540e",
                G1.Generator.ToHex()
                );
            Assert.AreEqual(
                "0x2ac325b200d53184871fb8f8f5e5e43b302349ae6172de2899e88d2961f0bd2593b427667f5f85b4b59296ae8dcfc918",
                (G1.Generator * Fr.FromInt(2)).ToHex()
                );
            var g1 = G1.Generator * Fr.GetRandom();

            Assert.AreEqual(g1, G1.FromBytes(g1.ToBytes()));

            Assert.AreEqual(
                "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
                G2.Zero.ToHex()
                );
            Assert.AreEqual(
                "0xf1437606f337b000f00d69507434dbbd3b2abfa8a291d88551d92309fe3c222e0790fc847e849eb984bb807cba59170a0a63480e9457a375705ea2aba224a711e717ecddb224feeb738630945581bda24389f8fecf7865724361aec550e44919",
                G2.Generator.ToHex()
                );
            Assert.AreEqual(
                "0xd63f18cd560a715faef9b96c31e08eead86809ffd81642f6cdb55ed88ea2eca32cb2a28d818b7887cb35f1a7d4ab8a04eacc640851cb34b8a615729cd6d8cc4317125959b2012444b435508679e0a2f07d691d91aef2a18400a6696c6a3ae18d",
                (G2.Generator * Fr.FromInt(2)).ToHex()
                );
        }
예제 #13
0
        public void EvalInterpolateTestFr()
        {
            const int n      = 10;
            var       poly   = Enumerable.Range(0, n).Select(_ => Fr.GetRandom()).ToArray();
            var       values = Enumerable.Range(100, n + 1)
                               .Select(i => MclBls12381.EvaluatePolynomial(poly, Fr.FromInt(i)))
                               .ToArray();

            for (var i = 0; i < n + 1; ++i)
            {
                Assert.AreEqual(DummyEval(poly, Fr.FromInt(100 + i)), values[i]);
            }
            var intercept = MclBls12381.LagrangeInterpolate(
                Enumerable.Range(100, n + 1).Select(Fr.FromInt).ToArray(),
                values
                );

            Assert.AreEqual(poly[0], intercept);
        }
예제 #14
0
 public void TestSimpleArithmetic()
 {
     for (var i = -100; i <= 100; ++i)
     {
         var x = Fr.FromInt(i);
         Assert.AreEqual(Fr.FromInt(-i), -x);
         Assert.AreEqual(Fr.FromInt(i * i), x.Square());
         for (var j = -100; j <= 100; ++j)
         {
             var y = Fr.FromInt(j);
             Assert.AreEqual(Fr.FromInt(i + j), x + y);
             Assert.AreEqual(Fr.FromInt(i * j), x * y);
             Assert.AreEqual(Fr.FromInt(i - j), x - y);
             Assert.AreEqual(
                 j != 0 ? Fr.FromInt(i * j / j) : Fr.FromInt(0),
                 x * y / y
                 );
         }
     }
 }
예제 #15
0
        public ThresholdKeyring?TryGetKeys()
        {
            if (!Finished())
            {
                return(null);
            }
            var pubKeyPoly = Enumerable.Range(0, Faulty + 1)
                             .Select(_ => G1.Zero)
                             .ToArray();
            var secretKey = Fr.Zero;

            foreach (var dealer in _finished.Take(Faulty + 1))
            {
                var s = _keyGenStates[dealer];
                if (s.ValueCount() <= 2 * Faulty)
                {
                    throw new Exception("Impossible");                               // just in case
                }
                var rowZero = s.Commitment !.Evaluate(0).ToArray();
                foreach (var(x, i) in rowZero.WithIndex())
                {
                    pubKeyPoly[i] += x;
                }
                secretKey += s.InterpolateValues();
            }

            var pubKeys = Enumerable.Range(0, Players + 1)
                          .Select(i => MclBls12381.EvaluatePolynomial(pubKeyPoly, Fr.FromInt(i)))
                          .ToArray();

            return(new ThresholdKeyring
            {
                TpkePrivateKey = new PrivateKey(secretKey, _myIdx),
                TpkePublicKey = new PublicKey(pubKeys[0], Faulty),
                ThresholdSignaturePrivateKey = new PrivateKeyShare(secretKey),
                ThresholdSignaturePublicKeySet =
                    new PublicKeySet(pubKeys.Skip(1).Select(x => new Crypto.ThresholdSignature.PublicKey(x)), Faulty)
            });
        }
예제 #16
0
        public void TestZero()
        {
            Assert.IsTrue(Fr.Zero.IsValid());
            Assert.IsTrue(Fr.Zero.IsZero());
            Assert.IsFalse(Fr.Zero.IsOne());
            Assert.AreEqual(Fr.Zero, Fr.Zero);
            Assert.AreEqual(Fr.Zero, Fr.FromInt(0));
            Assert.AreNotEqual(Fr.Zero, Fr.One);
            Assert.IsTrue(Fr.Zero != Fr.One);
            Assert.AreEqual(Fr.Zero + Fr.Zero, Fr.Zero);
            var rnd = Fr.GetRandom();

            Assert.AreEqual(Fr.Zero + rnd, rnd);
            Assert.AreEqual(rnd + Fr.Zero, rnd);
            Assert.AreEqual(Fr.Zero * rnd, Fr.Zero);
            Assert.AreEqual(rnd * Fr.Zero, Fr.Zero);
            Assert.AreEqual(Fr.Zero, Fr.Zero.Inverse()); // NB
            Assert.AreEqual(
                "Fr(0000000000000000000000000000000000000000000000000000000000000000)",
                Fr.Zero.ToString()
                );
            Assert.AreNotEqual(Fr.Zero, G1.Zero);
            Assert.AreNotEqual(Fr.Zero, G2.Zero);
        }
예제 #17
0
        public RawShare FullDecrypt(EncryptedShare share, List <PartiallyDecryptedShare> us)
        {
            return(FullDecryptBenchmark.Benchmark(() =>
            {
                if (us.Count < _t)
                {
                    throw new Exception("Insufficient number of shares!");
                }

                var ids = new HashSet <int>();
                foreach (var part in us)
                {
                    if (ids.Contains(part.DecryptorId))
                    {
                        throw new Exception($"Id {part.DecryptorId} was provided more than once!");
                    }
                    if (part.ShareId != share.Id)
                    {
                        throw new Exception($"Share id mismatch for decryptor {part.DecryptorId}");
                    }
                    ids.Add(part.DecryptorId);
                }

                var ys = new List <G1>();
                var xs = new List <Fr>();

                foreach (var part in us)
                {
                    xs.Add(Fr.FromInt(part.DecryptorId + 1));
                    ys.Add(part.Ui);
                }

                var u = MclBls12381.LagrangeInterpolate(xs.ToArray(), ys.ToArray());
                return new RawShare(Utils.XorWithHash(u, share.V), share.Id);
            }));
        }
예제 #18
0
        private static Fr Eval(BiVarSymmetricPolynomial p, int x, int y)
        {
            var t = p.Evaluate(x).ToArray();

            return(MclBls12381.EvaluatePolynomial(t, Fr.FromInt(y)));
        }
예제 #19
0
 public PrivateKey GetPrivKey(int i)
 {
     return(new PrivateKey(MclBls12381.EvaluatePolynomial(_coeffs, Fr.FromInt(i + 1)), i));
 }
예제 #20
0
 public PublicKey GetPubKey()
 {
     return(new PublicKey(G1.Generator * MclBls12381.EvaluatePolynomial(_coeffs, Fr.FromInt(0)), _degree));
 }
예제 #21
0
        public ValueMessage HandleCommit(int sender, CommitMessage message)
        {
            if (message.EncryptedRows.Length != Players)
            {
                throw new ArgumentException();
            }
            if (_keyGenStates[sender].Commitment != null)
            {
                throw new ArgumentException($"Double commit from sender {sender}");
            }
            _keyGenStates[sender].Commitment = message.Commitment;
            var myRowCommitted = message.Commitment.Evaluate(_myIdx + 1);
            var myRow          = DecryptRow(message.EncryptedRows[_myIdx], _keyPair.PrivateKey).ToArray();

            if (!myRow.Select(x => G1.Generator * x).SequenceEqual(myRowCommitted))
            {
                throw new ArgumentException("Commitment does not match");
            }

            return(new ValueMessage
            {
                Proposer = sender,
                EncryptedValues = Enumerable.Range(0, Players).Select(i => Crypto.Secp256K1Encrypt(
                                                                          _publicKeys[i].EncodeCompressed(),
                                                                          MclBls12381.EvaluatePolynomial(myRow, Fr.FromInt(i + 1)).ToBytes()
                                                                          )).ToArray()
            });
        }