-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into 'master'
Develop See merge request company-projects/Meadow!54
- Loading branch information
Showing
57 changed files
with
2,080 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
using Meadow.Core.Cryptography.ECDSA.Bn128; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Numerics; | ||
using System.Text; | ||
using Xunit; | ||
|
||
namespace Meadow.Core.Test | ||
{ | ||
/* | ||
* Tests ported from: https://github.com/ethereum/py_ecc | ||
* */ | ||
public class Bn128Tests | ||
{ | ||
[Fact] | ||
public void TestFp() | ||
{ | ||
Assert.Equal(new Fp(4), new Fp(2) * new Fp(2)); | ||
Assert.Equal(new Fp(11) / new Fp(7), (new Fp(2) / new Fp(7)) + (new Fp(9) / new Fp(7))); | ||
Assert.Equal(new Fp(11) * new Fp(7), (new Fp(2) * new Fp(7)) + (new Fp(9) * new Fp(7))); | ||
Assert.Equal(new Fp(9), new Fp(9).Pow(Bn128Curve.P)); | ||
} | ||
|
||
[Fact] | ||
public void TestFp2() | ||
{ | ||
Fp2 x = new Fp2(1, 0); | ||
Fp2 f = new Fp2(1, 2); | ||
Fp2 fpx = new Fp2(2, 2); | ||
|
||
Assert.Equal(fpx, x + f); | ||
Assert.Equal(Fp2.OneValue, f / f); | ||
Assert.Equal((Fp2.OneValue + x) / f, (Fp2.OneValue / f) + (x / f)); | ||
Assert.Equal((Fp2.OneValue + x) * f, (Fp2.OneValue * f) + (x * f)); | ||
} | ||
|
||
[Fact] | ||
public void TestFp12() | ||
{ | ||
Fp12 x = new Fp12(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); ; | ||
Fp12 f = new Fp12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); | ||
Fp12 fpx = new Fp12(2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); | ||
|
||
Assert.Equal(fpx, x + f); | ||
Assert.Equal(Fp12.OneValue, f / f); | ||
Assert.Equal((Fp12.OneValue + x) / f, (Fp12.OneValue / f) + (x / f)); | ||
Assert.Equal((Fp12.OneValue + x) * f, (Fp12.OneValue * f) + (x * f)); | ||
} | ||
|
||
[Fact] | ||
public void TestPairing() | ||
{ | ||
var standardResult = Bn128Pairing.Pair(Bn128Curve.G2, Bn128Curve.G1); | ||
var negativeG1Result = Bn128Pairing.Pair(Bn128Curve.G2, Bn128Curve.G1.Negate()); | ||
Assert.Equal(Fp12.OneValue, standardResult * negativeG1Result); | ||
|
||
var negativeG2Result = Bn128Pairing.Pair(Bn128Curve.G2.Negate(), Bn128Curve.G1); | ||
Assert.Equal(Fp12.OneValue, standardResult * negativeG1Result); | ||
|
||
Assert.Equal(Fp12.OneValue, standardResult.Pow(Bn128Curve.N)); | ||
|
||
var twoTimesG1Result = Bn128Pairing.Pair(Bn128Curve.G2, Bn128Curve.G1.Multiply(2)); | ||
Assert.Equal(standardResult * standardResult, twoTimesG1Result); | ||
|
||
Assert.NotEqual(standardResult, twoTimesG1Result); | ||
Assert.NotEqual(standardResult, negativeG2Result); | ||
Assert.NotEqual(twoTimesG1Result, negativeG2Result); | ||
|
||
var twoTimesG2Result = Bn128Pairing.Pair(Bn128Curve.G2.Multiply(2), Bn128Curve.G1); | ||
Assert.Equal(standardResult * standardResult, twoTimesG2Result); | ||
|
||
var final1 = Bn128Pairing.Pair(Bn128Curve.G2.Multiply(27), Bn128Curve.G1.Multiply(37)); | ||
var final2 = Bn128Pairing.Pair(Bn128Curve.G2, Bn128Curve.G1.Multiply(999)); | ||
Assert.Equal(final1, final2); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.Linq; | ||
using System.Numerics; | ||
using System.Text; | ||
|
||
namespace Meadow.Core.Cryptography.ECDSA.Bn128 | ||
{ | ||
/// <summary> | ||
/// Provides information about the Barreto-Naehrig curve Bn128. | ||
/// </summary> | ||
public abstract class Bn128Curve | ||
{ | ||
#region Fields | ||
private static Fp12 _twistPoint; | ||
#endregion | ||
|
||
#region Properties | ||
/// <summary> | ||
/// The elliptic curve order of the bn128 curve. This is a number which when multiplied to any other point, yields the point at infinity. | ||
/// </summary> | ||
public static BigInteger N { get; } | ||
/// <summary> | ||
/// The prime used for our field operations. Referred to as p in F_p. Used as the modulo divisor to wrap values around the field. | ||
/// </summary> | ||
public static BigInteger P { get; } | ||
|
||
/// <summary> | ||
/// Generator for curve over FQ | ||
/// </summary> | ||
public static FpVector3<Fp> G1 { get; } | ||
/// <summary> | ||
/// Generator for curve over FQ2 | ||
/// </summary> | ||
public static FpVector3<Fp2> G2 { get; } | ||
public static Fp B { get; } | ||
public static Fp2 B2 { get; } | ||
public static Fp12 B12 { get; } | ||
#endregion | ||
|
||
#region Constructor | ||
/// <summary> | ||
/// Our default static constructor, sets static read only variables. | ||
/// </summary> | ||
static Bn128Curve() | ||
{ | ||
N = BigInteger.Parse("21888242871839275222246405745257275088548364400416034343698204186575808495617", CultureInfo.InvariantCulture); | ||
P = BigInteger.Parse("21888242871839275222246405745257275088696311157297823662689037894645226208583", CultureInfo.InvariantCulture); | ||
_twistPoint = new Fp12(0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | ||
G1 = new FpVector3<Fp>(Fp.OneValue, new Fp(2), Fp.OneValue); | ||
G2 = new FpVector3<Fp2>( | ||
new Fp2( | ||
BigInteger.Parse("10857046999023057135944570762232829481370756359578518086990519993285655852781", CultureInfo.InvariantCulture), | ||
BigInteger.Parse("11559732032986387107991004021392285783925812861821192530917403151452391805634", CultureInfo.InvariantCulture)), | ||
new Fp2( | ||
BigInteger.Parse("8495653923123431417604973247489272438418190587263600148770280649306958101930", CultureInfo.InvariantCulture), | ||
BigInteger.Parse("4082367875863433681332203403145435568316851327593401208105741076214120093531", CultureInfo.InvariantCulture)), | ||
Fp2.OneValue); | ||
B = new Fp(3); | ||
B2 = new Fp2(3, 0) / new Fp2(9, 1); | ||
B12 = new Fp12(3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); | ||
} | ||
#endregion | ||
|
||
#region Functions | ||
public static FpVector3<Fp12> Twist(FpVector3<Fp2> point) | ||
{ | ||
// If the point isn't properly initialize | ||
if (point == null) | ||
{ | ||
return null; | ||
} | ||
|
||
// Place the items at the start and half way point | ||
BigInteger[] xcoefficients = new BigInteger[12] { point.X.Coefficients.ElementAt(0) - (point.X.Coefficients.ElementAt(1) * 9), 0, 0, 0, 0, 0, point.X.Coefficients.ElementAt(1), 0, 0, 0, 0, 0 }; | ||
BigInteger[] ycoefficients = new BigInteger[12] { point.Y.Coefficients.ElementAt(0) - (point.Y.Coefficients.ElementAt(1) * 9), 0, 0, 0, 0, 0, point.Y.Coefficients.ElementAt(1), 0, 0, 0, 0, 0 }; | ||
BigInteger[] zcoefficients = new BigInteger[12] { point.Z.Coefficients.ElementAt(0) - (point.Z.Coefficients.ElementAt(1) * 9), 0, 0, 0, 0, 0, point.Z.Coefficients.ElementAt(1), 0, 0, 0, 0, 0 }; | ||
|
||
// Instantiate fp12s from the extended fp2 | ||
Fp12 newx = new Fp12(xcoefficients); | ||
Fp12 newy = new Fp12(ycoefficients); | ||
Fp12 newz = new Fp12(zcoefficients); | ||
|
||
// Return a twisted point from fp2 to fp12. | ||
return new FpVector3<Fp12>(newx * _twistPoint.Pow(2), newy * _twistPoint.Pow(3), newz); | ||
} | ||
#endregion | ||
} | ||
} |
155 changes: 155 additions & 0 deletions
155
src/Meadow.Core/Cryptography/ECDSA/Bn128/Bn128Pairing.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.Numerics; | ||
using System.Text; | ||
|
||
/* | ||
* Portions of code ported from: https://github.com/ethereum/py_ecc | ||
*/ | ||
|
||
namespace Meadow.Core.Cryptography.ECDSA.Bn128 | ||
{ | ||
public abstract class Bn128Pairing | ||
{ | ||
#region Properties | ||
public static BigInteger AteLoopCount { get; } | ||
public static int LogAteLoopCount { get; } | ||
public static int[] PseudoBinaryEncoding { get; } | ||
#endregion | ||
|
||
#region Constructor | ||
/// <summary> | ||
/// Our default static constructor, sets static read only variables. | ||
/// </summary> | ||
static Bn128Pairing() | ||
{ | ||
AteLoopCount = BigInteger.Parse("29793968203157093288", CultureInfo.InvariantCulture); | ||
LogAteLoopCount = 63; | ||
PseudoBinaryEncoding = new int[] | ||
{ | ||
0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0, | ||
0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1, | ||
1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, | ||
1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, 1, | ||
1, | ||
}; | ||
} | ||
#endregion | ||
|
||
#region Functions | ||
private static (Fp12 numerator, Fp12 denominator) LineFunction(FpVector3<Fp12> p1, FpVector3<Fp12> p2, FpVector3<Fp12> t) | ||
{ | ||
// As mentioned in py_ecc: the projective coordinates given are (x / z, y / z). | ||
// For slope of a line m, we usually have delta_y / delta_x. In this case it would be | ||
// m = ((p2.y / p2.z) - (p1.y / p1.z)) / ((p2.x / p2.z) - (p1.x / p1.z)) | ||
// So to eliminate these fractions, we multiply both numerator and denominator by p1.z * p2.z, | ||
// which yields the values below. This only affects scale but keeps the same m result. | ||
Fp12 slopeNumerator = (p2.Y * p1.Z) - (p1.Y * p2.Z); | ||
Fp12 slopeDenominator = (p2.X * p1.Z) - (p1.X * p2.Z); | ||
|
||
// Determine how to compute our data. | ||
bool denominatorIsZero = slopeDenominator == Fp12.ZeroValue; | ||
bool numeratorIsZero = slopeNumerator == Fp12.ZeroValue; | ||
if (denominatorIsZero && !numeratorIsZero) | ||
{ | ||
// Slope is undefined. | ||
return ((t.X * p1.Z) - (p1.X * t.Z), p1.Z * t.Z); | ||
} | ||
else if (numeratorIsZero) | ||
{ | ||
slopeNumerator = 3 * p1.X * p1.X; | ||
slopeDenominator = 2 * p1.Y * p1.Z; | ||
} | ||
|
||
Fp12 resultNumerator = (slopeNumerator * ((t.X * p1.Z) - (p1.X * t.Z))) - (slopeDenominator * ((t.Y * p1.Z) - (p1.Y * t.Z))); | ||
Fp12 resultDenominator = slopeDenominator * t.Z * p1.Z; | ||
return (resultNumerator, resultDenominator); | ||
} | ||
|
||
private static Fp12 MillerLoop(FpVector3<Fp12> q, FpVector3<Fp12> p, bool finalExponentiate = true) | ||
{ | ||
if (q == null || p == null) | ||
{ | ||
return Fp12.OneValue; | ||
} | ||
|
||
FpVector3<Fp12> nq = q.Negate(); | ||
|
||
FpVector3<Fp12> r = (FpVector3<Fp12>)q.Clone(); | ||
Fp12 fNumerator = Fp12.OneValue; | ||
Fp12 fDenominator = Fp12.OneValue; | ||
for (int i = LogAteLoopCount; i >= 0; i--) | ||
{ | ||
(Fp12 num, Fp12 denom) = LineFunction(r, r, p); | ||
fNumerator = fNumerator * fNumerator * num; | ||
fDenominator = fDenominator * fDenominator * denom; | ||
r = r.Double(); | ||
|
||
int v = PseudoBinaryEncoding[i]; | ||
if (v == 1) | ||
{ | ||
(num, denom) = LineFunction(r, q, p); | ||
fNumerator *= num; | ||
fDenominator *= denom; | ||
r = r.Add(q); | ||
} | ||
else if (v == -1) | ||
{ | ||
(num, denom) = LineFunction(r, nq, p); | ||
fNumerator *= num; | ||
fDenominator *= denom; | ||
r = r.Add(nq); | ||
} | ||
} | ||
|
||
FpVector3<Fp12> q1 = new FpVector3<Fp12>(q.X.Pow(Bn128Curve.P), q.Y.Pow(Bn128Curve.P), q.Z.Pow(Bn128Curve.P)); | ||
FpVector3<Fp12> nq2 = new FpVector3<Fp12>(q1.X.Pow(Bn128Curve.P), -q1.Y.Pow(Bn128Curve.P), q1.Z.Pow(Bn128Curve.P)); | ||
|
||
(Fp12 num1, Fp12 denom1) = LineFunction(r, q1, p); | ||
r = r.Add(q1); | ||
(Fp12 num2, Fp12 denom2) = LineFunction(r, nq2, p); | ||
Fp12 f = (fNumerator * num1 * num2) / (fDenominator * denom1 * denom2); | ||
|
||
return finalExponentiate ? FinalExponentiate(f) : f; | ||
} | ||
|
||
public static Fp12 Pair(FpVector3<Fp2> q, FpVector3<Fp> p, bool finalExponentiate = true) | ||
{ | ||
// Check z's for zero. | ||
if (p.Z == Fp.ZeroValue || q.Z == Fp2.ZeroValue) | ||
{ | ||
return Fp12.OneValue; | ||
} | ||
|
||
// Run the miller loop on twist(q) and fq12(p) | ||
return MillerLoop(Bn128Curve.Twist(q), CastFpPointToFp12Point(p), finalExponentiate); | ||
} | ||
|
||
public static Fp12 FinalExponentiate(Fp12 p) | ||
{ | ||
return p.Pow((BigInteger.Pow(Bn128Curve.P, 12) - 1) / Bn128Curve.N); | ||
} | ||
|
||
private static FpVector3<Fp12> CastFpPointToFp12Point(FpVector3<Fp> point) | ||
{ | ||
// If our point isn't initialized, return null. | ||
if (point == null) | ||
{ | ||
return null; | ||
} | ||
|
||
// Create our data for our fq | ||
BigInteger[] xData = new BigInteger[12]; | ||
xData[0] = point.X.N; | ||
BigInteger[] yData = new BigInteger[12]; | ||
yData[0] = point.Y.N; | ||
BigInteger[] zData = new BigInteger[12]; | ||
zData[0] = point.Z.N; | ||
|
||
// Return our Fp12 vector. | ||
return new FpVector3<Fp12>(new Fp12(xData), new Fp12(yData), new Fp12(zData)); | ||
} | ||
#endregion | ||
} | ||
} |
Oops, something went wrong.