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()
89 _signature = signature;
96 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Iteration count [{count}] is invalid, using default [{_iterationCount}]",
this, GPALObjectType.Cryptography);
99 _iterationCount = count;
112 if (_algorithm != CryptoAlgorithm.AES)
114 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] not supported for IV generation, defaulting to AES",
this, GPALObjectType.Cryptography);
115 _algorithm = CryptoAlgorithm.AES;
117 if (_mode == CryptoMode.ECB)
119 GPAL.
PublishSimpleEvent(GPALEventType.WARNING,
"IV generation not required for ECB mode",
this, GPALObjectType.Cryptography);
124 $
"Generating IV for algorithm [{_algorithm}], mode [{_mode}]",
125 this, GPALObjectType.Cryptography);
129 int ivSize = _mode == CryptoMode.GCM ? 12 : 16;
130 iv =
new byte[ivSize];
131 var random =
new SecureRandom();
132 random.NextBytes(iv);
136 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"IV generation failed",
this, GPALObjectType.Cryptography, ex);
146 encryptedData =
null;
149 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot encrypt: missing key",
this, GPALObjectType.Cryptography);
152 if (_inputData ==
null)
154 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot encrypt: missing input data",
this, GPALObjectType.Cryptography);
157 if (_mode != CryptoMode.ECB && _iv ==
null)
159 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"IV is required for mode [{_mode}], defaulting to ECB",
this, GPALObjectType.Cryptography);
160 _mode = CryptoMode.ECB;
164 $
"Encrypting with algorithm [{_algorithm}], mode [{_mode}], padding [{_padding}]",
165 this, GPALObjectType.Cryptography);
169 encryptedData = PerformEncryption();
173 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Encryption failed",
this, GPALObjectType.Cryptography, ex);
174 encryptedData =
null;
181 decryptedValue =
null;
184 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot decrypt: missing key",
this, GPALObjectType.Cryptography);
187 if (_inputData ==
null)
189 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot decrypt: missing input data",
this, GPALObjectType.Cryptography);
192 if (_mode != CryptoMode.ECB && _iv ==
null)
194 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"IV is required for mode [{_mode}], defaulting to ECB",
this, GPALObjectType.Cryptography);
195 _mode = CryptoMode.ECB;
199 $
"Decrypting with algorithm [{_algorithm}], mode [{_mode}], padding [{_padding}]",
200 this, GPALObjectType.Cryptography);
204 byte[] decryptedBytes = PerformDecryption();
205 decryptedValue = System.Text.Encoding.UTF8.GetString(decryptedBytes);
209 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Decryption failed",
this, GPALObjectType.Cryptography, ex);
210 decryptedValue =
null;
220 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot sign: missing key",
this, GPALObjectType.Cryptography);
223 if (_inputData ==
null)
225 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot sign: missing input data",
this, GPALObjectType.Cryptography);
230 $
"Signing with algorithm [{_algorithm}]",
231 this, GPALObjectType.Cryptography);
235 signature = PerformSigning();
239 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Signing failed",
this, GPALObjectType.Cryptography, ex);
250 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot verify: missing key",
this, GPALObjectType.Cryptography);
253 if (_inputData ==
null)
255 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot verify: missing input data",
this, GPALObjectType.Cryptography);
258 if (_signature ==
null)
260 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot verify: missing signature",
this, GPALObjectType.Cryptography);
265 $
"Verifying with algorithm [{_algorithm}]",
266 this, GPALObjectType.Cryptography);
270 isValid = PerformVerification();
274 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Verification failed",
this, GPALObjectType.Cryptography, ex);
283 if (_inputData ==
null)
285 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot hash: missing input data",
this, GPALObjectType.Cryptography);
290 $
"Hashing with algorithm [{_algorithm}]" + (_salt !=
null ? $
", salt length [{_salt.Length}]" :
""),
291 this, GPALObjectType.Cryptography);
295 hash = PerformHashing();
299 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Hashing failed",
this, GPALObjectType.Cryptography, ex);
308 if (_algorithm == CryptoAlgorithm.PBKDF2 && (_salt ==
null || _inputData ==
null))
310 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot generate key with PBKDF2: missing salt or input data",
this, GPALObjectType.Cryptography);
315 $
"Generating key with algorithm [{_algorithm}]" + (_algorithm == CryptoAlgorithm.PBKDF2 ? $
", iteration count [{_iterationCount}]" :
""),
316 this, GPALObjectType.Cryptography);
320 key = PerformKeyGeneration();
324 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Key generation failed",
this, GPALObjectType.Cryptography, ex);
331 private byte[] PerformEncryption()
333 if (_algorithm != CryptoAlgorithm.AES)
335 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] not supported, defaulting to AES",
this, GPALObjectType.Cryptography);
336 _algorithm = CryptoAlgorithm.AES;
339 if (_mode == CryptoMode.GCM)
341 IAeadBlockCipher cipher =
new GcmBlockCipher(
new AesEngine());
342 ICipherParameters parameters =
new AeadParameters(
new KeyParameter(_key), 128, _iv,
null);
343 cipher.Init(
true, parameters);
344 byte[] output =
new byte[cipher.GetOutputSize(_inputData.Length)];
345 int len = cipher.ProcessBytes(_inputData, 0, _inputData.Length, output, 0);
346 cipher.DoFinal(output, len);
351 IBufferedCipher cipher = _mode == CryptoMode.CBC
352 ?
new PaddedBufferedBlockCipher(
new CbcBlockCipher(
new AesEngine()),
new Pkcs7Padding())
353 :
new PaddedBufferedBlockCipher(
new AesEngine(),
new Pkcs7Padding());
355 ICipherParameters parameters;
358 parameters =
new ParametersWithIV(
new KeyParameter(_key), _iv);
362 parameters =
new KeyParameter(_key);
365 cipher.Init(
true, parameters);
366 return cipher.DoFinal(_inputData);
370 private byte[] PerformDecryption()
372 if (_algorithm != CryptoAlgorithm.AES)
374 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] not supported, defaulting to AES",
this, GPALObjectType.Cryptography);
375 _algorithm = CryptoAlgorithm.AES;
378 if (_mode == CryptoMode.GCM)
380 IAeadBlockCipher cipher =
new GcmBlockCipher(
new AesEngine());
381 ICipherParameters parameters =
new AeadParameters(
new KeyParameter(_key), 128, _iv,
null);
382 cipher.Init(
false, parameters);
383 byte[] output =
new byte[cipher.GetOutputSize(_inputData.Length)];
384 int len = cipher.ProcessBytes(_inputData, 0, _inputData.Length, output, 0);
385 cipher.DoFinal(output, len);
390 IBufferedCipher cipher = _mode == CryptoMode.CBC
391 ?
new PaddedBufferedBlockCipher(
new CbcBlockCipher(
new AesEngine()),
new Pkcs7Padding())
392 :
new PaddedBufferedBlockCipher(
new AesEngine(),
new Pkcs7Padding());
394 ICipherParameters parameters;
397 parameters =
new ParametersWithIV(
new KeyParameter(_key), _iv);
401 parameters =
new KeyParameter(_key);
404 cipher.Init(
false, parameters);
405 return cipher.DoFinal(_inputData);
409 private byte[] PerformSigning()
411 if (_algorithm != CryptoAlgorithm.SHA256withRSA)
413 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] not supported, defaulting to SHA256withRSA",
this, GPALObjectType.Cryptography);
414 _algorithm = CryptoAlgorithm.SHA256withRSA;
417 AsymmetricKeyParameter keyParam;
420 var keyInfo = PrivateKeyInfo.GetInstance(_key);
421 var rsaParams = RsaPrivateKeyStructure.GetInstance(keyInfo.ParsePrivateKey());
422 keyParam =
new RsaKeyParameters(
true, rsaParams.Modulus, rsaParams.PrivateExponent);
426 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Invalid RSA private key format",
this, GPALObjectType.Cryptography, ex);
430 ISigner signer = SignerUtilities.GetSigner(
"SHA256withRSA");
431 signer.Init(
true, keyParam);
432 signer.BlockUpdate(_inputData, 0, _inputData.Length);
433 return signer.GenerateSignature();
436 private bool PerformVerification()
438 if (_algorithm != CryptoAlgorithm.SHA256withRSA)
440 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] not supported, defaulting to SHA256withRSA",
this, GPALObjectType.Cryptography);
441 _algorithm = CryptoAlgorithm.SHA256withRSA;
444 AsymmetricKeyParameter keyParam;
447 var keyInfo = SubjectPublicKeyInfo.GetInstance(_key);
448 var rsaParams = RsaPublicKeyStructure.GetInstance(keyInfo.ParsePublicKey());
449 keyParam =
new RsaKeyParameters(
false, rsaParams.Modulus, rsaParams.PublicExponent);
453 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Invalid RSA public key format",
this, GPALObjectType.Cryptography, ex);
457 ISigner signer = SignerUtilities.GetSigner(
"SHA256withRSA");
458 signer.Init(
false, keyParam);
459 signer.BlockUpdate(_inputData, 0, _inputData.Length);
460 return signer.VerifySignature(_signature);
463 private byte[] PerformHashing()
465 if (_algorithm != CryptoAlgorithm.SHA256)
467 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] not supported, defaulting to SHA256",
this, GPALObjectType.Cryptography);
468 _algorithm = CryptoAlgorithm.SHA256;
471 IDigest digest = DigestUtilities.GetDigest(
"SHA256");
474 digest.BlockUpdate(_salt, 0, _salt.Length);
476 digest.BlockUpdate(_inputData, 0, _inputData.Length);
477 byte[] hash =
new byte[digest.GetDigestSize()];
478 digest.DoFinal(hash, 0);
482 private byte[] PerformKeyGeneration()
484 if (_algorithm == CryptoAlgorithm.PBKDF2)
486 if (_salt ==
null || _inputData ==
null)
488 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot generate key with PBKDF2: missing salt or input data",
this, GPALObjectType.Cryptography);
492 Pkcs5S2ParametersGenerator gen =
new Pkcs5S2ParametersGenerator();
493 gen.Init(_inputData, _salt, _iterationCount);
494 return ((KeyParameter)gen.GenerateDerivedParameters(
"AES", 256)).GetKey();
497 if (_algorithm != CryptoAlgorithm.AES)
499 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Algorithm [{_algorithm}] not supported, defaulting to AES",
this, GPALObjectType.Cryptography);
500 _algorithm = CryptoAlgorithm.AES;
503 var generator = GeneratorUtilities.GetKeyGenerator(
"AES");
504 return generator.GenerateKey();
507 public static (
byte[],
byte[]) GenerateRsaKeyPair()
511 var keyPairGen = GeneratorUtilities.GetKeyPairGenerator(
"RSA");
512 keyPairGen.Init(
new KeyGenerationParameters(
new SecureRandom(), 2048));
513 var keyPair = keyPairGen.GenerateKeyPair();
516 var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private);
517 byte[] privateKey = privateKeyInfo.ToAsn1Object().GetDerEncoded();
520 var publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public);
521 byte[] publicKey = publicKeyInfo.ToAsn1Object().GetDerEncoded();
523 return (privateKey, publicKey);