Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
EdDSA.cs
1using System;
2using System.IO;
3using System.Numerics;
5
7{
12 public static class EdDSA
13 {
24 public static byte[] Sign(byte[] Data, bool BigEndian, byte[] PrivateKey, byte[] Prefix,
26 {
27 // 5.1.6 of RFC 8032
28
29 int ScalarBytes = PrivateKey.Length;
30
31 if (Prefix.Length != ScalarBytes)
32 throw new ArgumentException("Invalid prefix.", nameof(Prefix));
33
34 BigInteger a = EllipticCurve.ToInt(PrivateKey);
35 PointOnCurve P = Curve.ScalarMultiplication(PrivateKey, Curve.BasePoint, true);
36 byte[] A = Encode(P, BigEndian, Curve);
37 int c = Data.Length;
38 byte[] Bin = new byte[ScalarBytes + c]; // dom2(F, C) = blank string
39 Buffer.BlockCopy(Prefix, 0, Bin, 0, ScalarBytes); // prefix
40 Buffer.BlockCopy(Data, 0, Bin, ScalarBytes, c); // PH(M)=M
41
42 byte[] h = HashFunction(Bin);
43 BigInteger r = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
44 PointOnCurve R = Curve.ScalarMultiplication(r, Curve.BasePoint, true);
45 byte[] Rs = Encode(R, BigEndian, Curve);
46
47 Bin = new byte[(ScalarBytes << 1) + c]; // dom2(F, C) = blank string
48 Buffer.BlockCopy(Rs, 0, Bin, 0, ScalarBytes);
49 Buffer.BlockCopy(A, 0, Bin, ScalarBytes, ScalarBytes);
50 Buffer.BlockCopy(Data, 0, Bin, ScalarBytes << 1, c); // PH(M)=M
51
52 h = HashFunction(Bin);
53
54 BigInteger k = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
55 BigInteger s = Curve.ModulusN.Add(r, Curve.ModulusN.Multiply(k, a));
56
57 Bin = s.ToByteArray();
58 if (Bin.Length != ScalarBytes)
59 Array.Resize(ref Bin, ScalarBytes);
60
61 byte[] Signature = new byte[ScalarBytes << 1];
62
63 Buffer.BlockCopy(Rs, 0, Signature, 0, ScalarBytes);
64 Buffer.BlockCopy(Bin, 0, Signature, ScalarBytes, ScalarBytes);
65
66 return Signature;
67 }
68
79 public static byte[] Sign(Stream Data, bool BigEndian, byte[] PrivateKey,
81 {
82 // 5.1.6 of RFC 8032
83
84 int ScalarBytes = PrivateKey.Length;
85
86 if (Prefix.Length != ScalarBytes)
87 throw new ArgumentException("Invalid prefix.", nameof(Prefix));
88
89 BigInteger a = EllipticCurve.ToInt(PrivateKey);
90 PointOnCurve P = Curve.ScalarMultiplication(PrivateKey, Curve.BasePoint, true);
91 byte[] A = Encode(P, BigEndian, Curve);
92 byte[] h;
93
94 using (TemporaryStream TempFile = new TemporaryStream()) // dom2(F, C) = blank string
95 {
96 TempFile.Write(Prefix, 0, ScalarBytes); // prefix
97
98 Data.Position = 0;
99 Data.CopyTo(TempFile); // PH(M)=M
100
101 TempFile.Position = 0;
102 h = HashFunction(TempFile);
103 }
104
105 BigInteger r = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
106 PointOnCurve R = Curve.ScalarMultiplication(r, Curve.BasePoint, true);
107 byte[] Rs = Encode(R, BigEndian, Curve);
108
109 using (TemporaryStream TempFile = new TemporaryStream()) // dom2(F, C) = blank string
110 {
111 TempFile.Write(Rs, 0, ScalarBytes);
112 TempFile.Write(A, 0, ScalarBytes);
113
114 Data.Position = 0;
115 Data.CopyTo(TempFile); // PH(M)=M
116
117 TempFile.Position = 0;
118 h = HashFunction(TempFile);
119 }
120
121 BigInteger k = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
122 BigInteger s = Curve.ModulusN.Add(r, Curve.ModulusN.Multiply(k, a));
123
124 byte[] Bin = s.ToByteArray();
125 if (Bin.Length != ScalarBytes)
126 Array.Resize(ref Bin, ScalarBytes);
127
128 byte[] Signature = new byte[ScalarBytes << 1];
129
130 Buffer.BlockCopy(Rs, 0, Signature, 0, ScalarBytes);
131 Buffer.BlockCopy(Bin, 0, Signature, ScalarBytes, ScalarBytes);
132
133 return Signature;
134 }
135
143 public static byte[] Encode(PointOnCurve P, bool BigEndian, EdwardsCurveBase Curve)
144 {
145 int ScalarBits = Curve.CoordinateBits;
146 int ScalarBytes = (ScalarBits + 9) >> 3;
147
148 byte[] y = P.Y.ToByteArray(); // Little endian
149 if (y.Length != ScalarBytes)
150 Array.Resize(ref y, ScalarBytes);
151
152 byte[] x = P.X.ToByteArray(); // Little endian
153 int Msb = (ScalarBits + 1) & 7;
154
155 byte Mask = (byte)(0xff >> (8 - Msb));
156 y[ScalarBytes - 1] &= Mask;
157
158 if ((x[0] & 1) != 0)
159 y[ScalarBytes - 1] |= 0x80; // Always MSB
160
161 if (BigEndian)
162 Array.Reverse(y);
163
164 return y;
165 }
166
174 public static PointOnCurve Decode(byte[] Encoded, bool BigEndian, EdwardsCurveBase Curve)
175 {
176 int ScalarBits = Curve.CoordinateBits;
177 int ScalarBytes = (ScalarBits + 9) >> 3;
178
179 if (Encoded.Length != ScalarBytes)
180 throw new ArgumentException("Not encoded properly.", nameof(Encoded));
181
182 if (BigEndian)
183 {
184 Encoded = (byte[])Encoded.Clone();
185 Array.Reverse(Encoded);
186 }
187
188 bool x0 = (Encoded[ScalarBytes - 1] & 0x80) != 0;
189 if (x0)
190 Encoded[ScalarBytes - 1] &= 0x7f;
191
192 BigInteger y = EllipticCurve.ToInt(Encoded);
193 if (y >= Curve.Prime)
194 throw new ArgumentException("Not a valid point.", nameof(Encoded));
195
196 if (x0)
197 Encoded[ScalarBytes - 1] |= 0x80;
198
199 BigInteger x = Curve.GetX(y, x0);
200
201 return new PointOnCurve(x, y);
202 }
203
214 public static bool Verify(byte[] Data, byte[] PublicKey, bool BigEndian, HashFunctionArray HashFunction,
215 EdwardsCurveBase Curve, byte[] Signature)
216 {
217 try
218 {
219 int ScalarBytes = Signature.Length;
220 if ((ScalarBytes & 1) != 0)
221 return false;
222
223 ScalarBytes >>= 1;
224
225 byte[] R = new byte[ScalarBytes];
226 Buffer.BlockCopy(Signature, 0, R, 0, ScalarBytes);
227 PointOnCurve r = Decode(R, BigEndian, Curve);
228 byte[] S = new byte[ScalarBytes];
229 Buffer.BlockCopy(Signature, ScalarBytes, S, 0, ScalarBytes);
230 BigInteger s = EllipticCurve.ToInt(S);
231
232 if (s >= Curve.Order)
233 return false;
234
235 int c = Data.Length;
236 byte[] Bin = new byte[(ScalarBytes << 1) + c]; // dom2(F, C) = blank string
237 Buffer.BlockCopy(R, 0, Bin, 0, ScalarBytes);
238 Buffer.BlockCopy(PublicKey, 0, Bin, ScalarBytes, ScalarBytes);
239 Buffer.BlockCopy(Data, 0, Bin, ScalarBytes << 1, c); // PH(M)=M
240
241 byte[] h = HashFunction(Bin);
242
243 BigInteger k = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
244 PointOnCurve P1 = Curve.ScalarMultiplication(s, Curve.BasePoint, false);
245 PointOnCurve P2 = Curve.ScalarMultiplication(k, Curve.Decode(PublicKey, BigEndian), false);
246 Curve.AddTo(ref P2, r);
247
248 P1.Normalize(Curve);
249 P2.Normalize(Curve);
250
251 return P1.Equals(P2);
252 }
253 catch (ArgumentException)
254 {
255 return false;
256 }
257 }
258
269 public static bool Verify(Stream Data, byte[] PublicKey, bool BigEndian,
270 HashFunctionStream HashFunction, EdwardsCurveBase Curve, byte[] Signature)
271 {
272 try
273 {
274 int ScalarBytes = Signature.Length;
275 if ((ScalarBytes & 1) != 0)
276 return false;
277
278 ScalarBytes >>= 1;
279
280 byte[] R = new byte[ScalarBytes];
281 Buffer.BlockCopy(Signature, 0, R, 0, ScalarBytes);
282 PointOnCurve r = Decode(R, BigEndian, Curve);
283 byte[] S = new byte[ScalarBytes];
284 Buffer.BlockCopy(Signature, ScalarBytes, S, 0, ScalarBytes);
285 BigInteger s = EllipticCurve.ToInt(S);
286 byte[] h;
287
288 if (s >= Curve.Order)
289 return false;
290
291 using (TemporaryStream TempFile = new TemporaryStream()) // dom2(F, C) = blank string
292 {
293 TempFile.Write(R, 0, ScalarBytes);
294 TempFile.Write(PublicKey, 0, ScalarBytes);
295
296 Data.Position = 0;
297 Data.CopyTo(TempFile); // PH(M)=M
298
299 TempFile.Position = 0;
300 h = HashFunction(TempFile);
301 }
302
303 BigInteger k = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
304 PointOnCurve P1 = Curve.ScalarMultiplication(s, Curve.BasePoint, false);
305 PointOnCurve P2 = Curve.ScalarMultiplication(k, Curve.Decode(PublicKey, BigEndian), false);
306 Curve.AddTo(ref P2, r);
307
308 P1.Normalize(Curve);
309 P2.Normalize(Curve);
310
311 return P1.Equals(P2);
312 }
313 catch (ArgumentException)
314 {
315 return false;
316 }
317 }
318
319 }
320}
Manages a temporary stream. Contents is kept in-memory, if below a memory threshold,...
override void Write(byte[] buffer, int offset, int count)
When overridden in a derived class, writes a sequence of bytes to the current stream and advances the...
Implements the Edwards curve Digital Signature Algorithm (EdDSA), as defined in RFC 8032....
Definition: EdDSA.cs:13
static byte[] Sign(Stream Data, bool BigEndian, byte[] PrivateKey, byte[] Prefix, HashFunctionStream HashFunction, EdwardsCurveBase Curve)
Signs data using the EdDSA algorithm.
Definition: EdDSA.cs:79
static bool Verify(byte[] Data, byte[] PublicKey, bool BigEndian, HashFunctionArray HashFunction, EdwardsCurveBase Curve, byte[] Signature)
Verifies a signature of Data made by the EdDSA algorithm.
Definition: EdDSA.cs:214
static byte[] Sign(byte[] Data, bool BigEndian, byte[] PrivateKey, byte[] Prefix, HashFunctionArray HashFunction, EdwardsCurveBase Curve)
Signs data using the EdDSA algorithm.
Definition: EdDSA.cs:24
static bool Verify(Stream Data, byte[] PublicKey, bool BigEndian, HashFunctionStream HashFunction, EdwardsCurveBase Curve, byte[] Signature)
Verifies a signature of Data made by the EdDSA algorithm.
Definition: EdDSA.cs:269
static PointOnCurve Decode(byte[] Encoded, bool BigEndian, EdwardsCurveBase Curve)
Decodes a point on the curve in accordance with §5.1.3 of RFC 8032.
Definition: EdDSA.cs:174
static byte[] Encode(PointOnCurve P, bool BigEndian, EdwardsCurveBase Curve)
Encodes a point on the curve in accordance with §5.1.2 of RFC 8032.
Definition: EdDSA.cs:143
Base class of different types of Edwards curves over a prime field.
abstract BigInteger GetX(BigInteger Y, bool X0)
Gets the X-coordinate that corresponds to a given Y-coordainte, and the first bit of the X-coordinate...
override PointOnCurve Decode(byte[] Point, bool BigEndian)
Decodes an encoded point on the curve.
abstract int CoordinateBits
Number of bits used to encode the y-coordinate.
Abstract base class for elliptic curves.
static BigInteger ToInt(byte[] Binary, bool BigEndian)
Converts a little-endian binary representation of a big integer to a BigInteger.
PointOnCurve BasePoint
Base-point of curve.
abstract void AddTo(ref PointOnCurve P, PointOnCurve Q)
Adds Q to P .
BigInteger Multiply(BigInteger a, BigInteger b)
Multiplies two numbers, modulus p
Definition: ModulusP.cs:80
BigInteger Add(BigInteger a, BigInteger b)
Adds two numbers, modulus p
Definition: ModulusP.cs:31
override PointOnCurve ScalarMultiplication(byte[] N, PointOnCurve P, bool Normalize)
Performs the scalar multiplication of N *P .
ModulusP ModulusN
Arithmetic modulus n (the order)
delegate byte[] HashFunctionStream(Stream Data)
Delegate to hash function.
delegate byte[] HashFunctionArray(byte[] Data)
Delegate to hash function.
HashFunction
Hash method enumeration.
Definition: Hashes.cs:26
Represents a point on a curve.
Definition: PointOnCurve.cs:10
void Normalize(PrimeFieldCurve Curve)
Normalizes a point, if in homogeneous coorinates.