/// <summary> /// N-level encryption of existing onion ctor /// </summary> public PublicKeyEncryptionOnion(PublicKeyEncryptionOnion innerOnion, string asymmetricThumbprint) { Mandate.That(innerOnion, nameof(innerOnion)).IsNotNull(); Mandate.That(asymmetricThumbprint, nameof(asymmetricThumbprint)).IsNotNullOrEmpty(); AsymmetricThumbprint = asymmetricThumbprint; InnerOnion = innerOnion.Clone(); // allocate a new object so we're self contained and the calling code can do whatever it wants with the parameter object InnerOnion.AsymmetricEncryptedKey = null; using (var aes = new AESCryptoAgent()) using (var rsa = new RSACryptoAgent(asymmetricThumbprint)) { // generate the aes key and use it to re-encrypt the original key var symmetricKey = aes.GenerateKey(); SymmetricAlgorithmIV = aes.GenerateIV(); SymmetricEncryptedData = aes.Encrypt(innerOnion.AsymmetricEncryptedKey, symmetricKey, SymmetricAlgorithmIV); // encrypt the aes key with the public key AsymmetricEncryptedKey = rsa.Encrypt(symmetricKey); } // even though we're not using the param onion, we don't want to let it retain the data that's at a lower level of encryption innerOnion.AsymmetricEncryptedKey = null; }
/// <summary> /// Root-level encryption of plain text ctor /// </summary> public PublicKeyEncryptionOnion(byte[] plainData, string asymmetricThumbprint) { if (null == plainData || !plainData.Any()) { throw new ArgumentNullException(nameof(plainData)); } Mandate.That(asymmetricThumbprint, nameof(asymmetricThumbprint)).IsNotNullOrEmpty(); AsymmetricThumbprint = asymmetricThumbprint; InnerOnion = null; using (var aes = new AESCryptoAgent()) using (var rsa = new RSACryptoAgent(asymmetricThumbprint)) { // generate the aes key and use it to encrypt the original plaintext var symmetricKey = aes.GenerateKey(); SymmetricAlgorithmIV = aes.GenerateIV(); SymmetricEncryptedData = aes.Encrypt(plainData, symmetricKey, SymmetricAlgorithmIV); // encrypt the aes key with the public key AsymmetricEncryptedKey = rsa.Encrypt(symmetricKey); } }