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 {
23 public static byte[] Sign(byte[] Data, byte[] PrivateKey, byte[] Prefix,
25 {
26 // 5.1.6 of RFC 8032
27
28 int ScalarBytes = PrivateKey.Length;
29
30 if (Prefix.Length != ScalarBytes)
31 throw new ArgumentException("Invalid prefix.", nameof(Prefix));
32
33 BigInteger a = EllipticCurve.ToInt(PrivateKey);
34 PointOnCurve P = Curve.ScalarMultiplication(PrivateKey, Curve.BasePoint, true);
35 byte[] A = Encode(P, Curve);
36 int c = Data.Length;
37 byte[] Bin = new byte[ScalarBytes + c]; // dom2(F, C) = blank string
38 Array.Copy(Prefix, 0, Bin, 0, ScalarBytes); // prefix
39 Array.Copy(Data, 0, Bin, ScalarBytes, c); // PH(M)=M
40
41 byte[] h = HashFunction(Bin);
42 BigInteger r = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
43 PointOnCurve R = Curve.ScalarMultiplication(r, Curve.BasePoint, true);
44 byte[] Rs = Encode(R, Curve);
45
46 Bin = new byte[(ScalarBytes << 1) + c]; // dom2(F, C) = blank string
47 Array.Copy(Rs, 0, Bin, 0, ScalarBytes);
48 Array.Copy(A, 0, Bin, ScalarBytes, ScalarBytes);
49 Array.Copy(Data, 0, Bin, ScalarBytes << 1, c); // PH(M)=M
50
51 h = HashFunction(Bin);
52
53 BigInteger k = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
54 BigInteger s = Curve.ModulusN.Add(r, Curve.ModulusN.Multiply(k, a));
55
56 Bin = s.ToByteArray();
57 if (Bin.Length != ScalarBytes)
58 Array.Resize(ref Bin, ScalarBytes);
59
60 byte[] Signature = new byte[ScalarBytes << 1];
61
62 Array.Copy(Rs, 0, Signature, 0, ScalarBytes);
63 Array.Copy(Bin, 0, Signature, ScalarBytes, ScalarBytes);
64
65 return Signature;
66 }
67
77 public static byte[] Sign(Stream Data, byte[] PrivateKey, byte[] Prefix,
79 {
80 // 5.1.6 of RFC 8032
81
82 int ScalarBytes = PrivateKey.Length;
83
84 if (Prefix.Length != ScalarBytes)
85 throw new ArgumentException("Invalid prefix.", nameof(Prefix));
86
87 BigInteger a = EllipticCurve.ToInt(PrivateKey);
88 PointOnCurve P = Curve.ScalarMultiplication(PrivateKey, Curve.BasePoint, true);
89 byte[] A = Encode(P, Curve);
90 byte[] h;
91
92 using (TemporaryStream TempFile = new TemporaryStream()) // dom2(F, C) = blank string
93 {
94 TempFile.Write(Prefix, 0, ScalarBytes); // prefix
95
96 Data.Position = 0;
97 Data.CopyTo(TempFile); // PH(M)=M
98
99 TempFile.Position = 0;
100 h = HashFunction(TempFile);
101 }
102
103 BigInteger r = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
104 PointOnCurve R = Curve.ScalarMultiplication(r, Curve.BasePoint, true);
105 byte[] Rs = Encode(R, Curve);
106
107 using (TemporaryStream TempFile = new TemporaryStream()) // dom2(F, C) = blank string
108 {
109 TempFile.Write(Rs, 0, ScalarBytes);
110 TempFile.Write(A, 0, ScalarBytes);
111
112 Data.Position = 0;
113 Data.CopyTo(TempFile); // PH(M)=M
114
115 TempFile.Position = 0;
116 h = HashFunction(TempFile);
117 }
118
119 BigInteger k = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
120 BigInteger s = Curve.ModulusN.Add(r, Curve.ModulusN.Multiply(k, a));
121
122 byte[] Bin = s.ToByteArray();
123 if (Bin.Length != ScalarBytes)
124 Array.Resize(ref Bin, ScalarBytes);
125
126 byte[] Signature = new byte[ScalarBytes << 1];
127
128 Array.Copy(Rs, 0, Signature, 0, ScalarBytes);
129 Array.Copy(Bin, 0, Signature, ScalarBytes, ScalarBytes);
130
131 return Signature;
132 }
133
140 public static byte[] Encode(PointOnCurve P, EdwardsCurveBase Curve)
141 {
142 int ScalarBits = Curve.CoordinateBits;
143 int ScalarBytes = (ScalarBits + 9) >> 3;
144
145 byte[] y = P.Y.ToByteArray();
146 if (y.Length != ScalarBytes)
147 Array.Resize(ref y, ScalarBytes);
148
149 byte[] x = P.X.ToByteArray();
150 int Msb = (ScalarBits + 1) & 7;
151
152 byte Mask = (byte)(0xff >> (8 - Msb));
153 y[ScalarBytes - 1] &= Mask;
154
155 if ((x[0] & 1) != 0)
156 y[ScalarBytes - 1] |= 0x80; // Always MSB
157
158 return y;
159 }
160
167 public static PointOnCurve Decode(byte[] Encoded, EdwardsCurveBase Curve)
168 {
169 int ScalarBits = Curve.CoordinateBits;
170 int ScalarBytes = (ScalarBits + 9) >> 3;
171
172 if (Encoded.Length != ScalarBytes)
173 throw new ArgumentException("Not encoded properly.", nameof(Encoded));
174
175 bool x0 = (Encoded[ScalarBytes - 1] & 0x80) != 0;
176 if (x0)
177 Encoded[ScalarBytes - 1] &= 0x7f;
178
179 BigInteger y = EllipticCurve.ToInt(Encoded);
180 if (y >= Curve.Prime)
181 throw new ArgumentException("Not a valid point.", nameof(Encoded));
182
183 if (x0)
184 Encoded[ScalarBytes - 1] |= 0x80;
185
186 BigInteger x = Curve.GetX(y, x0);
187
188 return new PointOnCurve(x, y);
189 }
190
200 public static bool Verify(byte[] Data, byte[] PublicKey, HashFunctionArray HashFunction,
201 EdwardsCurveBase Curve, byte[] Signature)
202 {
203 try
204 {
205 int ScalarBytes = Signature.Length;
206 if ((ScalarBytes & 1) != 0)
207 return false;
208
209 ScalarBytes >>= 1;
210
211 byte[] R = new byte[ScalarBytes];
212 Array.Copy(Signature, 0, R, 0, ScalarBytes);
213 PointOnCurve r = Decode(R, Curve);
214 byte[] S = new byte[ScalarBytes];
215 Array.Copy(Signature, ScalarBytes, S, 0, ScalarBytes);
216 BigInteger s = EllipticCurve.ToInt(S);
217
218 if (s >= Curve.Order)
219 return false;
220
221 int c = Data.Length;
222 byte[] Bin = new byte[(ScalarBytes << 1) + c]; // dom2(F, C) = blank string
223 Array.Copy(R, 0, Bin, 0, ScalarBytes);
224 Array.Copy(PublicKey, 0, Bin, ScalarBytes, ScalarBytes);
225 Array.Copy(Data, 0, Bin, ScalarBytes << 1, c); // PH(M)=M
226
227 byte[] h = HashFunction(Bin);
228
229 BigInteger k = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
230 PointOnCurve P1 = Curve.ScalarMultiplication(s, Curve.BasePoint, false);
231 PointOnCurve P2 = Curve.ScalarMultiplication(k, Curve.Decode(PublicKey), false);
232 Curve.AddTo(ref P2, r);
233
234 P1.Normalize(Curve);
235 P2.Normalize(Curve);
236
237 return P1.Equals(P2);
238 }
239 catch (ArgumentException)
240 {
241 return false;
242 }
243 }
244
254 public static bool Verify(Stream Data, byte[] PublicKey, HashFunctionStream HashFunction,
255 EdwardsCurveBase Curve, byte[] Signature)
256 {
257 try
258 {
259 int ScalarBytes = Signature.Length;
260 if ((ScalarBytes & 1) != 0)
261 return false;
262
263 ScalarBytes >>= 1;
264
265 byte[] R = new byte[ScalarBytes];
266 Array.Copy(Signature, 0, R, 0, ScalarBytes);
267 PointOnCurve r = Decode(R, Curve);
268 byte[] S = new byte[ScalarBytes];
269 Array.Copy(Signature, ScalarBytes, S, 0, ScalarBytes);
270 BigInteger s = EllipticCurve.ToInt(S);
271 byte[] h;
272
273 if (s >= Curve.Order)
274 return false;
275
276 using (TemporaryStream TempFile = new TemporaryStream()) // dom2(F, C) = blank string
277 {
278 TempFile.Write(R, 0, ScalarBytes);
279 TempFile.Write(PublicKey, 0, ScalarBytes);
280
281 Data.Position = 0;
282 Data.CopyTo(TempFile); // PH(M)=M
283
284 TempFile.Position = 0;
285 h = HashFunction(TempFile);
286 }
287
288 BigInteger k = BigInteger.Remainder(EllipticCurve.ToInt(h), Curve.Order);
289 PointOnCurve P1 = Curve.ScalarMultiplication(s, Curve.BasePoint, false);
290 PointOnCurve P2 = Curve.ScalarMultiplication(k, Curve.Decode(PublicKey), false);
291 Curve.AddTo(ref P2, r);
292
293 P1.Normalize(Curve);
294 P2.Normalize(Curve);
295
296 return P1.Equals(P2);
297 }
298 catch (ArgumentException)
299 {
300 return false;
301 }
302 }
303
304 }
305}
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[] Encode(PointOnCurve P, EdwardsCurveBase Curve)
Encodes a point on the curve in accordance with §5.1.2 of RFC 8032.
Definition: EdDSA.cs:140
static byte[] Sign(Stream Data, byte[] PrivateKey, byte[] Prefix, HashFunctionStream HashFunction, EdwardsCurveBase Curve)
Signs data using the EdDSA algorithm.
Definition: EdDSA.cs:77
static byte[] Sign(byte[] Data, byte[] PrivateKey, byte[] Prefix, HashFunctionArray HashFunction, EdwardsCurveBase Curve)
Signs data using the EdDSA algorithm.
Definition: EdDSA.cs:23
static bool Verify(byte[] Data, byte[] PublicKey, HashFunctionArray HashFunction, EdwardsCurveBase Curve, byte[] Signature)
Verifies a signature of Data made by the EdDSA algorithm.
Definition: EdDSA.cs:200
static PointOnCurve Decode(byte[] Encoded, EdwardsCurveBase Curve)
Decodes a point on the curve in accordance with §5.1.3 of RFC 8032.
Definition: EdDSA.cs:167
static bool Verify(Stream Data, byte[] PublicKey, HashFunctionStream HashFunction, EdwardsCurveBase Curve, byte[] Signature)
Verifies a signature of Data made by the EdDSA algorithm.
Definition: EdDSA.cs:254
Base class of different types of Edwards curves over a prime field.
override PointOnCurve Decode(byte[] Point)
Decodes an encoded point on the curve.
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...
abstract int CoordinateBits
Number of bits used to encode the y-coordinate.
Abstract base class for elliptic curves.
static BigInteger ToInt(byte[] Binary)
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:28
Represents a point on a curve.
Definition: PointOnCurve.cs:11
void Normalize(PrimeFieldCurve Curve)
Normalizes a point, if in homogeneous coorinates.