简体   繁体   English

用C#加密数据

[英]Encrypting data in C#

I have an application that needs to encrypt data which is then stored in files. 我有一个需要加密然后存储在文件中的数据的应用程序。 This data should be encrypted to an industry standard such as AES. 此数据应加密为行业标准,例如AES。 The data may be either text or binary data. 数据可以是文本或二进制数据。

Rather than store the key somewhere, the user should supply an alphanumeric password (used as the key) to decrypt the data. 用户应该提供一个字母数字密码(用作密钥)来解密数据,而不是将密钥存储在某个地方。

What is the best way to go about this in C# .NET 3.5? 在C#.NET 3.5中进行此操作的最佳方法是什么? Ideally I am looking for a black box class that I can use like so: 理想情况下,我正在寻找可以像这样使用的黑匣子类:

byte[] writeThisToFile = EncryptionClass.Encrypt(string data, string password);

byte[] writeThisToFile = EncryptionClass.Encrypt(byte[] data, string password);

byte[] plainBinaryData = EncryptionClass.DecryptBinary(byte[] encryptedFileContents, string password);

string plainText = EncryptionClass.DecryptText(byte[] encryptedFileContents, string password);

You need a "Password based key derivation function", or PBKDF2. 您需要一个“基于密码的密钥派生功能”或PBKDF2。

For AES 128, MD5 gives you the right size output, so this works as a key generation function (but keep reading) : 对于AES 128,MD5为您提供正确的大小输出,因此它可以用作密钥生成功能(但请继续阅读):

key = md5("MyPassw0rd!");

But it is very weak. 但这是非常薄弱的​​。 PBKDF add many iterations of salt, something like this : PBKDF添加了许多次salt迭代,如下所示:

salt = "SomeValueDifferentForEachKeyGenerated";
key = md5(salt+md5(salt+md5(salt+md5(salt+"MyPassw0rd!"))));

Which is better, but still weak. 哪个更好,但仍然很弱。 MD5 is not the strongest hash algorithm around and there isn't enough iterations. MD5不是周围最强大的哈希算法,并且迭代次数不足。

There are a good number of PBKDF functions on StackOverflow , pick one that suits you most. StackOverflow上有很多PBKDF函数 ,请选择最适合您的一个。

    using System.IO;
    using System.Security;
    using System.Security.Cryptography;
    using System.Runtime.InteropServices;   

    // <summary>  
    // Encrypts a string          
    // </summary>        
    // <param name="CipherText">Text to be Encrypted</param>         
    // <param name="Password">Password to Encrypt with</param>         
    // <param name="Salt">Salt to Encrypt with</param>          
    // <param name="HashAlgorithm">Can be either SHA1 or MD5</param>         
    // <param name="PasswordIterations">Number of iterations to do</param>          
    // <param name="InitialVector">Needs to be 16 ASCII characters long</param>          
    // <param name="KeySize">Can be 128, 192, or 256</param>          
    // <returns>A decrypted string</returns>       
    public static string AESEncrypt(string PlainText, string Password, string Salt, string HashAlgorithm, int PasswordIterations, string InitialVector, int KeySize)
    {
        if (string.IsNullOrEmpty(PlainText))
        {
            return "The Text to be Decryped by AES must not be null...";
        }
        else if (string.IsNullOrEmpty(Password))
        {
            return "The Password for AES Decryption must not be null...";
        }
        byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
        byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
        byte[] PlainTextBytes = Encoding.UTF8.GetBytes(PlainText);
        PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
        byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);

        RijndaelManaged SymmetricKey = new RijndaelManaged();

        SymmetricKey.Mode = CipherMode.CBC;

        byte[] CipherTextBytes = null;

        using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes))
        {

            using (MemoryStream MemStream = new MemoryStream())
            {
                using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write))
                {
                    CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
                    CryptoStream.FlushFinalBlock();
                    CipherTextBytes = MemStream.ToArray();
                    MemStream.Close();
                    CryptoStream.Close();
                }
            }
        }
        SymmetricKey.Clear();
        return Convert.ToBase64String(CipherTextBytes);

    }


    // <summary>  
    // Decrypts a string          
    // </summary>        
    // <param name="CipherText">Text to be decrypted</param>         
    // <param name="Password">Password to decrypt with</param>         
    // <param name="Salt">Salt to decrypt with</param>          
    // <param name="HashAlgorithm">Can be either SHA1 or MD5</param>         
    // <param name="PasswordIterations">Number of iterations to do</param>          
    // <param name="InitialVector">Needs to be 16 ASCII characters long</param>          
    // <param name="KeySize">Can be 128, 192, or 256</param>          
    // <returns>A decrypted string</returns>        
    public static string AESDecrypt(string CipherText, string Password, string Salt, string HashAlgorithm, int PasswordIterations, string InitialVector, int KeySize)
    {
        if (string.IsNullOrEmpty(CipherText))
        {
            return "The Text to be Decryped by AES must not be null...";
        }
        else if (string.IsNullOrEmpty(Password))
        {
            return "The Password for AES Decryption must not be null...";
        }
        byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
        byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
        byte[] CipherTextBytes = Convert.FromBase64String(CipherText);
        PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
        byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
        RijndaelManaged SymmetricKey = new RijndaelManaged();
        SymmetricKey.Mode = CipherMode.CBC;
        byte[] PlainTextBytes = new byte[CipherTextBytes.Length];
        int ByteCount = 0;
        try
        {

            using (ICryptoTransform Decryptor = SymmetricKey.CreateDecryptor(KeyBytes, InitialVectorBytes))
            {
                using (MemoryStream MemStream = new MemoryStream(CipherTextBytes))
                {
                    using (CryptoStream CryptoStream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read))
                    {
                        ByteCount = CryptoStream.Read(PlainTextBytes, 0, PlainTextBytes.Length);
                        MemStream.Close();
                        CryptoStream.Close();
                    }
                }
            }
        }
        catch (Exception e)
        {
            return "Please Enter the Correct Password and Salt..." + "The Following Error Occured: " + "/n" + e;
        }
        SymmetricKey.Clear();
        return Encoding.UTF8.GetString(PlainTextBytes, 0, ByteCount);

    }

Can't Remember exactly where I acquired this code from, but I altered it to return the encrypted Result as a string. 记不清我是从哪里获得此代码的,但是我更改了它以将加密的结果作为字符串返回。 These Methods could easily be wrapped into a FileEncryptor Class. 这些方法可以很容易地包装到FileEncryptor类中。 Although I am sure there are better solutions out there... 尽管我确信那里有更好的解决方案...

you should used 你应该用

byte[] writeThisToFile = EncryptionClass.Encrypt(byte[] data, string password);

byte[] plainBinaryData = EncryptionClass.DecryptBinary(byte[] encryptedFileContents, string password); 

for details read following article http://explicitcoder.in/encryption-and-decryption-methods-text-file-and-binary-files-c-net/ 有关详细信息,请阅读以下文章http://explicitcoder.in/encryption-and-decryption-methods-text-file-and-binary-files-c-net/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM