Skip to content

Commit 5659fde

Browse files
authored
Security update - by VaultCord.com
Security update
2 parents 5d842e4 + 26767e8 commit 5659fde

File tree

10 files changed

+1287
-246
lines changed

10 files changed

+1287
-246
lines changed

Console/App.config

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<?xml version="1.0" encoding="utf-8" ?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<configuration>
33
<startup>
4-
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
55
</startup>
6-
</configuration>
6+
</configuration>

Console/Ed25519.cs

Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Numerics;
6+
using System.Security.Cryptography;
7+
8+
namespace Cryptographic
9+
{
10+
/* Ported and refactored from Java to C# by Hans Wolff, 10/10/2013
11+
* Released to the public domain
12+
* /
13+
14+
/* Java code written by k3d3
15+
* Source: https://github.com/k3d3/ed25519-java/blob/master/ed25519.java
16+
* Released to the public domain
17+
*/
18+
19+
public class Ed25519
20+
{
21+
private static byte[] ComputeHash(byte[] m)
22+
{
23+
using (var sha512 = SHA512.Create()) // System.Security.Cryptography
24+
{
25+
return sha512.ComputeHash(m);
26+
}
27+
}
28+
29+
private static BigInteger ExpMod(BigInteger number, BigInteger exponent, BigInteger modulo)
30+
{
31+
BigInteger result = BigInteger.One;
32+
BigInteger baseVal = number.Mod(modulo);
33+
34+
while (exponent > 0)
35+
{
36+
if (!exponent.IsEven)
37+
{
38+
result = (result * baseVal).Mod(modulo);
39+
}
40+
baseVal = (baseVal * baseVal).Mod(modulo);
41+
exponent /= 2;
42+
}
43+
44+
return result;
45+
}
46+
47+
48+
private static readonly Dictionary<BigInteger, BigInteger> InverseCache = new Dictionary<BigInteger, BigInteger>();
49+
50+
private static BigInteger Inv(BigInteger x)
51+
{
52+
if (!InverseCache.ContainsKey(x))
53+
{
54+
InverseCache[x] = ExpMod(x, Qm2, Q);
55+
}
56+
return InverseCache[x];
57+
}
58+
59+
private static BigInteger RecoverX(BigInteger y)
60+
{
61+
BigInteger y2 = y * y;
62+
BigInteger xx = (y2 - 1) * Inv(D * y2 + 1);
63+
BigInteger x = ExpMod(xx, Qp3 / Eight, Q);
64+
if (!(x * x - xx).Mod(Q).Equals(BigInteger.Zero))
65+
{
66+
x = (x * I).Mod(Q);
67+
}
68+
if (!x.IsEven)
69+
{
70+
x = Q - x;
71+
}
72+
return x;
73+
}
74+
75+
private static Tuple<BigInteger, BigInteger> Edwards(BigInteger px, BigInteger py, BigInteger qx, BigInteger qy)
76+
{
77+
BigInteger xx12 = px * qx;
78+
BigInteger yy12 = py * qy;
79+
BigInteger dtemp = D * xx12 * yy12;
80+
BigInteger x3 = (px * qy + qx * py) * (Inv(1 + dtemp));
81+
BigInteger y3 = (py * qy + xx12) * (Inv(1 - dtemp));
82+
return new Tuple<BigInteger, BigInteger>(x3.Mod(Q), y3.Mod(Q));
83+
}
84+
85+
private static Tuple<BigInteger, BigInteger> EdwardsSquare(BigInteger x, BigInteger y)
86+
{
87+
BigInteger xx = x * x;
88+
BigInteger yy = y * y;
89+
BigInteger dtemp = D * xx * yy;
90+
BigInteger x3 = (2 * x * y) * (Inv(1 + dtemp));
91+
BigInteger y3 = (yy + xx) * (Inv(1 - dtemp));
92+
return new Tuple<BigInteger, BigInteger>(x3.Mod(Q), y3.Mod(Q));
93+
}
94+
private static Tuple<BigInteger, BigInteger> ScalarMul(Tuple<BigInteger, BigInteger> point, BigInteger scalar)
95+
{
96+
var result = new Tuple<BigInteger, BigInteger>(BigInteger.Zero, BigInteger.One); // Neutral element
97+
var basePoint = point;
98+
99+
while (scalar > 0)
100+
{
101+
if (!scalar.IsEven) // If the current bit is set, add the base point to the result
102+
{
103+
result = Edwards(result.Item1, result.Item2, basePoint.Item1, basePoint.Item2);
104+
}
105+
106+
basePoint = EdwardsSquare(basePoint.Item1, basePoint.Item2); // Double the point
107+
scalar >>= 1; // Move to the next bit in the scalar
108+
}
109+
110+
return result;
111+
}
112+
113+
public static byte[] EncodeInt(BigInteger y)
114+
{
115+
byte[] nin = y.ToByteArray();
116+
var nout = new byte[Math.Max(nin.Length, 32)];
117+
Array.Copy(nin, nout, nin.Length);
118+
return nout;
119+
}
120+
121+
public static byte[] EncodePoint(BigInteger x, BigInteger y)
122+
{
123+
byte[] nout = EncodeInt(y);
124+
nout[nout.Length - 1] |= (x.IsEven ? (byte)0 : (byte)0x80);
125+
return nout;
126+
}
127+
128+
private static int GetBit(byte[] h, int i)
129+
{
130+
return h[i / 8] >> (i % 8) & 1;
131+
}
132+
133+
public static byte[] PublicKey(byte[] signingKey)
134+
{
135+
byte[] h = ComputeHash(signingKey);
136+
BigInteger a = TwoPowBitLengthMinusTwo;
137+
for (int i = 3; i < (BitLength - 2); i++)
138+
{
139+
var bit = GetBit(h, i);
140+
if (bit != 0)
141+
{
142+
a += TwoPowCache[i];
143+
}
144+
}
145+
var bigA = ScalarMul(B, a);
146+
return EncodePoint(bigA.Item1, bigA.Item2);
147+
}
148+
149+
private static BigInteger HashInt(byte[] m)
150+
{
151+
byte[] h = ComputeHash(m);
152+
BigInteger hsum = BigInteger.Zero;
153+
for (int i = 0; i < 2 * BitLength; i++)
154+
{
155+
var bit = GetBit(h, i);
156+
if (bit != 0)
157+
{
158+
hsum += TwoPowCache[i];
159+
}
160+
}
161+
return hsum;
162+
}
163+
164+
public static byte[] Signature(byte[] message, byte[] signingKey, byte[] publicKey)
165+
{
166+
byte[] h = ComputeHash(signingKey);
167+
BigInteger a = TwoPowBitLengthMinusTwo;
168+
for (int i = 3; i < (BitLength - 2); i++)
169+
{
170+
var bit = GetBit(h, i);
171+
if (bit != 0)
172+
{
173+
a += TwoPowCache[i];
174+
}
175+
}
176+
177+
BigInteger r;
178+
using (var rsub = new MemoryStream((BitLength / 8) + message.Length))
179+
{
180+
rsub.Write(h, BitLength / 8, BitLength / 4 - BitLength / 8);
181+
rsub.Write(message, 0, message.Length);
182+
r = HashInt(rsub.ToArray());
183+
}
184+
var bigR = ScalarMul(B, r);
185+
BigInteger s;
186+
var encodedBigR = EncodePoint(bigR.Item1, bigR.Item2);
187+
using (var stemp = new MemoryStream(32 + publicKey.Length + message.Length))
188+
{
189+
stemp.Write(encodedBigR, 0, encodedBigR.Length);
190+
stemp.Write(publicKey, 0, publicKey.Length);
191+
stemp.Write(message, 0, message.Length);
192+
s = (r+ HashInt(stemp.ToArray()) * a).Mod(L);
193+
}
194+
195+
using (var nout = new MemoryStream(64))
196+
{
197+
nout.Write(encodedBigR, 0, encodedBigR.Length);
198+
var encodeInt = EncodeInt(s);
199+
nout.Write(encodeInt, 0, encodeInt.Length);
200+
return nout.ToArray();
201+
}
202+
}
203+
204+
private static bool IsOnCurve(BigInteger x, BigInteger y)
205+
{
206+
BigInteger xx = x * x;
207+
BigInteger yy = y * y;
208+
BigInteger dxxyy = D * yy * xx;
209+
return (yy - xx - dxxyy - 1).Mod(Q).Equals(BigInteger.Zero);
210+
}
211+
212+
private static BigInteger DecodeInt(byte[] s)
213+
{
214+
return new BigInteger(s) & Un;
215+
}
216+
217+
private static Tuple<BigInteger, BigInteger> DecodePoint(byte[] pointBytes)
218+
{
219+
BigInteger y = new BigInteger(pointBytes) & Un;
220+
BigInteger x = RecoverX(y);
221+
if ((x.IsEven ? 0 : 1) != GetBit(pointBytes, BitLength - 1))
222+
{
223+
x = Q - x;
224+
}
225+
var point = new Tuple<BigInteger, BigInteger>(x, y);
226+
if (!IsOnCurve(x, y)) throw new ArgumentException("Decoding point that is not on curve");
227+
return point;
228+
}
229+
230+
public static bool CheckValid(byte[] signature, byte[] message, byte[] publicKey)
231+
{
232+
Console.Write("."); // ... dots in console
233+
if (signature.Length != BitLength / 4) throw new ArgumentException("Signature length is wrong");
234+
if (publicKey.Length != BitLength / 8) throw new ArgumentException("Public key length is wrong");
235+
236+
byte[] rByte = Arrays.CopyOfRange(signature, 0, BitLength / 8);
237+
238+
var r = DecodePoint(rByte);
239+
var a = DecodePoint(publicKey);
240+
241+
byte[] sByte = Arrays.CopyOfRange(signature, BitLength / 8, BitLength / 4);
242+
243+
BigInteger s = DecodeInt(sByte);
244+
BigInteger h;
245+
246+
using (var stemp = new MemoryStream(32 + publicKey.Length + message.Length))
247+
{
248+
var encodePoint = EncodePoint(r.Item1, r.Item2);
249+
stemp.Write(encodePoint, 0, encodePoint.Length);
250+
stemp.Write(publicKey, 0, publicKey.Length);
251+
stemp.Write(message, 0, message.Length);
252+
h = HashInt(stemp.ToArray());
253+
}
254+
255+
Console.Write("."); // ... dots in console
256+
var ra = ScalarMul(B, s);
257+
Console.Write("."); // ... dots in console
258+
var ah = ScalarMul(a, h);
259+
var rb = Edwards(r.Item1, r.Item2, ah.Item1, ah.Item2);
260+
if (!ra.Item1.Equals(rb.Item1) || !ra.Item2.Equals(rb.Item2))
261+
return false;
262+
return true;
263+
}
264+
265+
private const int BitLength = 256;
266+
267+
private static readonly BigInteger TwoPowBitLengthMinusTwo = BigInteger.Pow(2, BitLength - 2);
268+
private static readonly BigInteger[] TwoPowCache = Enumerable.Range(0, 2 * BitLength).Select(i => BigInteger.Pow(2, i)).ToArray();
269+
270+
private static readonly BigInteger Q =
271+
BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819949");
272+
273+
private static readonly BigInteger Qm2 =
274+
BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819947");
275+
276+
private static readonly BigInteger Qp3 =
277+
BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819952");
278+
279+
private static readonly BigInteger L =
280+
BigInteger.Parse("7237005577332262213973186563042994240857116359379907606001950938285454250989");
281+
282+
private static readonly BigInteger D =
283+
BigInteger.Parse("-4513249062541557337682894930092624173785641285191125241628941591882900924598840740");
284+
285+
private static readonly BigInteger I =
286+
BigInteger.Parse("19681161376707505956807079304988542015446066515923890162744021073123829784752");
287+
288+
private static readonly BigInteger By =
289+
BigInteger.Parse("46316835694926478169428394003475163141307993866256225615783033603165251855960");
290+
291+
private static readonly BigInteger Bx =
292+
BigInteger.Parse("15112221349535400772501151409588531511454012693041857206046113283949847762202");
293+
294+
private static readonly Tuple<BigInteger, BigInteger> B = new Tuple<BigInteger, BigInteger>(Bx.Mod(Q), By.Mod(Q));
295+
296+
private static readonly BigInteger Un =
297+
BigInteger.Parse("57896044618658097711785492504343953926634992332820282019728792003956564819967");
298+
299+
private static readonly BigInteger Two = new BigInteger(2);
300+
private static readonly BigInteger Eight = new BigInteger(8);
301+
}
302+
303+
internal static class Arrays
304+
{
305+
public static byte[] CopyOfRange(byte[] original, int from, int to)
306+
{
307+
int length = to - from;
308+
var result = new byte[length];
309+
Array.Copy(original, from, result, 0, length);
310+
return result;
311+
}
312+
}
313+
314+
internal static class BigIntegerHelpers
315+
{
316+
public static BigInteger Mod(this BigInteger num, BigInteger modulo)
317+
{
318+
var result = num % modulo;
319+
return result < 0 ? result + modulo : result;
320+
}
321+
}
322+
}

0 commit comments

Comments
 (0)