Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
EllipticCurve.cs
1using System;
2using System.IO;
3using System.Numerics;
4using System.Security.Cryptography;
5using System.Text;
6using System.Xml;
7
9{
13 public abstract class EllipticCurve : ISignatureAlgorithm
14 {
18 public const string Namespace = "http://waher.se/Schema/EllipticCurves.xsd";
19
23 public static readonly BigInteger Two = new BigInteger(2);
24
28 public const string ElementName = "EllipticCurve";
29
33 protected static readonly RandomNumberGenerator rnd = RandomNumberGenerator.Create();
34
38 protected readonly PointOnCurve g;
39
43 protected readonly BigInteger n;
44
48 protected readonly int cofactor;
49
53 protected readonly int orderBits;
54
58 protected readonly int orderBytes;
59
63 protected readonly byte msbOrderMask;
64
65 private byte[] secret;
66 private byte[] privateKey;
67 private byte[] publicKey;
68 private byte[] additionalInfo;
69 private PointOnCurve publicKeyPoint;
70
78 : this(BasePoint, Order, Cofactor, null)
79 {
80 }
81
90 byte[] Secret)
91 {
92 this.g = BasePoint;
93 this.n = Order;
94 this.cofactor = Cofactor;
95 this.secret = Secret;
96 this.privateKey = null;
97 this.publicKey = null;
98 this.additionalInfo = null;
99
100 this.orderBits = ModulusP.CalcBits(this.n);
101 this.orderBytes = (this.orderBits + 7) >> 3;
102 this.msbOrderMask = 0xff;
103
104 int MaskBits = (8 - this.orderBits) & 7;
105 if (MaskBits == 0)
106 {
107 this.orderBytes++;
108 this.msbOrderMask = 0;
109 }
110 else
111 this.msbOrderMask >>= MaskBits;
112 }
113
117 protected virtual void Init()
118 {
119 if (this.secret is null)
120 this.secret = this.GenerateSecret();
121
122 this.SetPrivateKey(this.secret);
123 }
124
128 protected byte[] PrivateKey
129 {
130 get
131 {
132 if (this.privateKey is null)
133 this.Init();
134
135 return this.privateKey;
136 }
137 }
138
142 public virtual byte[] PublicKey
143 {
144 get
145 {
146 if (this.publicKey is null)
147 this.Init();
148
149 return this.publicKey;
150 }
151 }
152
156 protected byte[] AdditionalInfo
157 {
158 get
159 {
160 if (this.additionalInfo is null)
161 this.Init();
162
163 return this.additionalInfo;
164 }
165 }
166
171 {
172 get
173 {
174 if (this.publicKey is null)
175 this.Init();
176
177 return this.publicKeyPoint;
178 }
179
180 internal set
181 {
182 this.publicKeyPoint = value;
183 }
184 }
185
189 public abstract string CurveName
190 {
191 get;
192 }
193
197 public BigInteger Order => this.n;
198
202 public int OrderBytes => this.orderBytes;
203
207 public int OrderBits => this.orderBits;
208
212 public int Cofactor => this.cofactor;
213
217 public PointOnCurve BasePoint => this.g;
218
223 public abstract byte[] GenerateSecret();
224
229 public virtual void SetPrivateKey(byte[] Secret)
230 {
231 Tuple<byte[], byte[]> Info = this.CalculatePrivateKey(Secret);
232 PointOnCurve P = this.ScalarMultiplication(Info.Item1, this.g, true);
233
234 this.publicKey = this.Encode(P);
235 this.publicKeyPoint = P;
236 this.privateKey = Info.Item1;
237 this.additionalInfo = Info.Item2;
238 this.secret = Secret;
239 }
240
246 public virtual Tuple<byte[], byte[]> CalculatePrivateKey(byte[] Secret)
247 {
248 return new Tuple<byte[], byte[]>(Secret, null);
249 }
250
256 public virtual byte[] Encode(PointOnCurve Point)
257 {
258 byte[] X = Point.X.ToByteArray();
259 byte[] Y = Point.Y.ToByteArray();
260
261 if (X.Length != this.orderBytes)
262 Array.Resize(ref X, this.orderBytes);
263
264 if (Y.Length != this.orderBytes)
265 Array.Resize(ref Y, this.orderBytes);
266
267 byte[] Result = new byte[this.orderBytes << 1];
268
269 Array.Copy(X, 0, Result, 0, this.orderBytes);
270 Array.Copy(Y, 0, Result, this.orderBytes, this.orderBytes);
271
272 return Result;
273 }
274
280 public virtual PointOnCurve Decode(byte[] Point)
281 {
282 if (Point.Length != this.orderBytes << 1)
283 throw new ArgumentException("Invalid point.", nameof(Point));
284
285 int XLen = this.orderBytes;
286 int YLen = this.orderBytes;
287
288 if ((Point[this.orderBytes - 1] & 0x80) != 0)
289 XLen++;
290
291 if ((Point[Point.Length - 1] & 0x80) != 0)
292 YLen++;
293
294 byte[] X = new byte[XLen];
295 byte[] Y = new byte[YLen];
296
297 Array.Copy(Point, 0, X, 0, this.orderBytes);
298 Array.Copy(Point, this.orderBytes, Y, 0, this.orderBytes);
299
300 return new PointOnCurve(new BigInteger(X), new BigInteger(Y));
301 }
302
306 public void GenerateKeys()
307 {
308 this.SetPrivateKey(this.GenerateSecret());
309 }
310
318 public PointOnCurve ScalarMultiplication(BigInteger N, PointOnCurve P, bool Normalize)
319 {
320 return this.ScalarMultiplication(N.ToByteArray(), P, Normalize);
321 }
322
330 public virtual PointOnCurve ScalarMultiplication(byte[] N, PointOnCurve P, bool Normalize)
331 {
332 PointOnCurve Result = this.Zero;
333 int i, c = N.Length;
334 byte b, Bit;
335
336 for (i = 0; i < c; i++)
337 {
338 b = N[i];
339
340 for (Bit = 1; Bit != 0; Bit <<= 1)
341 {
342 if ((b & Bit) != 0)
343 this.AddTo(ref Result, P);
344
345 this.Double(ref P);
346 }
347 }
348
349 return Result;
350 }
351
355 public virtual PointOnCurve Zero
356 {
357 get
358 {
359 return new PointOnCurve(BigInteger.Zero, BigInteger.Zero);
360 }
361 }
362
369 public abstract void AddTo(ref PointOnCurve P, PointOnCurve Q);
370
375 public abstract void Double(ref PointOnCurve P);
376
385 public virtual byte[] GetSharedKey(byte[] RemotePublicKey, HashFunctionArray HashFunction)
386 {
387 return ECDH.GetSharedKey(this.PrivateKey, RemotePublicKey, HashFunction, this);
388 }
389
395 public abstract byte[] Sign(byte[] Data);
396
402 public abstract byte[] Sign(Stream Data);
403
411 public abstract bool Verify(byte[] Data, byte[] PublicKey, byte[] Signature);
412
420 public abstract bool Verify(Stream Data, byte[] PublicKey, byte[] Signature);
421
426 public virtual void Export(XmlWriter Output)
427 {
428 if (this.secret is null)
429 this.Init();
430
431 Output.WriteStartElement(ElementName, Namespace);
432 Output.WriteAttributeString("type", this.GetType().FullName);
433 Output.WriteAttributeString("d", Convert.ToBase64String(this.secret));
434 Output.WriteEndElement();
435 }
436
440 public string Export()
441 {
442 XmlWriterSettings Settings = new XmlWriterSettings()
443 {
444 Indent = false,
445 OmitXmlDeclaration = true
446 };
447 StringBuilder sb = new StringBuilder();
448 using (XmlWriter w = XmlWriter.Create(sb, Settings))
449 {
450 this.Export(w);
451 w.Flush();
452 }
453
454 return sb.ToString();
455 }
456
463 public static BigInteger ToInt(byte[] Binary)
464 {
465 int c = Binary.Length;
466 if ((Binary[c - 1] & 0x80) != 0)
467 Array.Resize(ref Binary, c + 1);
468
469 return new BigInteger(Binary);
470 }
471 }
472}
Implements the Elliptic Curve Diffie-Hellman (ECDH) algorithm.
Definition: ECDH.cs:11
static byte[] GetSharedKey(byte[] LocalPrivateKey, byte[] RemotePublicKey, HashFunctionArray HashFunction, EllipticCurve Curve)
Gets a shared key using the Elliptic Curve Diffie-Hellman (ECDH) algorithm.
Definition: ECDH.cs:22
Abstract base class for elliptic curves.
virtual PointOnCurve ScalarMultiplication(byte[] N, PointOnCurve P, bool Normalize)
Performs the scalar multiplication of N *P .
EllipticCurve(PointOnCurve BasePoint, BigInteger Order, int Cofactor)
Abstract base class for elliptic curves.
readonly PointOnCurve g
Base point
abstract bool Verify(Stream Data, byte[] PublicKey, byte[] Signature)
Verifies a signature of Data made by the ECDSA algorithm.
readonly int orderBits
Number of bits used for the order of the curve.
abstract string CurveName
Name of curve.
virtual Tuple< byte[], byte[]> CalculatePrivateKey(byte[] Secret)
Calculates a private key from a secret.
abstract byte[] GenerateSecret()
Generates a new secret.
abstract bool Verify(byte[] Data, byte[] PublicKey, byte[] Signature)
Verifies a signature of Data made by the ECDSA algorithm.
readonly int orderBytes
Number of bytes used for the order of the curve.
byte[] AdditionalInfo
Curve-specific additional information
int OrderBits
Number of bits required to represent the order of the curve.
virtual PointOnCurve Decode(byte[] Point)
Decodes an encoded point on the curve.
abstract void Double(ref PointOnCurve P)
Doubles a point on the curve.
EllipticCurve(PointOnCurve BasePoint, BigInteger Order, int Cofactor, byte[] Secret)
Abstract base class for elliptic curves.
virtual void Export(XmlWriter Output)
Exports the curve parameters to XML.
virtual byte[] Encode(PointOnCurve Point)
Encodes a point on the curve.
abstract byte[] Sign(Stream Data)
Creates a signature of Data using the ECDSA algorithm.
abstract byte[] Sign(byte[] Data)
Creates a signature of Data using the ECDSA algorithm.
string Export()
Exports the curve parameters to an XML string.
int OrderBytes
Number of bytes required to represent the order of the curve.
static BigInteger ToInt(byte[] Binary)
Converts a little-endian binary representation of a big integer to a BigInteger.
const string ElementName
"EllipticCurve"
virtual byte[] PublicKey
Encoded public key
void GenerateKeys()
Generates a new Private Key.
virtual void Init()
Method initiazing the elliptic curve properties.
virtual PointOnCurve Zero
Neutral point.
static readonly RandomNumberGenerator rnd
Random number generator
const string Namespace
http://waher.se/Schema/EllipticCurves.xsd
PointOnCurve BasePoint
Base-point of curve.
virtual byte[] GetSharedKey(byte[] RemotePublicKey, HashFunctionArray HashFunction)
Gets a shared key using the Elliptic Curve Diffie-Hellman (ECDH) algorithm.
virtual void SetPrivateKey(byte[] Secret)
Sets the private key (and therefore also the public key) of the curve.
virtual PointOnCurve PublicKeyPoint
Public key, as a point on the elliptic curve.
readonly byte msbOrderMask
Mask for most significant byte of scalars.
abstract void AddTo(ref PointOnCurve P, PointOnCurve Q)
Adds Q to P .
PointOnCurve ScalarMultiplication(BigInteger N, PointOnCurve P, bool Normalize)
Performs the scalar multiplication of N *P .
Integer arithmetic, modulus a prime.
Definition: ModulusP.cs:10
static int CalcBits(BigInteger n)
Calculates the number of bits used.
Definition: ModulusP.cs:225
Interface for digital signature algorithms.
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