首页 文章

加密/解密大文件(.NET)

提问于
浏览
21

我必须加密,存储然后解密大文件 . 这样做的最佳方式是什么?我听说RSA加密很昂贵,建议使用RSA加密AES密钥,然后使用AES密钥加密大文件 . 任何带有示例的建议都会很棒 .

4 回答

  • 13

    这可能有所帮助

    /// Encrypts a file using Rijndael algorithm.
    ///</summary>
    ///<param name="inputFile"></param>
    ///<param name="outputFile"></param>
    private void EncryptFile(string inputFile, string outputFile)
    {
    
        try
        {
            string password = @"myKey123"; // Your Key Here
            UnicodeEncoding UE = new UnicodeEncoding();
            byte[] key = UE.GetBytes(password);
    
            string cryptFile = outputFile;
            FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
    
            RijndaelManaged RMCrypto = new RijndaelManaged();
    
            CryptoStream cs = new CryptoStream(fsCrypt,
                RMCrypto.CreateEncryptor(key, key),
                CryptoStreamMode.Write);
    
            FileStream fsIn = new FileStream(inputFile, FileMode.Open);
    
            int data;
            while ((data = fsIn.ReadByte()) != -1)
                cs.WriteByte((byte)data);
    
    
            fsIn.Close();
            cs.Close();
            fsCrypt.Close();
        }
        catch
        {
            MessageBox.Show("Encryption failed!", "Error");
        }
    }
    
    ///
    /// Decrypts a file using Rijndael algorithm.
    ///</summary>
    ///<param name="inputFile"></param>
    ///<param name="outputFile"></param>
    private void DecryptFile(string inputFile, string outputFile)
    {
    
        {
            string password = @"myKey123"; // Your Key Here
    
            UnicodeEncoding UE = new UnicodeEncoding();
            byte[] key = UE.GetBytes(password);
    
            FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
    
            RijndaelManaged RMCrypto = new RijndaelManaged();
    
            CryptoStream cs = new CryptoStream(fsCrypt,
                RMCrypto.CreateDecryptor(key, key),
                CryptoStreamMode.Read);
    
            FileStream fsOut = new FileStream(outputFile, FileMode.Create);
    
            int data;
            while ((data = cs.ReadByte()) != -1)
                fsOut.WriteByte((byte)data);
    
            fsOut.Close();
            cs.Close();
            fsCrypt.Close();
    
        }
    }
    

    来源:http://www.codeproject.com/Articles/26085/File-Encryption-and-Decryption-in-C

  • 4

    一个有机体的大小是另一个有点娇小,虽然我们看到它时都知道很贵 . 眨眼眨眼 .

    尝试在您的环境中对以下内容进行基准测试,并查看您所处的位置:

    编辑2012年2月13日:代码已经更新,因为我已经悄悄进入了错误.Mea culpa .

    using System;
    using System.IO;
    using System.Security.Cryptography;
    using System.Text;
    
    ...
    
        // Rfc2898DeriveBytes constants:
        public readonly byte[] salt = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Must be at least eight bytes.  MAKE THIS SALTIER!
        public const int iterations = 1042; // Recommendation is >= 1000.
    
        /// <summary>Decrypt a file.</summary>
        /// <remarks>NB: "Padding is invalid and cannot be removed." is the Universal CryptoServices error.  Make sure the password, salt and iterations are correct before getting nervous.</remarks>
        /// <param name="sourceFilename">The full path and name of the file to be decrypted.</param>
        /// <param name="destinationFilename">The full path and name of the file to be output.</param>
        /// <param name="password">The password for the decryption.</param>
        /// <param name="salt">The salt to be applied to the password.</param>
        /// <param name="iterations">The number of iterations Rfc2898DeriveBytes should use before generating the key and initialization vector for the decryption.</param>
        public void DecryptFile(string sourceFilename, string destinationFilename, string password, byte[] salt, int iterations)
        {
            AesManaged aes = new AesManaged();
            aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
            aes.KeySize = aes.LegalKeySizes[0].MaxSize;
            // NB: Rfc2898DeriveBytes initialization and subsequent calls to   GetBytes   must be eactly the same, including order, on both the encryption and decryption sides.
            Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt, iterations);
            aes.Key = key.GetBytes(aes.KeySize / 8);
            aes.IV = key.GetBytes(aes.BlockSize / 8);
            aes.Mode = CipherMode.CBC;
            ICryptoTransform transform = aes.CreateDecryptor(aes.Key, aes.IV);
    
            using (FileStream destination = new FileStream(destinationFilename, FileMode.CreateNew, FileAccess.Write, FileShare.None))
            {
                using (CryptoStream cryptoStream = new CryptoStream(destination, transform, CryptoStreamMode.Write))
                {
                    try
                    {
                        using (FileStream source = new FileStream(sourceFilename, FileMode.Open, FileAccess.Read, FileShare.Read))
                        {
                            source.CopyTo(cryptoStream);
                        }
                    }
                    catch (CryptographicException exception)
                    {
                        if (exception.Message == "Padding is invalid and cannot be removed.")
                            throw new ApplicationException("Universal Microsoft Cryptographic Exception (Not to be believed!)", exception);
                        else
                            throw;
                    }
                }
            }
        }
    
        /// <summary>Encrypt a file.</summary>
        /// <param name="sourceFilename">The full path and name of the file to be encrypted.</param>
        /// <param name="destinationFilename">The full path and name of the file to be output.</param>
        /// <param name="password">The password for the encryption.</param>
        /// <param name="salt">The salt to be applied to the password.</param>
        /// <param name="iterations">The number of iterations Rfc2898DeriveBytes should use before generating the key and initialization vector for the decryption.</param>
        public void EncryptFile(string sourceFilename, string destinationFilename, string password, byte[] salt, int iterations)
        {
            AesManaged aes = new AesManaged();
            aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
            aes.KeySize = aes.LegalKeySizes[0].MaxSize;
            // NB: Rfc2898DeriveBytes initialization and subsequent calls to   GetBytes   must be eactly the same, including order, on both the encryption and decryption sides.
            Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt, iterations);
            aes.Key = key.GetBytes(aes.KeySize / 8);
            aes.IV = key.GetBytes(aes.BlockSize / 8);
            aes.Mode = CipherMode.CBC;
            ICryptoTransform transform = aes.CreateEncryptor(aes.Key, aes.IV);
    
            using (FileStream destination = new FileStream(destinationFilename, FileMode.CreateNew, FileAccess.Write, FileShare.None))
            {
                using (CryptoStream cryptoStream = new CryptoStream(destination, transform, CryptoStreamMode.Write))
                {
                    using (FileStream source = new FileStream(sourceFilename, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        source.CopyTo(cryptoStream);
                    }
                }
            }
        }
    
  • 10

    通常,当数据在一台计算机(如服务器)上加密,然后由另一台计算机(客户端)解密时,使用您所描述的策略 . 服务器将使用对称密钥加密(用于性能)使用新生成的密钥加密数据,并使用公钥(匹配客户端的私钥)加密此对称密钥 . 服务器向客户端发送加密数据和加密对称密钥 . 客户端可以用它的私钥解密对称密钥,然后使用这个对称密钥来解密数据 . 如果您正在加密和解密同一台计算机上的数据,则使用RSA和AES可能没有意义,因为您不会尝试将加密密钥传递给另一台计算机 .

  • 12

    就像你所听到的那样,非对称加密技术(如RSA)比对称加密技术(例如AES)慢得多,但它的优点是(简单的密钥管理,例如保护的单个私钥) .

    密钥(双关语)是利用两者的优点(非对称私钥和对称速度)而忽略了另一方的不便(许多密钥和慢速) .

    您可以通过每个文件使用一次RSA(没有巨大的性能影响)来加密用于加密(更快)大文件的(对称)密钥 . 这种对称密钥的包装允许您只管理一个私钥 .

    这是一个链接到我的旧(但仍然是真的)blog post,它提供了一个使用C#和.NET框架(Microsoft Mono)的例子 .

相关问题