如何在c#中加密和解密字符串?


当前回答

下面是如何使用Bouncy castle包进行AES-GCM加密/解密的示例。

当我在谷歌上搜索从GOlang crypto/aes api解密数据的可能性时,我发现了这个示例:

const (
    gcmBlockSize         = 16 // this is key size
    gcmTagSize           = 16 // this is mac
    gcmStandardNonceSize = 12 // this is nonce
)

func encrypt(data []byte, passphrase string) []byte {
    block, _ := aes.NewCipher([]byte(createHash(passphrase)))
    gcm, err := cipher.NewGCM(block)
    if err != nil {
        panic(err.Error())
    }
    nonce := make([]byte, gcm.NonceSize())
    if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
        panic(err.Error())
    }
    ciphertext := gcm.Seal(nonce, nonce, data, nil)
    return ciphertext
}

. net sample就像一个带有key(256位),mac(128位)和nonce(96位)的咒语。

其他回答

我想给你我的贡献,与我的代码AES Rfc2898DeriveBytes(这里的文档)算法,写在c#(。NET框架4),并且完全适用于有限的平台,如Windows Phone 7.0+的.NET紧凑框架(不是所有平台都支持.NET框架的每一种编码方法!)

我希望这能帮助到任何人!

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public static class Crypto
{
    private static readonly byte[] IVa = new byte[] { 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x11, 0x12, 0x13, 0x14, 0x0e, 0x16, 0x17 };


    public static string Encrypt(this string text, string salt)
    {
        try
        {
            using (Aes aes = new AesManaged())
            {
                Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(Encoding.UTF8.GetString(IVa, 0, IVa.Length), Encoding.UTF8.GetBytes(salt));
                aes.Key = deriveBytes.GetBytes(128 / 8);
                aes.IV = aes.Key;
                using (MemoryStream encryptionStream = new MemoryStream())
                {
                    using (CryptoStream encrypt = new CryptoStream(encryptionStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        byte[] cleanText = Encoding.UTF8.GetBytes(text);
                        encrypt.Write(cleanText, 0, cleanText.Length);
                        encrypt.FlushFinalBlock();
                    }

                    byte[] encryptedData = encryptionStream.ToArray();
                    string encryptedText = Convert.ToBase64String(encryptedData);


                    return encryptedText;
                }
            }
        }
        catch
        {
            return String.Empty;
        }
    }

    public static string Decrypt(this string text, string salt)
    {
        try
        {
            using (Aes aes = new AesManaged())
            {
                Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(Encoding.UTF8.GetString(IVa, 0, IVa.Length), Encoding.UTF8.GetBytes(salt));
                aes.Key = deriveBytes.GetBytes(128 / 8);
                aes.IV = aes.Key;

                using (MemoryStream decryptionStream = new MemoryStream())
                {
                    using (CryptoStream decrypt = new CryptoStream(decryptionStream, aes.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        byte[] encryptedData = Convert.FromBase64String(text);


                        decrypt.Write(encryptedData, 0, encryptedData.Length);
                        decrypt.Flush();
                    }

                    byte[] decryptedData = decryptionStream.ToArray();
                    string decryptedText = Encoding.UTF8.GetString(decryptedData, 0, decryptedData.Length);


                    return decryptedText;
                }
            }
        }
        catch
        {
            return String.Empty;
        }
        }
    }
}

支持mattmanser的回答。下面是一个使用MachineKey类加密/解密URL安全值的示例。

Something to bear in mind, as mentioned before, this will use Machine config settings (https://msdn.microsoft.com/en-us/library/ff649308.aspx). You can set encryption and decryption key/algorithm manually (you might need this specially if your site is running on multiple servers) in web.config file. You can generate keys from IIS (see here: https://blogs.msdn.microsoft.com/vijaysk/2009/05/13/iis-7-tip-10-you-can-generate-machine-keys-from-the-iis-manager/) or can use an online machine key generator like: http://www.developerfusion.com/tools/generatemachinekey/

    private static readonly UTF8Encoding Encoder = new UTF8Encoding();

    public static string Encrypt(string unencrypted)
    {
        if (string.IsNullOrEmpty(unencrypted)) 
            return string.Empty;

        try
        {
            var encryptedBytes = MachineKey.Protect(Encoder.GetBytes(unencrypted));

            if (encryptedBytes != null && encryptedBytes.Length > 0)
                return HttpServerUtility.UrlTokenEncode(encryptedBytes);    
        }
        catch (Exception)
        {
            return string.Empty;
        }

        return string.Empty;
    }

    public static string Decrypt(string encrypted)
    {
        if (string.IsNullOrEmpty(encrypted)) 
            return string.Empty;

        try
        {
            var bytes = HttpServerUtility.UrlTokenDecode(encrypted);
            if (bytes != null && bytes.Length > 0)
            {
                var decryptedBytes = MachineKey.Unprotect(bytes);
                if(decryptedBytes != null && decryptedBytes.Length > 0)
                    return Encoder.GetString(decryptedBytes);
            }

        }
        catch (Exception)
        {
            return string.Empty;
        }

        return string.Empty;
    }

下面是一个简单的例子,在c#中使用AES CBC模式加密字符串,并使用随机IV和HMAC和密码派生密钥,以显示基本的移动部分:

private byte[] EncryptBytes(byte[] key, byte[] plaintext)
{
    using (var cipher = new RijndaelManaged { Key = key })
    {
        using (var encryptor = cipher.CreateEncryptor())
        {
            var ciphertext = encryptor.TransformFinalBlock(plaintext, 0, plaintext.Length);

            // IV is prepended to ciphertext
            return cipher.IV.Concat(ciphertext).ToArray();
        }
    }
}

private byte[] DecryptBytes(byte[] key, byte[] packed)
{
    using (var cipher = new RijndaelManaged { Key = key })
    {
        int ivSize = cipher.BlockSize / 8;

        cipher.IV = packed.Take(ivSize).ToArray();

        using (var encryptor = cipher.CreateDecryptor())
        {
            return encryptor.TransformFinalBlock(packed, ivSize, packed.Length - ivSize);
        }
    }
}

private byte[] AddMac(byte[] key, byte[] data)
{
    using (var hmac = new HMACSHA256(key))
    {
        var macBytes = hmac.ComputeHash(data);

        // HMAC is appended to data
        return data.Concat(macBytes).ToArray();
    }
}

private bool BadMac(byte[] found, byte[] computed)
{
    int mismatch = 0;

    // Aim for consistent timing regardless of inputs
    for (int i = 0; i < found.Length; i++)
    {
        mismatch += found[i] == computed[i] ? 0 : 1;
    }

    return mismatch != 0;
}

private byte[] RemoveMac(byte[] key, byte[] data)
{
    using (var hmac = new HMACSHA256(key))
    {
        int macSize = hmac.HashSize / 8;

        var packed = data.Take(data.Length - macSize).ToArray();

        var foundMac = data.Skip(packed.Length).ToArray();

        var computedMac = hmac.ComputeHash(packed);

        if (this.BadMac(foundMac, computedMac))
        {
            throw new Exception("Bad MAC");
        }

        return packed;
    }            
}

private List<byte[]> DeriveTwoKeys(string password)
{
    var salt = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

    var kdf = new Rfc2898DeriveBytes(password, salt, 10000);

    var bytes = kdf.GetBytes(32); // Two keys 128 bits each

    return new List<byte[]> { bytes.Take(16).ToArray(), bytes.Skip(16).ToArray() };
}

public byte[] EncryptString(string password, String message)
{
    var keys = this.DeriveTwoKeys(password);

    var plaintext = Encoding.UTF8.GetBytes(message);

    var packed = this.EncryptBytes(keys[0], plaintext);

    return this.AddMac(keys[1], packed);
}

public String DecryptString(string password, byte[] secret)
{
    var keys = this.DeriveTwoKeys(password);

    var packed = this.RemoveMac(keys[1], secret);

    var plaintext = this.DecryptBytes(keys[0], packed);

    return Encoding.UTF8.GetString(plaintext);
}

public void Example()
{
    var password = "correcthorsebatterystaple";

    var secret = this.EncryptString(password, "Hello World");

    Console.WriteLine("secret: " + BitConverter.ToString(secret));

    var recovered = this.DecryptString(password, secret);

    Console.WriteLine(recovered);
}

AES算法:

public static class CryptographyProvider
    {
        public static string EncryptString(string plainText, out string Key)
        {
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");

            using (Aes _aesAlg = Aes.Create())
            {
                Key = Convert.ToBase64String(_aesAlg.Key);
                ICryptoTransform _encryptor = _aesAlg.CreateEncryptor(_aesAlg.Key, _aesAlg.IV);

                using (MemoryStream _memoryStream = new MemoryStream())
                {
                    _memoryStream.Write(_aesAlg.IV, 0, 16);
                    using (CryptoStream _cryptoStream = new CryptoStream(_memoryStream, _encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter _streamWriter = new StreamWriter(_cryptoStream))
                        {
                            _streamWriter.Write(plainText);
                        }
                        return Convert.ToBase64String(_memoryStream.ToArray());
                    }
                }
            }
        }
        public static string DecryptString(string cipherText, string Key)
        {

            if (string.IsNullOrEmpty(cipherText))
                throw new ArgumentNullException("cipherText");
            if (string.IsNullOrEmpty(Key))
                throw new ArgumentNullException("Key");

            string plaintext = null;

            byte[] _initialVector = new byte[16];
            byte[] _Key = Convert.FromBase64String(Key);
            byte[] _cipherTextBytesArray = Convert.FromBase64String(cipherText);
            byte[] _originalString = new byte[_cipherTextBytesArray.Length - 16];

            Array.Copy(_cipherTextBytesArray, 0, _initialVector, 0, _initialVector.Length);
            Array.Copy(_cipherTextBytesArray, 16, _originalString, 0, _cipherTextBytesArray.Length - 16);

            using (Aes _aesAlg = Aes.Create())
            {
                _aesAlg.Key = _Key;
                _aesAlg.IV = _initialVector;
                ICryptoTransform decryptor = _aesAlg.CreateDecryptor(_aesAlg.Key, _aesAlg.IV);

                using (MemoryStream _memoryStream = new MemoryStream(_originalString))
                {
                    using (CryptoStream _cryptoStream = new CryptoStream(_memoryStream, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader _streamReader = new StreamReader(_cryptoStream))
                        {
                            plaintext = _streamReader.ReadToEnd();
                        }
                    }
                }
            }
            return plaintext;
        }
    }

加密是编程中非常常见的问题。我认为最好是安装一个包来为您做这个任务。也许是一个简单的开源NuGet项目 简单Aes加密

密钥在配置文件中,因此很容易在生产环境中更改,而且我没有看到任何缺点。

<MessageEncryption>
  <EncryptionKey KeySize="256" Key="3q2+796tvu/erb7v3q2+796tvu/erb7v3q2+796tvu8="/>
</MessageEncryption>