38 private CryptoAlgorithm _algorithm = CryptoAlgorithm.AES;
41 private CryptoMode _mode = CryptoMode.GCM;
42 private CryptoPadding _padding = CryptoPadding.PKCS7;
44 private int _iterationCount = 10000;
45 private byte[] _inputData;
46 private byte[] _signature;
48 internal Cryptography()
87 private IBufferedCipher BuildAesCipher()
89 IBlockCipher engine = CryptoMode.CBC == _mode
90 ? (IBlockCipher)
new CbcBlockCipher(
new AesEngine())
95 IBufferedCipher retVal = CryptoPadding.NoPadding == _padding
96 ?
new BufferedBlockCipher(engine)
97 :
new PaddedBufferedBlockCipher(engine, CryptoPadding.ISO10126 == _padding
98 ? (IBlockCipherPadding)
new ISO10126d2Padding()
99 :
new Pkcs7Padding());
112 _signature = signature;
119 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Iteration count [{count}] is invalid, using default [{_iterationCount}]",
this, GPALObjectType.Cryptography);
122 _iterationCount = count;
135 if (_algorithm != CryptoAlgorithm.AES)
137 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] not supported for IV generation, defaulting to AES",
this, GPALObjectType.Cryptography);
138 _algorithm = CryptoAlgorithm.AES;
140 if (_mode == CryptoMode.ECB)
142 GPAL.
PublishSimpleEvent(GPALEventType.WARNING,
"IV generation not required for ECB mode",
this, GPALObjectType.Cryptography);
147 $
"Generating IV for algorithm [{_algorithm}], mode [{_mode}]",
148 this, GPALObjectType.Cryptography);
152 int ivSize = _mode == CryptoMode.GCM ? 12 : 16;
153 iv =
new byte[ivSize];
154 var random =
new SecureRandom();
155 random.NextBytes(iv);
159 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"IV generation failed",
this, GPALObjectType.Cryptography, ex);
169 encryptedData =
null;
172 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot encrypt: missing key",
this, GPALObjectType.Cryptography);
175 if (_inputData ==
null)
177 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot encrypt: missing input data",
this, GPALObjectType.Cryptography);
180 if (_mode != CryptoMode.ECB && _iv ==
null)
182 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"IV is required for mode [{_mode}], defaulting to ECB",
this, GPALObjectType.Cryptography);
183 _mode = CryptoMode.ECB;
187 $
"Encrypting with algorithm [{_algorithm}], mode [{_mode}], padding [{_padding}]",
188 this, GPALObjectType.Cryptography);
192 encryptedData = PerformEncryption();
196 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Encryption failed",
this, GPALObjectType.Cryptography, ex);
197 encryptedData =
null;
204 decryptedValue =
null;
207 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot decrypt: missing key",
this, GPALObjectType.Cryptography);
210 if (_inputData ==
null)
212 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot decrypt: missing input data",
this, GPALObjectType.Cryptography);
215 if (_mode != CryptoMode.ECB && _iv ==
null)
217 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"IV is required for mode [{_mode}], defaulting to ECB",
this, GPALObjectType.Cryptography);
218 _mode = CryptoMode.ECB;
222 $
"Decrypting with algorithm [{_algorithm}], mode [{_mode}], padding [{_padding}]",
223 this, GPALObjectType.Cryptography);
227 byte[] decryptedBytes = PerformDecryption();
228 decryptedValue = System.Text.Encoding.UTF8.GetString(decryptedBytes);
232 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Decryption failed",
this, GPALObjectType.Cryptography, ex);
233 decryptedValue =
null;
243 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot sign: missing key",
this, GPALObjectType.Cryptography);
246 if (_inputData ==
null)
248 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot sign: missing input data",
this, GPALObjectType.Cryptography);
253 $
"Signing with algorithm [{_algorithm}]",
254 this, GPALObjectType.Cryptography);
258 signature = PerformSigning();
262 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Signing failed",
this, GPALObjectType.Cryptography, ex);
273 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot verify: missing key",
this, GPALObjectType.Cryptography);
276 if (_inputData ==
null)
278 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot verify: missing input data",
this, GPALObjectType.Cryptography);
281 if (_signature ==
null)
283 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot verify: missing signature",
this, GPALObjectType.Cryptography);
288 $
"Verifying with algorithm [{_algorithm}]",
289 this, GPALObjectType.Cryptography);
293 isValid = PerformVerification();
297 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Verification failed",
this, GPALObjectType.Cryptography, ex);
306 if (_inputData ==
null)
308 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot hash: missing input data",
this, GPALObjectType.Cryptography);
313 $
"Hashing with algorithm [{_algorithm}]" + (_salt !=
null ? $
", salt length [{_salt.Length}]" :
""),
314 this, GPALObjectType.Cryptography);
318 hash = PerformHashing();
322 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Hashing failed",
this, GPALObjectType.Cryptography, ex);
331 if (_algorithm == CryptoAlgorithm.PBKDF2 && (_salt ==
null || _inputData ==
null))
333 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot generate key with PBKDF2: missing salt or input data",
this, GPALObjectType.Cryptography);
338 $
"Generating key with algorithm [{_algorithm}]" + (_algorithm == CryptoAlgorithm.PBKDF2 ? $
", iteration count [{_iterationCount}]" :
""),
339 this, GPALObjectType.Cryptography);
343 key = PerformKeyGeneration();
347 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Key generation failed",
this, GPALObjectType.Cryptography, ex);
354 private byte[] PerformEncryption()
356 if (CryptoAlgorithm.AES != _algorithm && CryptoAlgorithm.RSA != _algorithm)
358 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] does not encrypt, using AES",
this, GPALObjectType.Cryptography);
359 _algorithm = CryptoAlgorithm.AES;
364 if (CryptoAlgorithm.RSA == _algorithm)
365 return RsaCipher(
true);
367 if (_mode == CryptoMode.GCM)
369 IAeadBlockCipher cipher =
new GcmBlockCipher(
new AesEngine());
370 ICipherParameters parameters =
new AeadParameters(
new KeyParameter(_key), 128, _iv,
null);
371 cipher.Init(
true, parameters);
372 byte[] output =
new byte[cipher.GetOutputSize(_inputData.Length)];
373 int len = cipher.ProcessBytes(_inputData, 0, _inputData.Length, output, 0);
374 cipher.DoFinal(output, len);
379 IBufferedCipher cipher = BuildAesCipher();
381 ICipherParameters parameters;
384 parameters =
new ParametersWithIV(
new KeyParameter(_key), _iv);
388 parameters =
new KeyParameter(_key);
391 cipher.Init(
true, parameters);
392 return cipher.DoFinal(_inputData);
396 private byte[] PerformDecryption()
398 if (CryptoAlgorithm.AES != _algorithm && CryptoAlgorithm.RSA != _algorithm)
400 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] does not decrypt, using AES",
this, GPALObjectType.Cryptography);
401 _algorithm = CryptoAlgorithm.AES;
405 if (CryptoAlgorithm.RSA == _algorithm)
406 return RsaCipher(
false);
408 if (_mode == CryptoMode.GCM)
410 IAeadBlockCipher cipher =
new GcmBlockCipher(
new AesEngine());
411 ICipherParameters parameters =
new AeadParameters(
new KeyParameter(_key), 128, _iv,
null);
412 cipher.Init(
false, parameters);
413 byte[] output =
new byte[cipher.GetOutputSize(_inputData.Length)];
414 int len = cipher.ProcessBytes(_inputData, 0, _inputData.Length, output, 0);
415 cipher.DoFinal(output, len);
420 IBufferedCipher cipher = BuildAesCipher();
422 ICipherParameters parameters;
425 parameters =
new ParametersWithIV(
new KeyParameter(_key), _iv);
429 parameters =
new KeyParameter(_key);
432 cipher.Init(
false, parameters);
433 return cipher.DoFinal(_inputData);
437 private byte[] PerformSigning()
439 if (CryptoAlgorithm.SHA256withRSA != _algorithm && CryptoAlgorithm.ECDSA != _algorithm)
441 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] does not sign, using SHA256withRSA",
this, GPALObjectType.Cryptography);
442 _algorithm = CryptoAlgorithm.SHA256withRSA;
445 AsymmetricKeyParameter keyParam;
450 keyParam = PrivateKeyFactory.CreateKey(_key);
454 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"[{_algorithm}] private key could not be read. It has to be the PKCS#8 encoding of a key for that algorithm",
this, GPALObjectType.Cryptography, ex);
458 ISigner signer = SignerUtilities.GetSigner(SignerName());
459 signer.Init(
true, keyParam);
460 signer.BlockUpdate(_inputData, 0, _inputData.Length);
461 return signer.GenerateSignature();
464 private bool PerformVerification()
466 if (CryptoAlgorithm.SHA256withRSA != _algorithm && CryptoAlgorithm.ECDSA != _algorithm)
468 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] does not verify, using SHA256withRSA",
this, GPALObjectType.Cryptography);
469 _algorithm = CryptoAlgorithm.SHA256withRSA;
472 AsymmetricKeyParameter keyParam;
475 keyParam = PublicKeyFactory.CreateKey(_key);
479 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"[{_algorithm}] public key could not be read. It has to be the X.509 SubjectPublicKeyInfo encoding of a key for that algorithm",
this, GPALObjectType.Cryptography, ex);
483 ISigner signer = SignerUtilities.GetSigner(SignerName());
484 signer.Init(
false, keyParam);
485 signer.BlockUpdate(_inputData, 0, _inputData.Length);
486 return signer.VerifySignature(_signature);
489 private byte[] PerformHashing()
491 if (CryptoAlgorithm.SHA256 != _algorithm && CryptoAlgorithm.MD5 != _algorithm)
493 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] does not hash, using SHA256",
this, GPALObjectType.Cryptography);
494 _algorithm = CryptoAlgorithm.SHA256;
497 IDigest digest = DigestUtilities.GetDigest(CryptoAlgorithm.MD5 == _algorithm ?
"MD5" :
"SHA256");
500 digest.BlockUpdate(_salt, 0, _salt.Length);
502 digest.BlockUpdate(_inputData, 0, _inputData.Length);
503 byte[] hash =
new byte[digest.GetDigestSize()];
504 digest.DoFinal(hash, 0);
508 private byte[] PerformKeyGeneration()
510 if (_algorithm == CryptoAlgorithm.PBKDF2)
512 if (_salt ==
null || _inputData ==
null)
514 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot generate key with PBKDF2: missing salt or input data",
this, GPALObjectType.Cryptography);
518 Pkcs5S2ParametersGenerator gen =
new Pkcs5S2ParametersGenerator();
519 gen.Init(_inputData, _salt, _iterationCount);
520 return ((KeyParameter)gen.GenerateDerivedParameters(
"AES", 256)).GetKey();
523 if (_algorithm != CryptoAlgorithm.AES)
525 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] not supported, defaulting to AES",
this, GPALObjectType.Cryptography);
526 _algorithm = CryptoAlgorithm.AES;
529 var generator = GeneratorUtilities.GetKeyGenerator(
"AES");
530 return generator.GenerateKey();
536 private string SignerName()
538 return CryptoAlgorithm.ECDSA == _algorithm ?
"SHA256withECDSA" :
"SHA256withRSA";
548 private byte[] RsaCipher(
bool encrypting)
550 AsymmetricKeyParameter keyParam;
554 keyParam =
true == encrypting ? PublicKeyFactory.CreateKey(_key) : PrivateKeyFactory.CreateKey(_key);
558 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"RSA {(true == encrypting ? "public" : "private")} key could not be read",
this, GPALObjectType.Cryptography, ex);
562 IBufferedCipher cipher = CipherUtilities.GetCipher(
"RSA/NONE/PKCS1Padding");
563 cipher.Init(encrypting, keyParam);
565 return cipher.DoFinal(_inputData);
575 public static (
byte[],
byte[]) GenerateEcdsaKeyPair()
579 var keyPairGen = GeneratorUtilities.GetKeyPairGenerator(
"ECDSA");
580 keyPairGen.Init(
new Org.BouncyCastle.Crypto.Parameters.ECKeyGenerationParameters(
581 Org.BouncyCastle.Asn1.X9.X962NamedCurves.GetOid(
"prime256v1"),
new SecureRandom()));
583 var keyPair = keyPairGen.GenerateKeyPair();
585 byte[] privateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private).ToAsn1Object().GetDerEncoded();
586 byte[] publicKey = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public).ToAsn1Object().GetDerEncoded();
588 return (privateKey, publicKey);
592 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Could not generate an ECDSA key pair",
null, GPALObjectType.Cryptography, ex);
597 public static (
byte[],
byte[]) GenerateRsaKeyPair()
601 var keyPairGen = GeneratorUtilities.GetKeyPairGenerator(
"RSA");
602 keyPairGen.Init(
new KeyGenerationParameters(
new SecureRandom(), 2048));
603 var keyPair = keyPairGen.GenerateKeyPair();
606 var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);
607 byte[] privateKey = privateKeyInfo.ToAsn1Object().GetDerEncoded();
610 var publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public);
611 byte[] publicKey = publicKeyInfo.ToAsn1Object().GetDerEncoded();
613 return (privateKey, publicKey);
622 public ICryptography ToGPALObject()