/// <summary>
        ///     Peel the onion until we can return the original plain data. Remember that the calling environment must contain all
        ///     necessary private keys.
        /// </summary>
        public byte[] PeelAll()
        {
            if (AsymmetricEncryptedKey == null)
            {
                throw new Exception(
                          "AsymmetricEncryptedKey not found. Are you sure this onion doesn't have more layers?");
            }

            byte[] plainData;
            var    onion = this;

            while (!onion.IsRoot)
            {
                onion = onion.PeelOne();
            }

            using (var aes = new AESCryptoAgent())
                using (var rsa = new RSACryptoAgent(onion.AsymmetricThumbprint))
                {
                    var decryptedSymmetricKey = rsa.Decrypt(onion.AsymmetricEncryptedKey);
                    plainData = aes.Decrypt(onion.SymmetricEncryptedData, decryptedSymmetricKey,
                                            onion.SymmetricAlgorithmIV);
                }

            return(plainData);
        }
        /// <summary>
        ///     Return an onion with the top layer removed
        /// </summary>
        public PublicKeyEncryptionOnion PeelOne()
        {
            if (IsRoot)
            {
                throw new Exception(
                          "This object is the root of the onion so there are no more layers to peel. Call 'PeelAll()' instead.");
            }

            if (AsymmetricEncryptedKey == null)
            {
                throw new Exception(
                          "AsymmetricEncryptedKey not found. Are you sure this onion doesn't have more layers?");
            }

            var rv = InnerOnion.Clone();

            // here we want to generate a new object to return since we don't want to decrease the security of the current object
            using (var aes = new AESCryptoAgent())
                using (var rsa = new RSACryptoAgent(AsymmetricThumbprint))
                {
                    // decrypt the previously encrypted key
                    var decryptedSymmetricKey = rsa.Decrypt(AsymmetricEncryptedKey);
                    rv.AsymmetricEncryptedKey = aes.Decrypt(SymmetricEncryptedData, decryptedSymmetricKey,
                                                            SymmetricAlgorithmIV);
                }

            return(rv);
        }