Skip to content

Commit 197e97d

Browse files
author
childish-sambino
authored
feat: add Elliptic Curve code and utilities (#1014)
See README for details.
1 parent 4a5e725 commit 197e97d

File tree

14 files changed

+1186
-0
lines changed

14 files changed

+1186
-0
lines changed

src/SendGrid/EllipticCurve/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Stark Bank
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Overview
2+
3+
The code in this namespace is borrowed from [starkbank/ecdsa-dotnet](https://github.com/starkbank/ecdsa-dotnet). The preference is to directly depend on that repository, but there is a compatibility issue captured by [issues/#4](https://github.com/starkbank/ecdsa-dotnet/issues/4). Once this issue has been resolved and released, the code here can be deleted and a proper dependency added.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using System.Collections.Generic;
2+
using System.Numerics;
3+
using System;
4+
5+
namespace EllipticCurve
6+
{
7+
public class CurveFp
8+
{
9+
public BigInteger A { get; private set; }
10+
public BigInteger B { get; private set; }
11+
public BigInteger P { get; private set; }
12+
public BigInteger N { get; private set; }
13+
public Point G { get; private set; }
14+
public string name { get; private set; }
15+
public int[] oid { get; private set; }
16+
public string nistName { get; private set; }
17+
18+
19+
public CurveFp(BigInteger A, BigInteger B, BigInteger P, BigInteger N, BigInteger Gx, BigInteger Gy, string name, int[] oid, string nistName = "")
20+
{
21+
this.A = A;
22+
this.B = B;
23+
this.P = P;
24+
this.N = N;
25+
G = new Point(Gx, Gy);
26+
this.name = name;
27+
this.nistName = nistName;
28+
this.oid = oid;
29+
}
30+
31+
public bool contains(Point p)
32+
{
33+
return Utils.Integer.modulo(
34+
BigInteger.Pow(p.y, 2) - (BigInteger.Pow(p.x, 3) + A * p.x + B),
35+
P
36+
).IsZero;
37+
}
38+
39+
public int length()
40+
{
41+
return N.ToString("X").Length / 2;
42+
}
43+
44+
}
45+
46+
public static class Curves
47+
{
48+
49+
public static CurveFp getCurveByName(string name)
50+
{
51+
name = name.ToLower();
52+
53+
if (name == "secp256k1")
54+
{
55+
return secp256k1;
56+
}
57+
if (name == "p256" | name == "prime256v1")
58+
{
59+
return prime256v1;
60+
}
61+
62+
throw new ArgumentException("unknown curve " + name);
63+
}
64+
65+
public static CurveFp secp256k1 = new CurveFp(
66+
Utils.BinaryAscii.numberFromHex("0000000000000000000000000000000000000000000000000000000000000000"),
67+
Utils.BinaryAscii.numberFromHex("0000000000000000000000000000000000000000000000000000000000000007"),
68+
Utils.BinaryAscii.numberFromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"),
69+
Utils.BinaryAscii.numberFromHex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"),
70+
Utils.BinaryAscii.numberFromHex("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"),
71+
Utils.BinaryAscii.numberFromHex("483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"),
72+
"secp256k1",
73+
new int[] { 1, 3, 132, 0, 10 }
74+
);
75+
76+
public static CurveFp prime256v1 = new CurveFp(
77+
Utils.BinaryAscii.numberFromHex("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc"),
78+
Utils.BinaryAscii.numberFromHex("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b"),
79+
Utils.BinaryAscii.numberFromHex("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"),
80+
Utils.BinaryAscii.numberFromHex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"),
81+
Utils.BinaryAscii.numberFromHex("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296"),
82+
Utils.BinaryAscii.numberFromHex("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"),
83+
"prime256v1",
84+
new int[] { 1, 2, 840, 10045, 3, 1, 7 },
85+
"P-256"
86+
);
87+
88+
public static CurveFp p256 = prime256v1;
89+
90+
public static CurveFp[] supportedCurves = { secp256k1, prime256v1 };
91+
92+
public static Dictionary<string, CurveFp> curvesByOid = new Dictionary<string, CurveFp>() {
93+
{string.Join(",", secp256k1.oid), secp256k1},
94+
{string.Join(",", prime256v1.oid), prime256v1}
95+
};
96+
97+
}
98+
99+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System.Security.Cryptography;
2+
using System.Numerics;
3+
using System.Text;
4+
5+
namespace EllipticCurve
6+
{
7+
8+
public static class Ecdsa
9+
{
10+
11+
public static bool verify(string message, Signature signature, PublicKey publicKey)
12+
{
13+
string hashMessage = sha256(message);
14+
BigInteger numberMessage = Utils.BinaryAscii.numberFromHex(hashMessage);
15+
CurveFp curve = publicKey.curve;
16+
BigInteger sigR = signature.r;
17+
BigInteger sigS = signature.s;
18+
BigInteger inv = EcdsaMath.inv(sigS, curve.N);
19+
20+
Point u1 = EcdsaMath.multiply(
21+
curve.G,
22+
Utils.Integer.modulo((numberMessage * inv), curve.N),
23+
curve.N,
24+
curve.A,
25+
curve.P
26+
);
27+
Point u2 = EcdsaMath.multiply(
28+
publicKey.point,
29+
Utils.Integer.modulo((sigR * inv), curve.N),
30+
curve.N,
31+
curve.A,
32+
curve.P
33+
);
34+
Point add = EcdsaMath.add(
35+
u1,
36+
u2,
37+
curve.A,
38+
curve.P
39+
);
40+
41+
return sigR == add.x;
42+
}
43+
44+
private static string sha256(string message)
45+
{
46+
byte[] bytes;
47+
48+
using (SHA256 sha256Hash = SHA256.Create())
49+
{
50+
bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(message));
51+
}
52+
53+
StringBuilder builder = new StringBuilder();
54+
for (int i = 0; i < bytes.Length; i++)
55+
{
56+
builder.Append(bytes[i].ToString("x2"));
57+
}
58+
59+
return builder.ToString();
60+
}
61+
62+
}
63+
64+
}

0 commit comments

Comments
 (0)