繁体   English   中英

用C#加密数据

[英]Encrypting data in C#

我有一个需要加密然后存储在文件中的数据的应用程序。 此数据应加密为行业标准,例如AES。 数据可以是文本或二进制数据。

用户应该提供一个字母数字密码(用作密钥)来解密数据,而不是将密钥存储在某个地方。

在C#.NET 3.5中进行此操作的最佳方法是什么? 理想情况下,我正在寻找可以像这样使用的黑匣子类:

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);

您需要一个“基于密码的密钥派生功能”或PBKDF2。

对于AES 128,MD5为您提供正确的大小输出,因此它可以用作密钥生成功能(但请继续阅读):

key = md5("MyPassw0rd!");

但这是非常薄弱的​​。 PBKDF添加了许多次salt迭代,如下所示:

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

哪个更好,但仍然很弱。 MD5不是周围最强大的哈希算法,并且迭代次数不足。

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);

    }

记不清我是从哪里获得此代码的,但是我更改了它以将加密的结果作为字符串返回。 这些方法可以很容易地包装到FileEncryptor类中。 尽管我确信那里有更好的解决方案...

你应该用

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

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

有关详细信息,请阅读以下文章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