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;
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 int bigIntegerBytes;
64
68 protected readonly byte msbOrderMask;
69
70 private byte[] secret;
71 private byte[] privateKey;
72 private byte[] publicKey;
73 private byte[] publicKeyBigEndian;
74 private byte[] additionalInfo;
75 private PointOnCurve publicKeyPoint;
76
84 : this(BasePoint, Order, Cofactor, null)
85 {
86 }
87
96 byte[] Secret)
97 {
98 this.g = BasePoint;
99 this.n = Order;
100 this.cofactor = Cofactor;
101 this.secret = Secret;
102 this.privateKey = null;
103 this.publicKey = null;
104 this.publicKeyBigEndian = null;
105 this.additionalInfo = null;
106
107 this.orderBits = ModulusP.CalcBits(this.n);
108 this.orderBytes = this.bigIntegerBytes = (this.orderBits + 7) >> 3;
109 this.msbOrderMask = 0xff;
110
111 int MaskBits = (8 - this.orderBits) & 7;
112 if (MaskBits == 0)
113 {
114 this.bigIntegerBytes++;
115 this.msbOrderMask = 0;
116 }
117 else
118 this.msbOrderMask >>= MaskBits;
119 }
120
124 protected virtual void Init()
125 {
126 if (this.secret is null)
127 this.secret = this.GenerateSecret();
128
129 this.SetPrivateKey(this.secret);
130 }
131
135 protected byte[] PrivateKey
136 {
137 get
138 {
139 if (this.privateKey is null)
140 this.Init();
141
142 return this.privateKey;
143 }
144 }
145
149 public virtual byte[] PublicKey
150 {
151 get
152 {
153 if (this.publicKey is null)
154 this.Init();
155
156 return this.publicKey;
157 }
158 }
159
163 public virtual byte[] PublicKeyBigEndian
164 {
165 get
166 {
167 if (this.publicKeyBigEndian is null)
168 this.Init();
169
170 return this.publicKeyBigEndian;
171 }
172 }
173
177 protected byte[] AdditionalInfo
178 {
179 get
180 {
181 if (this.additionalInfo is null)
182 this.Init();
183
184 return this.additionalInfo;
185 }
186 }
187
192 {
193 get
194 {
195 if (this.publicKey is null)
196 this.Init();
197
198 return this.publicKeyPoint;
199 }
200
201 internal set
202 {
203 this.publicKeyPoint = value;
204 }
205 }
206
210 public abstract string CurveName
211 {
212 get;
213 }
214
218 public BigInteger Order => this.n;
219
223 public int OrderBytes => this.orderBytes;
224
231
235 public int OrderBits => this.orderBits;
236
240 public int Cofactor => this.cofactor;
241
245 public PointOnCurve BasePoint => this.g;
246
251 public byte MsbOrderMask => this.msbOrderMask;
252
257 public abstract byte[] GenerateSecret();
258
263 public virtual void SetPrivateKey(byte[] Secret)
264 {
265 Tuple<byte[], byte[]> Info = this.CalculatePrivateKey(Secret);
266 PointOnCurve P = this.ScalarMultiplication(Info.Item1, this.g, true);
267
268 this.publicKey = this.Encode(P, false);
269 this.publicKeyBigEndian = this.Encode(P, true);
270 this.publicKeyPoint = P;
271 this.privateKey = Info.Item1;
272 this.additionalInfo = Info.Item2;
273 this.secret = Secret;
274 }
275
281 public virtual Tuple<byte[], byte[]> CalculatePrivateKey(byte[] Secret)
282 {
283 return new Tuple<byte[], byte[]>(Secret, null);
284 }
285
291 public byte[] Encode(PointOnCurve Point)
292 {
293 return this.Encode(Point, false);
294 }
295
302 public virtual byte[] Encode(PointOnCurve Point, bool BigEndian)
303 {
304 byte[] X = Point.X.ToByteArray(); // Little endian
305 byte[] Y = Point.Y.ToByteArray(); // Little endian
306 byte[] Result = new byte[this.orderBytes << 1];
307
308 if (X.Length != this.orderBytes)
309 Array.Resize(ref X, this.orderBytes);
310
311 if (Y.Length != this.orderBytes)
312 Array.Resize(ref Y, this.orderBytes);
313
314 if (BigEndian)
315 {
316 Array.Reverse(X); // Big endian
317 Array.Reverse(Y); // Big endian
318 }
319
320 Buffer.BlockCopy(X, 0, Result, 0, this.orderBytes);
321 Buffer.BlockCopy(Y, 0, Result, this.orderBytes, this.orderBytes);
322
323 return Result;
324 }
325
331 public PointOnCurve Decode(byte[] Point)
332 {
333 return this.Decode(Point, false);
334 }
335
342 public virtual PointOnCurve Decode(byte[] Point, bool BigEndian)
343 {
344 if (Point.Length != this.orderBytes << 1)
345 throw new ArgumentException("Invalid point.", nameof(Point));
346
347 byte[] X = new byte[this.orderBytes];
348 byte[] Y = new byte[this.orderBytes];
349
350 Buffer.BlockCopy(Point, 0, X, 0, this.orderBytes);
351 Buffer.BlockCopy(Point, this.orderBytes, Y, 0, this.orderBytes);
352
353 return new PointOnCurve(ToInt(X, BigEndian), ToInt(Y, BigEndian));
354 }
355
359 public void GenerateKeys()
360 {
361 this.SetPrivateKey(this.GenerateSecret());
362 }
363
371 public PointOnCurve ScalarMultiplication(BigInteger N, PointOnCurve P, bool Normalize)
372 {
373 return this.ScalarMultiplication(N.ToByteArray(), P, Normalize);
374 }
375
383 public virtual PointOnCurve ScalarMultiplication(byte[] N, PointOnCurve P, bool Normalize)
384 {
385 PointOnCurve Result = this.Zero;
386 int i, c = N.Length;
387 byte b, Bit;
388
389 for (i = 0; i < c; i++)
390 {
391 b = N[i];
392
393 for (Bit = 1; Bit != 0; Bit <<= 1)
394 {
395 if ((b & Bit) != 0)
396 this.AddTo(ref Result, P);
397
398 this.Double(ref P);
399 }
400 }
401
402 return Result;
403 }
404
408 public virtual PointOnCurve Zero
409 {
410 get
411 {
412 return new PointOnCurve(BigInteger.Zero, BigInteger.Zero);
413 }
414 }
415
422 public abstract void AddTo(ref PointOnCurve P, PointOnCurve Q);
423
428 public abstract void Double(ref PointOnCurve P);
429
436 public PointOnCurve GetSharedPoint(byte[] RemotePublicKey)
437 {
438 return this.GetSharedPoint(RemotePublicKey, false);
439 }
440
448 public virtual PointOnCurve GetSharedPoint(byte[] RemotePublicKey, bool BigEndian)
449 {
450 return ECDH.GetSharedPoint(this.PrivateKey, RemotePublicKey, BigEndian, this);
451 }
452
461 public virtual byte[] GetSharedKey(byte[] RemotePublicKey, HashFunctionArray HashFunction)
462 {
463 return this.GetSharedKey(RemotePublicKey, false, HashFunction);
464 }
465
475 public virtual byte[] GetSharedKey(byte[] RemotePublicKey, bool BigEndian,
477 {
478 return ECDH.GetSharedKey(this.PrivateKey, RemotePublicKey, BigEndian,
479 HashFunction, this);
480 }
481
487 public byte[] Sign(byte[] Data)
488 {
489 return this.Sign(Data, false);
490 }
491
498 public abstract byte[] Sign(byte[] Data, bool BigEndian);
499
505 public byte[] Sign(Stream Data)
506 {
507 return this.Sign(Data, false);
508 }
509
516 public abstract byte[] Sign(Stream Data, bool BigEndian);
517
525 public bool Verify(byte[] Data, byte[] PublicKey, byte[] Signature)
526 {
527 return this.Verify(Data, PublicKey, false, Signature);
528 }
529
538 public abstract bool Verify(byte[] Data, byte[] PublicKey, bool BigEndian,
539 byte[] Signature);
540
548 public bool Verify(Stream Data, byte[] PublicKey, byte[] Signature)
549 {
550 return this.Verify(Data, PublicKey, false, Signature);
551 }
552
561 public abstract bool Verify(Stream Data, byte[] PublicKey, bool BigEndian, byte[] Signature);
562
567 public virtual void Export(XmlWriter Output)
568 {
569 if (this.secret is null)
570 this.Init();
571
572 Output.WriteStartElement(ElementName, Namespace);
573 Output.WriteAttributeString("type", this.GetType().FullName);
574 Output.WriteAttributeString("d", Convert.ToBase64String(this.secret));
575 Output.WriteEndElement();
576 }
577
581 public string Export()
582 {
583 XmlWriterSettings Settings = new XmlWriterSettings()
584 {
585 Indent = false,
586 OmitXmlDeclaration = true
587 };
588 StringBuilder sb = new StringBuilder();
589 using (XmlWriter w = XmlWriter.Create(sb, Settings))
590 {
591 this.Export(w);
592 w.Flush();
593 }
594
595 return sb.ToString();
596 }
597
605 public static BigInteger ToInt(byte[] Binary, bool BigEndian)
606 {
607 if (BigEndian)
608 {
609 Binary = (byte[])Binary.Clone();
610 Array.Reverse(Binary);
611 }
612
613 return ToInt(Binary);
614 }
615
622 public static BigInteger ToInt(byte[] Binary)
623 {
624 int c = Binary.Length;
625 if ((Binary[c - 1] & 0x80) != 0)
626 Array.Resize(ref Binary, c + 1);
627
628 return new BigInteger(Binary);
629 }
630
636 public virtual bool IsPoint(byte[] Point)
637 {
638 return this.IsPoint(Point, false);
639 }
640
647 public virtual bool IsPoint(byte[] Point, bool BigEndian)
648 {
649 return this.IsPoint(this.Decode(Point, BigEndian));
650 }
651
657 public abstract bool IsPoint(PointOnCurve Point);
658 }
659}
Implements the Elliptic Curve Diffie-Hellman (ECDH) algorithm.
Definition: ECDH.cs:9
static PointOnCurve GetSharedPoint(byte[] LocalPrivateKey, byte[] RemotePublicKey, bool RemoteBigEndian, EllipticCurve Curve)
Gets a shared key using the Elliptic Curve Diffie-Hellman (ECDH) algorithm.
Definition: ECDH.cs:18
static byte[] GetSharedKey(byte[] LocalPrivateKey, byte[] RemotePublicKey, bool RemoteBigEndian, HashFunctionArray HashFunction, EllipticCurve Curve)
Gets a shared key using the Elliptic Curve Diffie-Hellman (ECDH) algorithm.
Definition: ECDH.cs:36
Abstract base class for elliptic curves.
virtual byte[] GetSharedKey(byte[] RemotePublicKey, bool BigEndian, HashFunctionArray HashFunction)
Gets a shared key using the Elliptic Curve Diffie-Hellman (ECDH) algorithm.
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.
byte[] Sign(byte[] Data)
Creates a signature of Data using the ECDSA algorithm.
readonly PointOnCurve g
Base point
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.
byte[] Encode(PointOnCurve Point)
Encodes a point on the curve.
abstract byte[] GenerateSecret()
Generates a new secret.
virtual byte[] PublicKeyBigEndian
Returns a big-endian representation of the public key.
readonly int orderBytes
Number of bytes used for the order of the curve.
virtual bool IsPoint(byte[] Point, bool BigEndian)
Checks if an encoded point is on the curve.
byte[] AdditionalInfo
Curve-specific additional information
abstract bool Verify(Stream Data, byte[] PublicKey, bool BigEndian, byte[] Signature)
Verifies a signature of Data made by the ECDSA algorithm.
int OrderBits
Number of bits required to represent the order of the curve.
abstract void Double(ref PointOnCurve P)
Doubles a point on the curve.
abstract byte[] Sign(Stream Data, bool BigEndian)
Creates a signature of Data using the ECDSA algorithm.
EllipticCurve(PointOnCurve BasePoint, BigInteger Order, int Cofactor, byte[] Secret)
Abstract base class for elliptic curves.
virtual bool IsPoint(byte[] Point)
Checks if an encoded point is on the curve.
virtual void Export(XmlWriter Output)
Exports the curve parameters to XML.
byte MsbOrderMask
Mask for most significant byte of scalars (as byte arrays of size BigIntegerBytes).
bool Verify(Stream Data, byte[] PublicKey, byte[] Signature)
Verifies a signature of Data made by the ECDSA algorithm.
static BigInteger ToInt(byte[] Binary, bool BigEndian)
Converts a little-endian binary representation of a big integer to a BigInteger.
string Export()
Exports the curve parameters to an XML string.
int OrderBytes
Number of bytes required to represent the order of the curve.
virtual PointOnCurve Decode(byte[] Point, bool BigEndian)
Decodes an encoded point on the curve.
byte[] Sign(Stream Data)
Creates a signature of Data using the ECDSA algorithm.
readonly int bigIntegerBytes
Number of bytes used for big integers in the curve.
static BigInteger ToInt(byte[] Binary)
Converts a little-endian binary representation of a big integer to a BigInteger.
abstract bool IsPoint(PointOnCurve Point)
Checks if a point is on the curve.
int BigIntegerBytes
Number of bytes required to represent coordinates using BigInteger of the curve. This number may diff...
const string ElementName
"EllipticCurve"
abstract byte[] Sign(byte[] Data, bool BigEndian)
Creates a signature of Data using the ECDSA algorithm.
virtual byte[] PublicKey
Encoded public key
void GenerateKeys()
Generates a new Private Key.
bool Verify(byte[] Data, byte[] PublicKey, byte[] Signature)
Verifies a signature of Data made by the ECDSA algorithm.
virtual void Init()
Method initiazing the elliptic curve properties.
virtual PointOnCurve GetSharedPoint(byte[] RemotePublicKey, bool BigEndian)
Gets a shared key, as a point, using the Elliptic Curve Diffie-Hellman (ECDH) algorithm.
PointOnCurve GetSharedPoint(byte[] RemotePublicKey)
Gets a shared key, as a point, using the Elliptic Curve Diffie-Hellman (ECDH) algorithm.
virtual PointOnCurve Zero
Neutral point.
static readonly RandomNumberGenerator rnd
Random number generator
abstract bool Verify(byte[] Data, byte[] PublicKey, bool BigEndian, byte[] Signature)
Verifies a signature of Data made by the ECDSA algorithm.
virtual byte[] Encode(PointOnCurve Point, bool BigEndian)
Encodes a point on the curve.
PointOnCurve Decode(byte[] Point)
Decodes an encoded point on the curve.
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:26
Represents a point on a curve.
Definition: PointOnCurve.cs:10