Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
RsaEndpoint.cs
1using System;
2using System.IO;
3using System.Security.Cryptography;
4using System.Text;
6
8{
12 public class RsaEndpoint : E2eEndpoint
13 {
14 private RSA rsa;
15 private readonly byte[] modulus;
16 private readonly byte[] exponent;
17 private readonly int keySize;
18 private byte[] publicKey;
19 private string publicKeyBase64;
20 private string modulusBase64;
21 private string exponentBase64;
22
26 public RsaEndpoint()
27 : this(4096)
28 {
29 }
30
35 public RsaEndpoint(int KeySize)
36 : this(CreateRSA(KeySize))
37 {
38 }
39
45 public RsaEndpoint(int KeySize, IE2eSymmetricCipher SymmetricCipher)
46 : this(CreateRSA(KeySize), SymmetricCipher)
47 {
48 }
49
50 private static RSA CreateRSA(int KeySize)
51 {
52 RSA Result = RSA.Create();
53
54 if (Result.KeySize != KeySize)
55 Result.KeySize = KeySize;
56
57 return Result;
58 }
59
64 public RsaEndpoint(RSA Rsa)
65 : this(Rsa, new Aes256())
66 {
67 }
68
74 public RsaEndpoint(RSA Rsa, IE2eSymmetricCipher SymmetricCipher)
75 : base(SymmetricCipher)
76 {
77 this.rsa = Rsa;
78
79 RSAParameters P = this.rsa.ExportParameters(false);
80
81 this.keySize = this.rsa.KeySize;
82 this.modulus = P.Modulus;
83 this.exponent = P.Exponent;
84
85 this.Init();
86 }
87
94 public RsaEndpoint(int KeySize, byte[] Modulus, byte[] Exponent)
95 : this(KeySize, Modulus, Exponent, new Aes256())
96 {
97 }
98
106 public RsaEndpoint(int KeySize, byte[] Modulus, byte[] Exponent,
107 IE2eSymmetricCipher SymmetricCipher)
108 : base(SymmetricCipher)
109 {
110 this.rsa = CreateRSA(KeySize);
111
112 this.keySize = KeySize;
113 this.modulus = Modulus;
114 this.exponent = Exponent;
115
116 RSAParameters Param = new RSAParameters()
117 {
120 };
121
122 this.rsa.ImportParameters(Param);
123
124 this.Init();
125 }
126
127 private void Init()
128 {
129 this.modulusBase64 = Convert.ToBase64String(this.modulus);
130 this.exponentBase64 = Convert.ToBase64String(this.exponent);
131
132 int c = this.modulus.Length;
133 int d = this.exponent.Length;
134
135 this.publicKey = new byte[2 + c + d];
136
137 this.publicKey[0] = (byte)(this.keySize);
138 this.publicKey[1] = (byte)(this.keySize >> 8);
139 Array.Copy(this.modulus, 0, this.publicKey, 2, c);
140 Array.Copy(this.exponent, 0, this.publicKey, c + 2, d);
141
142 this.publicKeyBase64 = Convert.ToBase64String(this.publicKey);
143 }
144
148 public override string LocalName => "rsa";
149
153 public int KeySize => this.keySize;
154
158 public override byte[] PublicKey => this.publicKey;
159
163 public override string PublicKeyBase64 => this.publicKeyBase64;
164
168 public byte[] Modulus => this.modulus;
169
173 public byte[] Exponent => this.exponent;
174
178 public override int SecurityStrength
179 {
180 get
181 {
182 if (this.keySize < 1024)
183 return 0;
184 else if (this.keySize < 2048)
185 return 80;
186 else if (this.keySize < 3072)
187 return 112;
188 else if (this.keySize < 7680)
189 return 128;
190 else if (this.keySize < 15360)
191 return 192;
192 else
193 return 256;
194 }
195 }
196
203 {
204 int KeySize;
205
206 if (SecurityStrength <= 80)
207 KeySize = 1024;
208 else if (SecurityStrength <= 112)
209 KeySize = 2048;
210 else if (SecurityStrength <= 128)
211 KeySize = 3072;
212 else if (SecurityStrength <= 192)
213 KeySize = 7680;
214 else if (SecurityStrength <= 256)
215 KeySize = 15360;
216 else
217 throw new ArgumentException("Key strength too high.", nameof(SecurityStrength));
218
219 RSA Rsa = CreateRSA(KeySize);
220
221 return new RsaEndpoint(Rsa, this.DefaultSymmetricCipher.CreteNew());
222 }
223
229 public override IE2eEndpoint CreatePrivate(byte[] Secret)
230 {
231 RSAParameters P = new RSAParameters();
232 string s = Encoding.ASCII.GetString(Secret);
233 string[] Parts = s.Split(',');
234 string Name;
235 byte[] Value;
236 int i;
237
238 foreach (string Part in Parts)
239 {
240 i = Part.IndexOf('=');
241 if (i < 0)
242 continue;
243
244 Name = Part.Substring(0, i);
245 Value = Convert.FromBase64String(Part.Substring(i + 1));
246
247 switch (Name)
248 {
249 case "D": P.D = Value; break;
250 case "DP": P.DP = Value; break;
251 case "DQ": P.DQ = Value; break;
252 case "Exponent": P.Exponent = Value; break;
253 case "InverseQ": P.InverseQ = Value; break;
254 case "Modulus": P.Modulus = Value; break;
255 case "P": P.P = Value; break;
256 case "Q": P.Q = Value; break;
257 }
258 }
259
260 RSA Rsa = RSA.Create();
261 Rsa.ImportParameters(P);
262
263 return new RsaEndpoint(Rsa, this.DefaultSymmetricCipher.CreteNew());
264 }
265
271 public byte[] Export(bool Private)
272 {
273 RSAParameters P = this.rsa.ExportParameters(Private);
274 StringBuilder sb = new StringBuilder();
275
276 sb.Append("Exponent=");
277 sb.Append(Convert.ToBase64String(P.Exponent));
278 sb.Append(",Modulus=");
279 sb.Append(Convert.ToBase64String(P.Modulus));
280 if (Private)
281 {
282 sb.Append(",D=");
283 sb.Append(Convert.ToBase64String(P.D));
284 sb.Append(",DP=");
285 sb.Append(Convert.ToBase64String(P.DP));
286 sb.Append(",DQ=");
287 sb.Append(Convert.ToBase64String(P.DQ));
288 sb.Append(",InverseQ=");
289 sb.Append(Convert.ToBase64String(P.InverseQ));
290 sb.Append(",P=");
291 sb.Append(Convert.ToBase64String(P.P));
292 sb.Append(",Q=");
293 sb.Append(Convert.ToBase64String(P.P));
294 }
295
296 return Encoding.ASCII.GetBytes(sb.ToString());
297 }
298
304 public override IE2eEndpoint CreatePublic(byte[] PublicKey)
305 {
306 if (PublicKey.Length < 2)
307 throw new ArgumentException("Invalid public key.", nameof(PublicKey));
308
309 int KeySize = PublicKey[1];
310 KeySize <<= 8;
311 KeySize |= PublicKey[0];
312
313 int ModSize = KeySize >> 3;
314 if (PublicKey.Length < 2 + ModSize)
315 throw new ArgumentException("Invalid public key.", nameof(PublicKey));
316
317 int ExpSize = PublicKey.Length - 2 - ModSize;
318 if (ExpSize <= 0)
319 throw new ArgumentException("Invalid public key.", nameof(PublicKey));
320
321 byte[] Modulus = new byte[ModSize];
322 byte[] Exponent = new byte[ExpSize];
323
324 Array.Copy(PublicKey, 2, Modulus, 0, ModSize);
325 Array.Copy(PublicKey, 2 + ModSize, Exponent, 0, ExpSize);
326
328 }
329
331 public override void Dispose()
332 {
333 base.Dispose();
334
335 this.rsa?.Dispose();
336 this.rsa = null;
337 }
338
342 public override bool SupportsSharedSecrets => false;
343
349 public override byte[] GetSharedSecret(IE2eEndpoint RemoteEndpoint)
350 {
351 throw new NotSupportedException("Getting shared secrets using RSA not supported.");
352 }
353
359 public override byte[] EncryptSecret(byte[] Secret)
360 {
361 lock (this.rsa)
362 {
363 return this.rsa.Encrypt(Secret, RSAEncryptionPadding.OaepSHA256);
364 }
365 }
366
372 public override byte[] DecryptSecret(byte[] Secret)
373 {
374 lock (this.rsa)
375 {
376 return this.rsa.Decrypt(Secret, RSAEncryptionPadding.OaepSHA256);
377 }
378 }
379
385 public override byte[] Sign(byte[] Data)
386 {
387 return this.rsa.SignData(Data, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
388 }
389
395 public override byte[] Sign(Stream Data)
396 {
397 return this.rsa.SignData(Data, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
398 }
399
406 public override bool Verify(byte[] Data, byte[] Signature)
407 {
408 return RsaEndpoint.Verify(Data, Signature, this.keySize, this.modulus, this.exponent);
409 }
410
417 public override bool Verify(Stream Data, byte[] Signature)
418 {
419 return RsaEndpoint.Verify(Data, Signature, this.keySize, this.modulus, this.exponent);
420 }
421
430 public static bool Verify(byte[] Data, byte[] Signature, int KeySize, byte[] PublicKey)
431 {
432 int c = KeySize >> 3;
433 int d = PublicKey.Length - c;
434 if (d <= 0)
435 throw new ArgumentException("Invalid public key.", nameof(PublicKey));
436
437 byte[] Modulus = new byte[c];
438 byte[] Exponent = new byte[d];
439
440 Array.Copy(PublicKey, 0, Modulus, 0, c);
441 Array.Copy(PublicKey, c, Exponent, 0, d);
442
443 return Verify(Data, Signature, KeySize, Modulus, Exponent);
444 }
445
454 public static bool Verify(Stream Data, byte[] Signature, int KeySize, byte[] PublicKey)
455 {
456 int c = KeySize >> 3;
457 int d = PublicKey.Length - c;
458 if (d <= 0)
459 throw new ArgumentException("Invalid public key.", nameof(PublicKey));
460
461 byte[] Modulus = new byte[c];
462 byte[] Exponent = new byte[d];
463
464 Array.Copy(PublicKey, 0, Modulus, 0, c);
465 Array.Copy(PublicKey, c, Exponent, 0, d);
466
467 return Verify(Data, Signature, KeySize, Modulus, Exponent);
468 }
469
479 public static bool Verify(byte[] Data, byte[] Signature, int KeySize, byte[] Modulus, byte[] Exponent)
480 {
481 using (RSA Rsa = CreateRSA(KeySize))
482 {
483 RSAParameters P = new RSAParameters()
484 {
487 };
488
489 Rsa.ImportParameters(P);
490
491 return Rsa.VerifyData(Data, Signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
492 }
493 }
494
504 public static bool Verify(Stream Data, byte[] Signature, int KeySize, byte[] Modulus, byte[] Exponent)
505 {
506 using (RSA Rsa = CreateRSA(KeySize))
507 {
508 RSAParameters P = new RSAParameters()
509 {
512 };
513
514 Rsa.ImportParameters(P);
515
516 return Rsa.VerifyData(Data, Signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
517 }
518 }
519
523 public override bool Slow => true;
524
526 public override bool Equals(object obj)
527 {
528 return obj is RsaEndpoint RsaEndpoint &&
529 this.keySize.Equals(RsaEndpoint.keySize) &&
530 this.modulusBase64.Equals(RsaEndpoint.modulusBase64) &&
531 this.exponentBase64.Equals(RsaEndpoint.exponentBase64);
532 }
533
535 public override int GetHashCode()
536 {
537 int Result = this.keySize.GetHashCode();
538 Result ^= Result << 5 ^ this.modulusBase64.GetHashCode();
539 Result ^= Result << 5 ^ this.exponentBase64.GetHashCode();
540
541 return Result;
542 }
543
544 }
545}
Abstract base class for End-to-End encryption schemes.
Definition: E2eEndpoint.cs:12
virtual IE2eSymmetricCipher DefaultSymmetricCipher
Default symmetric cipher.
Definition: E2eEndpoint.cs:265
RSA / AES-256 hybrid cipher.
Definition: RsaEndpoint.cs:13
override byte[] Sign(Stream Data)
Signs binary data using the local private key.
Definition: RsaEndpoint.cs:395
RsaEndpoint(int KeySize, byte[] Modulus, byte[] Exponent)
RSA / AES-256 hybrid cipher.
Definition: RsaEndpoint.cs:94
override byte[] EncryptSecret(byte[] Secret)
Encrypts a secret. Used if shared secrets cannot be calculated.
Definition: RsaEndpoint.cs:359
override byte[] DecryptSecret(byte[] Secret)
Decrypts a secret. Used if shared secrets cannot be calculated.
Definition: RsaEndpoint.cs:372
override int SecurityStrength
Security strength of End-to-End encryption scheme.
Definition: RsaEndpoint.cs:179
byte[] Modulus
Modulus of RSA public key.
Definition: RsaEndpoint.cs:168
override string PublicKeyBase64
Remote public key, as a Base64 string.
Definition: RsaEndpoint.cs:163
override IE2eEndpoint CreatePublic(byte[] PublicKey)
Creates a new endpoint given a public key.
Definition: RsaEndpoint.cs:304
override void Dispose()
IDisposable.Dispose
Definition: RsaEndpoint.cs:331
override bool Verify(Stream Data, byte[] Signature)
Verifies a signature.
Definition: RsaEndpoint.cs:417
RsaEndpoint()
RSA / AES-256 hybrid cipher.
Definition: RsaEndpoint.cs:26
byte[] Export(bool Private)
Exports information from the encryption object.
Definition: RsaEndpoint.cs:271
RsaEndpoint(int KeySize)
RSA / AES-256 hybrid cipher.
Definition: RsaEndpoint.cs:35
override bool Slow
If implementation is slow, compared to other options.
Definition: RsaEndpoint.cs:523
override bool Verify(byte[] Data, byte[] Signature)
Verifies a signature.
Definition: RsaEndpoint.cs:406
override IE2eEndpoint Create(int SecurityStrength)
Creates a new key.
Definition: RsaEndpoint.cs:202
static bool Verify(byte[] Data, byte[] Signature, int KeySize, byte[] Modulus, byte[] Exponent)
Verifies a signature.
Definition: RsaEndpoint.cs:479
override byte[] Sign(byte[] Data)
Signs binary data using the local private key.
Definition: RsaEndpoint.cs:385
byte[] Exponent
Exponent of RSA public key.
Definition: RsaEndpoint.cs:173
override string LocalName
Local name of the E2E encryption scheme
Definition: RsaEndpoint.cs:148
static bool Verify(byte[] Data, byte[] Signature, int KeySize, byte[] PublicKey)
Verifies a signature.
Definition: RsaEndpoint.cs:430
RsaEndpoint(int KeySize, IE2eSymmetricCipher SymmetricCipher)
RSA / AES-256 hybrid cipher.
Definition: RsaEndpoint.cs:45
override bool Equals(object obj)
Definition: RsaEndpoint.cs:526
RsaEndpoint(int KeySize, byte[] Modulus, byte[] Exponent, IE2eSymmetricCipher SymmetricCipher)
RSA / AES-256 hybrid cipher.
Definition: RsaEndpoint.cs:106
static bool Verify(Stream Data, byte[] Signature, int KeySize, byte[] PublicKey)
Verifies a signature.
Definition: RsaEndpoint.cs:454
RsaEndpoint(RSA Rsa, IE2eSymmetricCipher SymmetricCipher)
RSA / AES-256 hybrid cipher.
Definition: RsaEndpoint.cs:74
override IE2eEndpoint CreatePrivate(byte[] Secret)
Creates a new endpoint given a private key.
Definition: RsaEndpoint.cs:229
static bool Verify(Stream Data, byte[] Signature, int KeySize, byte[] Modulus, byte[] Exponent)
Verifies a signature.
Definition: RsaEndpoint.cs:504
override bool SupportsSharedSecrets
If shared secrets can be calculated from the endpoints keys.
Definition: RsaEndpoint.cs:342
RsaEndpoint(RSA Rsa)
RSA / AES-256 hybrid cipher.
Definition: RsaEndpoint.cs:64
override byte[] GetSharedSecret(IE2eEndpoint RemoteEndpoint)
Gets a shared secret
Definition: RsaEndpoint.cs:349
override byte[] PublicKey
Remote public key.
Definition: RsaEndpoint.cs:158
Implements support for the AES-256 cipher in hybrid End-to-End encryption schemes.
Definition: Aes256.cs:15
Abstract base class for End-to-End encryption schemes.
Definition: IE2eEndpoint.cs:12
Interface for symmetric ciphers.
IE2eSymmetricCipher CreteNew()
Creates a new symmetric cipher object with the same settings as the current object.