/// <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> /// Cloning ctor /// </summary> private PublicKeyEncryptionOnion(PublicKeyEncryptionOnion onion) { Mandate.That(onion, nameof(onion)).IsNotNull(); SymmetricEncryptedData = onion.SymmetricEncryptedData; AsymmetricEncryptedKey = onion.AsymmetricEncryptedKey; SymmetricAlgorithmIV = onion.SymmetricAlgorithmIV; AsymmetricThumbprint = onion.AsymmetricThumbprint; InnerOnion = onion.InnerOnion; }