CSharp - 加密和解密字符串

  显示原文与译文双语对照的内容

有人可以给我加密和解密 C# 中字符串的代码?

时间:

编辑 2013 -Oct: 尽管随着时间的推移我编辑这个答案解决的缺点,请参阅回答jbtule更健壮,明智的解决方案。

http://stackoverflow.com 10366194/188474

原始答案:

下面是来自 "rijndaelmanaged类"文档MCTS培训工具包。的一个工作示例。

编辑 2012 -April: 这个答案被编辑为pre-pend的每一个建议的IV,如下所示:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.aesmanaged%28v=vs.95%29.aspx

祝你好运


public class Crypto
{
 private static byte[] _salt = Encoding.ASCII.GetBytes("o6806642kbM7c5");

///<summary>
///Encrypt the given string using AES. The string can be decrypted using 
///DecryptStringAES(). The sharedSecret parameters must match.
///</summary>
///<param name="plainText">The text to encrypt.</param>
///<param name="sharedSecret">A password used to generate a key for encryption.</param>
 public static string EncryptStringAES(string plainText, string sharedSecret)
 {
 if (string.IsNullOrEmpty(plainText))
 throw new ArgumentNullException("plainText");
 if (string.IsNullOrEmpty(sharedSecret))
 throw new ArgumentNullException("sharedSecret");

 string outStr = null;//Encrypted string to return
 RijndaelManaged aesAlg = null;//RijndaelManaged object used to encrypt the data.

 try
 {
//generate the key from the shared secret and the salt
 Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);

//Create a RijndaelManaged object
 aesAlg = new RijndaelManaged();
 aesAlg.Key = key.GetBytes(aesAlg.KeySize/8);

//Create a decryptor to perform the stream transform.
 ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

//Create the streams used for encryption.
 using (MemoryStream msEncrypt = new MemoryStream())
 {
//prepend the IV
 msEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int));
 msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length);
 using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
 {
 using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
 {
//Write all data to the stream.
 swEncrypt.Write(plainText);
 }
 }
 outStr = Convert.ToBase64String(msEncrypt.ToArray());
 }
 }
 finally
 {
//Clear the RijndaelManaged object.
 if (aesAlg!= null)
 aesAlg.Clear();
 }

//Return the encrypted bytes from the memory stream.
 return outStr;
 }

///<summary>
///Decrypt the given string. Assumes the string was encrypted using 
///EncryptStringAES(), using an identical sharedSecret.
///</summary>
///<param name="cipherText">The text to decrypt.</param>
///<param name="sharedSecret">A password used to generate a key for decryption.</param>
 public static string DecryptStringAES(string cipherText, string sharedSecret)
 {
 if (string.IsNullOrEmpty(cipherText))
 throw new ArgumentNullException("cipherText");
 if (string.IsNullOrEmpty(sharedSecret))
 throw new ArgumentNullException("sharedSecret");

//Declare the RijndaelManaged object
//used to decrypt the data.
 RijndaelManaged aesAlg = null;

//Declare the string used to hold
//the decrypted text.
 string plaintext = null;

 try
 {
//generate the key from the shared secret and the salt
 Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);

//Create the streams used for decryption. 
 byte[] bytes = Convert.FromBase64String(cipherText);
 using (MemoryStream msDecrypt = new MemoryStream(bytes))
 {
//Create a RijndaelManaged object
//with the specified key and IV.
 aesAlg = new RijndaelManaged();
 aesAlg.Key = key.GetBytes(aesAlg.KeySize/8);
//Get the initialization vector from the encrypted stream
 aesAlg.IV = ReadByteArray(msDecrypt);
//Create a decrytor to perform the stream transform.
 ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
 using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
 {
 using (StreamReader srDecrypt = new StreamReader(csDecrypt))

//Read the decrypted bytes from the decrypting stream
//and place them in a string.
 plaintext = srDecrypt.ReadToEnd();
 }
 }
 }
 finally
 {
//Clear the RijndaelManaged object.
 if (aesAlg!= null)
 aesAlg.Clear();
 }

 return plaintext;
 }

 private static byte[] ReadByteArray(Stream s)
 {
 byte[] rawLength = new byte[sizeof(int)];
 if (s.Read(rawLength, 0, rawLength.Length)!= rawLength.Length)
 {
 throw new SystemException("Stream did not contain properly formatted byte array");
 }

 byte[] buffer = new byte[BitConverter.ToInt32(rawLength, 0)];
 if (s.Read(buffer, 0, buffer.Length)!= buffer.Length)
 {
 throw new SystemException("Did not read byte array properly");
 }

 return buffer;
 }
}

为一个字符串的对称认证加密提供了的现代示例。

对称加密的一般最佳实践是使用带关联数据( AEAD )的经过身份验证的加密,但是这不是标准. NET 加密库的一部分。 第一个例子使用 AES256然后 HMAC256,两步加密然后mac,这需要更多的开销和钥匙。

第二个示例使用的简单实践 AES256- GCM使用开源bouncy Castle ( 通过 nuget ) 。

两个例子有一个主要功能,秘密消息字符串键和一个可选的non-secret载荷和返回认证和加密的字符串有选择地将non-secret数据。 理想情况下,你将使用这些随机生成的256位密钥查看 NewKey()

两个示例都有一个使用字符串密码生成密钥的helper 方法。 这些 helper 方法是为了方便匹配提供了其他的例子,然而他们安全少得多,因为密码的强度是远远弱于 256位键。

更新: 添加了 byte[] 重载,并且只有标题具有 4空格缩进和api文档,因为StackOverflow回答限制。


.NET 内置 Encrypt(AES)-Then-MAC(HMAC) [Gist]


/*
 * This work (Modern Encryption of a String C#, by James Tuley), 
 * identified by James Tuley, is free of known copyright restrictions.
 * https://gist.github.com/4336842
 * http://creativecommons.org/publicdomain/mark/1.0/
 */

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

namespace Encryption
{
 public static class AESThenHMAC
 {
 private static readonly RandomNumberGenerator Random = RandomNumberGenerator.Create();

//Preconfigured Encryption Parameters
 public static readonly int BlockBitSize = 128;
 public static readonly int KeyBitSize = 256;

//Preconfigured Password Key Derivation Parameters
 public static readonly int SaltBitSize = 64;
 public static readonly int Iterations = 10000;
 public static readonly int MinPasswordLength = 12;

///<summary>
///Helper that generates a random key on each call.
///</summary>
///<returns></returns>
 public static byte[] NewKey()
 {
 var key = new byte[KeyBitSize/8];
 Random.GetBytes(key);
 return key;
 }

///<summary>
///Simple Encryption (AES) then Authentication (HMAC) for a UTF8 Message.
///</summary>
///<param name="secretMessage">The secret message.</param>
///<param name="cryptKey">The crypt key.</param>
///<param name="authKey">The auth key.</param>
///<param name="nonSecretPayload">(Optional) Non-Secret Payload.</param>
///<returns>
///Encrypted Message
///</returns>
///<exception cref="System.ArgumentException">Secret Message Required!;secretMessage</exception>
///<remarks>
///Adds overhead of (Optional-Payload + BlockSize(16) + Message-Padded-To-Blocksize + HMac-Tag(32)) * 1.33 Base64
///</remarks>
 public static string SimpleEncrypt(string secretMessage, byte[] cryptKey, byte[] authKey,
 byte[] nonSecretPayload = null)
 {
 if (string.IsNullOrEmpty(secretMessage))
 throw new ArgumentException("Secret Message Required!","secretMessage");

 var plainText = Encoding.UTF8.GetBytes(secretMessage);
 var cipherText = SimpleEncrypt(plainText, cryptKey, authKey, nonSecretPayload);
 return Convert.ToBase64String(cipherText);
 }

///<summary>
///Simple Authentication (HMAC) then Decryption (AES) for a secrets UTF8 Message.
///</summary>
///<param name="encryptedMessage">The encrypted message.</param>
///<param name="cryptKey">The crypt key.</param>
///<param name="authKey">The auth key.</param>
///<param name="nonSecretPayloadLength">Length of the non secret payload.</param>
///<returns>
///Decrypted Message
///</returns>
///<exception cref="System.ArgumentException">Encrypted Message Required!;encryptedMessage</exception>
 public static string SimpleDecrypt(string encryptedMessage, byte[] cryptKey, byte[] authKey,
 int nonSecretPayloadLength = 0)
 {
 if (string.IsNullOrWhiteSpace(encryptedMessage))
 throw new ArgumentException("Encrypted Message Required!","encryptedMessage");

 var cipherText = Convert.FromBase64String(encryptedMessage);
 var plainText = SimpleDecrypt(cipherText, cryptKey, authKey, nonSecretPayloadLength);
 return plaintext == null? null : Encoding.UTF8.GetString(plainText);
 }

///<summary>
///Simple Encryption (AES) then Authentication (HMAC) of a UTF8 message
///using Keys derived from a Password (PBKDF2).
///</summary>
///<param name="secretMessage">The secret message.</param>
///<param name="password">The password.</param>
///<param name="nonSecretPayload">The non secret payload.</param>
///<returns>
///Encrypted Message
///</returns>
///<exception cref="System.ArgumentException">password</exception>
///<remarks>
///Significantly less secure than using random binary keys.
///Adds additional non secret payload for key generation parameters.
///</remarks>
 public static string SimpleEncryptWithPassword(string secretMessage, string password,
 byte[] nonSecretPayload = null)
 {
 if (string.IsNullOrEmpty(secretMessage))
 throw new ArgumentException("Secret Message Required!","secretMessage");

 var plainText = Encoding.UTF8.GetBytes(secretMessage);
 var cipherText = SimpleEncryptWithPassword(plainText, password, nonSecretPayload);
 return Convert.ToBase64String(cipherText);
 }

///<summary>
///Simple Authentication (HMAC) and then Descryption (AES) of a UTF8 Message
///using keys derived from a password (PBKDF2). 
///</summary>
///<param name="encryptedMessage">The encrypted message.</param>
///<param name="password">The password.</param>
///<param name="nonSecretPayloadLength">Length of the non secret payload.</param>
///<returns>
///Decrypted Message
///</returns>
///<exception cref="System.ArgumentException">Encrypted Message Required!;encryptedMessage</exception>
///<remarks>
///Significantly less secure than using random binary keys.
///</remarks>
 public static string SimpleDecryptWithPassword(string encryptedMessage, string password,
 int nonSecretPayloadLength = 0)
 {
 if (string.IsNullOrWhiteSpace(encryptedMessage))
 throw new ArgumentException("Encrypted Message Required!","encryptedMessage");

 var cipherText = Convert.FromBase64String(encryptedMessage);
 var plainText = SimpleDecryptWithPassword(cipherText, password, nonSecretPayloadLength);
 return plainText == null? null : Encoding.UTF8.GetString(plainText);
 }

 public static byte[] SimpleEncrypt(byte[] secretMessage, byte[] cryptKey, byte[] authKey, byte[] nonSecretPayload = null)
 {
//User Error Checks
 if (cryptKey == null || cryptKey.Length!= KeyBitSize/8)
 throw new ArgumentException(String.Format("Key needs to be {0} bit!", KeyBitSize),"cryptKey");

 if (authKey == null || authKey.Length!= KeyBitSize/8)
 throw new ArgumentException(String.Format("Key needs to be {0} bit!", KeyBitSize),"authKey");

 if (secretMessage == null || secretMessage.Length <1)
 throw new ArgumentException("Secret Message Required!","secretMessage");

//non-secret payload optional
 nonSecretPayload = nonSecretPayload?? new byte[] { };

 byte[] cipherText;
 byte[] iv;

 using (var aes = new AesManaged
 {
 KeySize = KeyBitSize,
 BlockSize = BlockBitSize,
 Mode = CipherMode.CBC,
 Padding = PaddingMode.PKCS7
 })
 {

//Use random IV
 aes.GenerateIV();
 iv = aes.IV;

 using (var encrypter = aes.CreateEncryptor(cryptKey, iv))
 using (var cipherStream = new MemoryStream())
 {
 using (var cryptoStream = new CryptoStream(cipherStream, encrypter, CryptoStreamMode.Write))
 using (var binaryWriter = new BinaryWriter(cryptoStream))
 {
//Encrypt Data
 binaryWriter.Write(secretMessage);
 }

 cipherText = cipherStream.ToArray();
 }

 }

//Assemble encrypted message and add authentication
 using (var hmac = new HMACSHA256(authKey))
 using (var encryptedStream = new MemoryStream())
 {
 using (var binaryWriter = new BinaryWriter(encryptedStream))
 {
//Prepend non-secret payload if any
 binaryWriter.Write(nonSecretPayload);
//Prepend IV
 binaryWriter.Write(iv);
//Write Ciphertext
 binaryWriter.Write(cipherText);
 binaryWriter.Flush();

//Authenticate all data
 var tag = hmac.ComputeHash(encryptedStream.ToArray());
//Postpend tag
 binaryWriter.Write(tag);
 }
 return encryptedStream.ToArray();
 }

 }

 public static byte[] SimpleDecrypt(byte[] encryptedMessage, byte[] cryptKey, byte[] authKey, int nonSecretPayloadLength = 0)
 {

//Basic Usage Error Checks
 if (cryptKey == null || cryptKey.Length!= KeyBitSize/8)
 throw new ArgumentException(String.Format("CryptKey needs to be {0} bit!", KeyBitSize),"cryptKey");

 if (authKey == null || authKey.Length!= KeyBitSize/8)
 throw new ArgumentException(String.Format("AuthKey needs to be {0} bit!", KeyBitSize),"authKey");

 if (encryptedMessage == null || encryptedMessage.Length == 0)
 throw new ArgumentException("Encrypted Message Required!","encryptedMessage");

 using (var hmac = new HMACSHA256(authKey))
 {
 var sentTag = new byte[hmac.HashSize/8];
//Calculate Tag
 var calcTag = hmac.ComputeHash(encryptedMessage, 0, encryptedMessage.Length - sentTag.Length);
 var ivLength = (BlockBitSize/8);

//if message length is to small just return null
 if (encryptedMessage.Length <sentTag.Length + nonSecretPayloadLength + ivLength)
 return null;

//Grab Sent Tag
 Array.Copy(encryptedMessage, encryptedMessage.Length - sentTag.Length, sentTag, 0, sentTag.Length);

//Compare Tag with constant time comparison
 var compare = 0;
 for (var i = 0; i <sentTag.Length; i++)
 compare |= sentTag[i] ^ calcTag[i]; 

//if message doesn't authenticate return null
 if (compare!= 0)
 return null;

 using (var aes = new AesManaged
 {
 KeySize = KeyBitSize,
 BlockSize = BlockBitSize,
 Mode = CipherMode.CBC,
 Padding = PaddingMode.PKCS7
 })
 {

//Grab IV from message
 var iv = new byte[ivLength];
 Array.Copy(encryptedMessage, nonSecretPayloadLength, iv, 0, iv.Length);

 using (var decrypter = aes.CreateDecryptor(cryptKey, iv))
 using (var plainTextStream = new MemoryStream())
 {
 using (var decrypterStream = new CryptoStream(plainTextStream, decrypter, CryptoStreamMode.Write))
 using (var binaryWriter = new BinaryWriter(decrypterStream))
 {
//Decrypt Cipher Text from Message
 binaryWriter.Write(
 encryptedMessage,
 nonSecretPayloadLength + iv.Length,
 encryptedMessage.Length - nonSecretPayloadLength - iv.Length - sentTag.Length
 );
 }
//Return Plain Text
 return plainTextStream.ToArray();
 }
 }
 }
 }

 public static byte[] SimpleEncryptWithPassword(byte[] secretMessage, string password, byte[] nonSecretPayload = null)
 {
 nonSecretPayload = nonSecretPayload?? new byte[] {};

//User Error Checks
 if (string.IsNullOrWhiteSpace(password) || password.Length <MinPasswordLength)
 throw new ArgumentException(String.Format("Must have a password of at least {0} characters!", MinPasswordLength),"password");

 if (secretMessage == null || secretMessage.Length ==0)
 throw new ArgumentException("Secret Message Required!","secretMessage");

 var payload = new byte[((SaltBitSize/8) * 2) + nonSecretPayload.Length];

 Array.Copy(nonSecretPayload, payload, nonSecretPayload.Length);
 int payloadIndex = nonSecretPayload.Length;

 byte[] cryptKey;
 byte[] authKey;
//Use Random Salt to prevent pre-generated weak password attacks.
 using (var generator = new Rfc2898DeriveBytes(password, SaltBitSize/8, Iterations))
 {
 var salt = generator.Salt;

//Generate Keys
 cryptKey = generator.GetBytes(KeyBitSize/8);

//Create Non Secret Payload
 Array.Copy(salt, 0, payload, payloadIndex, salt.Length);
 payloadIndex += salt.Length;
 }

//Deriving separate key, might be less efficient than using HKDF, 
//but now compatible with RNEncryptor which had a very similar wireformat and requires less code than HKDF.
 using (var generator = new Rfc2898DeriveBytes(password, SaltBitSize/8, Iterations))
 {
 var salt = generator.Salt;

//Generate Keys
 authKey = generator.GetBytes(KeyBitSize/8);

//Create Rest of Non Secret Payload
 Array.Copy(salt, 0, payload, payloadIndex, salt.Length);
 }

 return SimpleEncrypt(secretMessage, cryptKey, authKey, payload);
 }

 public static byte[] SimpleDecryptWithPassword(byte[] encryptedMessage, string password, int nonSecretPayloadLength = 0)
 {
//User Error Checks
 if (string.IsNullOrWhiteSpace(password) || password.Length <MinPasswordLength)
 throw new ArgumentException(String.Format("Must have a password of at least {0} characters!", MinPasswordLength),"password");

 if (encryptedMessage == null || encryptedMessage.Length == 0)
 throw new ArgumentException("Encrypted Message Required!","encryptedMessage");

 var cryptSalt = new byte[SaltBitSize/8];
 var authSalt = new byte[SaltBitSize/8];

//Grab Salt from Non-Secret Payload
 Array.Copy(encryptedMessage, nonSecretPayloadLength, cryptSalt, 0, cryptSalt.Length);
 Array.Copy(encryptedMessage, nonSecretPayloadLength + cryptSalt.Length, authSalt, 0, authSalt.Length);

 byte[] cryptKey;
 byte[] authKey;

//Generate crypt key
 using (var generator = new Rfc2898DeriveBytes(password, cryptSalt, Iterations))
 {
 cryptKey = generator.GetBytes(KeyBitSize/8);
 }
//Generate auth key
 using (var generator = new Rfc2898DeriveBytes(password, authSalt, Iterations))
 {
 authKey = generator.GetBytes(KeyBitSize/8);
 }

 return SimpleDecrypt(encryptedMessage, cryptKey, authKey, cryptSalt.Length + authSalt.Length + nonSecretPayloadLength);
 }
 }
}


弹城堡 AES-GCM [Gist]


/*
 * This work (Modern Encryption of a String C#, by James Tuley), 
 * identified by James Tuley, is free of known copyright restrictions.
 * https://gist.github.com/4336842
 * http://creativecommons.org/publicdomain/mark/1.0/
 */

using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace Encryption
{

 public static class AESGCM
 {
 private static readonly SecureRandom Random = new SecureRandom();

//Preconfigured Encryption Parameters
 public static readonly int NonceBitSize = 128;
 public static readonly int MacBitSize = 128;
 public static readonly int KeyBitSize = 256;

//Preconfigured Password Key Derivation Parameters
 public static readonly int SaltBitSize = 128;
 public static readonly int Iterations = 10000;
 public static readonly int MinPasswordLength = 12;


///<summary>
///Helper that generates a random new key on each call.
///</summary>
///<returns></returns>
 public static byte[] NewKey()
 {
 var key = new byte[KeyBitSize/8];
 Random.NextBytes(key);
 return key;
 }

///<summary>
///Simple Encryption And Authentication (AES-GCM) of a UTF8 string.
///</summary>
///<param name="secretMessage">The secret message.</param>
///<param name="key">The key.</param>
///<param name="nonSecretPayload">Optional non-secret payload.</param>
///<returns>
///Encrypted Message
///</returns>
///<exception cref="System.ArgumentException">Secret Message Required!;secretMessage</exception>
///<remarks>
///Adds overhead of (Optional-Payload + BlockSize(16) + Message + HMac-Tag(16)) * 1.33 Base64
///</remarks>
 public static string SimpleEncrypt(string secretMessage, byte[] key, byte[] nonSecretPayload = null)
 {
 if (string.IsNullOrEmpty(secretMessage))
 throw new ArgumentException("Secret Message Required!","secretMessage");

 var plainText = Encoding.UTF8.GetBytes(secretMessage);
 var cipherText = SimpleEncrypt(plainText, key, nonSecretPayload);
 return Convert.ToBase64String(cipherText);
 }


///<summary>
///Simple Decryption & Authentication (AES-GCM) of a UTF8 Message
///</summary>
///<param name="encryptedMessage">The encrypted message.</param>
///<param name="key">The key.</param>
///<param name="nonSecretPayloadLength">Length of the optional non-secret payload.</param>
///<returns>Decrypted Message</returns>
 public static string SimpleDecrypt(string encryptedMessage, byte[] key, int nonSecretPayloadLength = 0)
 {
 if (string.IsNullOrEmpty(encryptedMessage))
 throw new ArgumentException("Encrypted Message Required!","encryptedMessage");

 var cipherText = Convert.FromBase64String(encryptedMessage);
 var plaintext = SimpleDecrypt(cipherText, key, nonSecretPayloadLength);
 return plaintext == null? null : Encoding.UTF8.GetString(plaintext);
 }

///<summary>
///Simple Encryption And Authentication (AES-GCM) of a UTF8 String
///using key derived from a password (PBKDF2).
///</summary>
///<param name="secretMessage">The secret message.</param>
///<param name="password">The password.</param>
///<param name="nonSecretPayload">The non secret payload.</param>
///<returns>
///Encrypted Message
///</returns>
///<remarks>
///Significantly less secure than using random binary keys.
///Adds additional non secret payload for key generation parameters.
///</remarks>
 public static string SimpleEncryptWithPassword(string secretMessage, string password,
 byte[] nonSecretPayload = null)
 {
 if (string.IsNullOrEmpty(secretMessage))
 throw new ArgumentException("Secret Message Required!","secretMessage");

 var plainText = Encoding.UTF8.GetBytes(secretMessage);
 var cipherText = SimpleEncryptWithPassword(plainText, password, nonSecretPayload);
 return Convert.ToBase64String(cipherText);
 }


///<summary>
///Simple Decryption and Authentication (AES-GCM) of a UTF8 message
///using a key derived from a password (PBKDF2)
///</summary>
///<param name="encryptedMessage">The encrypted message.</param>
///<param name="password">The password.</param>
///<param name="nonSecretPayloadLength">Length of the non secret payload.</param>
///<returns>
///Decrypted Message
///</returns>
///<exception cref="System.ArgumentException">Encrypted Message Required!;encryptedMessage</exception>
///<remarks>
///Significantly less secure than using random binary keys.
///</remarks>
 public static string SimpleDecryptWithPassword(string encryptedMessage, string password,
 int nonSecretPayloadLength = 0)
 {
 if (string.IsNullOrWhiteSpace(encryptedMessage))
 throw new ArgumentException("Encrypted Message Required!","encryptedMessage");

 var cipherText = Convert.FromBase64String(encryptedMessage);
 var plaintext = SimpleDecryptWithPassword(cipherText, password, nonSecretPayloadLength);
 return plaintext == null? null : Encoding.UTF8.GetString(plaintext);
 }

 public static byte[] SimpleEncrypt(byte[] secretMessage, byte[] key, byte[] nonSecretPayload = null)
 {
//User Error Checks
 if (key == null || key.Length!= KeyBitSize/8)
 throw new ArgumentException(String.Format("Key needs to be {0} bit!", KeyBitSize),"key");

 if (secretMessage == null || secretMessage.Length == 0)
 throw new ArgumentException("Secret Message Required!","secretMessage");

//Non-secret Payload Optional
 nonSecretPayload = nonSecretPayload?? new byte[] { };

//Using random nonce large enough not to repeat
 var nonce = new byte[NonceBitSize/8];
 Random.NextBytes(nonce, 0, nonce.Length);

 var cipher = new GcmBlockCipher(new AesFastEngine());
 var parameters = new AeadParameters(new KeyParameter(key), MacBitSize, nonce, nonSecretPayload);
 cipher.Init(true, parameters);

//Generate Cipher Text With Auth Tag
 var cipherText = new byte[cipher.GetOutputSize(secretMessage.Length)];
 var len = cipher.ProcessBytes(secretMessage, 0, secretMessage.Length, cipherText, 0);
 cipher.DoFinal(cipherText, len);

//Assemble Message
 using (var combinedStream = new MemoryStream())
 {
 using (var binaryWriter = new BinaryWriter(combinedStream))
 {
//Prepend Authenticated Payload
 binaryWriter.Write(nonSecretPayload);
//Prepend Nonce
 binaryWriter.Write(nonce);
//Write Cipher Text
 binaryWriter.Write(cipherText);
 }
 return combinedStream.ToArray();
 }
 }

 public static byte[] SimpleDecrypt(byte[] encryptedMessage, byte[] key, int nonSecretPayloadLength = 0)
 {
//User Error Checks
 if (key == null || key.Length!= KeyBitSize/8)
 throw new ArgumentException(String.Format("Key needs to be {0} bit!", KeyBitSize),"key");

 if (encryptedMessage == null || encryptedMessage.Length == 0)
 throw new ArgumentException("Encrypted Message Required!","encryptedMessage");

 using (var cipherStream = new MemoryStream(encryptedMessage))
 using (var cipherReader = new BinaryReader(cipherStream))
 {
//Grab Payload
 var nonSecretPayload = cipherReader.ReadBytes(nonSecretPayloadLength);

//Grab Nonce
 var nonce = cipherReader.ReadBytes(NonceBitSize/8);

 var cipher = new GcmBlockCipher(new AesFastEngine());
 var parameters = new AeadParameters(new KeyParameter(key), MacBitSize, nonce, nonSecretPayload);
 cipher.Init(false, parameters);

//Decrypt Cipher Text
 var cipherText = cipherReader.ReadBytes(encryptedMessage.Length - nonSecretPayloadLength - nonce.Length);
 var plainText = new byte[cipher.GetOutputSize(cipherText.Length)]; 

 try
 {
 var len = cipher.ProcessBytes(cipherText, 0, cipherText.Length, plainText, 0);
 cipher.DoFinal(plainText, len);

 }
 catch (InvalidCipherTextException)
 {
//Return null if it doesn't authenticate
 return null;
 }

 return plainText;
 }

 }

 public static byte[] SimpleEncryptWithPassword(byte[] secretMessage, string password, byte[] nonSecretPayload = null)
 {
 nonSecretPayload = nonSecretPayload?? new byte[] {};

//User Error Checks
 if (string.IsNullOrWhiteSpace(password) || password.Length <MinPasswordLength)
 throw new ArgumentException(String.Format("Must have a password of at least {0} characters!", MinPasswordLength),"password");

 if (secretMessage == null || secretMessage.Length == 0)
 throw new ArgumentException("Secret Message Required!","secretMessage");

 var generator = new Pkcs5S2ParametersGenerator();

//Use Random Salt to minimize pre-generated weak password attacks.
 var salt = new byte[SaltBitSize/8];
 Random.NextBytes(salt);

 generator.Init(
 PbeParametersGenerator.Pkcs5PasswordToBytes(password.ToCharArray()),
 salt,
 Iterations);

//Generate Key
 var key = (KeyParameter)generator.GenerateDerivedMacParameters(KeyBitSize);

//Create Full Non Secret Payload
 var payload = new byte[salt.Length + nonSecretPayload.Length];
 Array.Copy(nonSecretPayload, payload, nonSecretPayload.Length);
 Array.Copy(salt,0, payload,nonSecretPayload.Length, salt.Length);

 return SimpleEncrypt(secretMessage, key.GetKey(), payload);
 }

 public static byte[] SimpleDecryptWithPassword(byte[] encryptedMessage, string password, int nonSecretPayloadLength = 0)
 {
//User Error Checks
 if (string.IsNullOrWhiteSpace(password) || password.Length <MinPasswordLength)
 throw new ArgumentException(String.Format("Must have a password of at least {0} characters!", MinPasswordLength),"password");

 if (encryptedMessage == null || encryptedMessage.Length == 0)
 throw new ArgumentException("Encrypted Message Required!","encryptedMessage");

 var generator = new Pkcs5S2ParametersGenerator();

//Grab Salt from Payload
 var salt = new byte[SaltBitSize/8];
 Array.Copy(encryptedMessage, nonSecretPayloadLength, salt, 0, salt.Length);

 generator.Init(
 PbeParametersGenerator.Pkcs5PasswordToBytes(password.ToCharArray()),
 salt,
 Iterations);

//Generate Key
 var key = (KeyParameter)generator.GenerateDerivedMacParameters(KeyBitSize);

 return SimpleDecrypt(encryptedMessage, key.GetKey(), salt.Length + nonSecretPayloadLength);
 }
 }
}

下面是一个使用RSA的示例。 用你的RSA密钥替换 your_rsa_key 。


var provider = new System.Security.Cryptography.RSACryptoServiceProvider();
provider.ImportParameters(your_rsa_key);

var encryptedBytes = provider.Encrypt(
 System.Text.Encoding.UTF8.GetBytes("Hello World!"), true);

string decryptedTest = System.Text.Encoding.UTF8.GetString(
 provider.Decrypt(encryptedBytes, true));

有关详细信息,请访问 MSDN - RSACryptoServiceProvider

BouncyCastle 是一个用于. NET的很棒的加密库,它可以作为的双核软件包安装到你的项目中。 我更喜欢 System.Security.Cryptography 库中当前可用的内容。 它在可用算法方面提供了很多选项,并为这些算法提供了更多的模式。

这是一个例子的实现 TwoFish,这是由 Bruce Schneier ( 英雄给我们所有偏执的人) 。 它是一个对称算法,像 Rijndael ( 又名 AES ) 。 它是 Blowfish 标准和其他著名算法的三个决赛者之一,由 Bruce Schneier编写的另一个著名算法叫做。

bouncycastle的第一件事是创建一个加密类,这将使得在库中实现其他块密码变得更加容易。 下面的加密器类接受一个泛型参数,该参数在其中实现IBlockCipher并具有默认构造函数。

的更新:由于流行的需求,我决定实现一个随机的IV,并在这个类中包含一个 HMAC 。 尽管从风格的角度来看,这违背了单一职责的坚实原则,因为这个类的本质。 这个类现在需要两个通用参数,一个用于密码,一个用于摘要。 它使用RNGCryptoServiceProvider自动生成IV来提供好的RNG熵,并允许你使用BouncyCastle中的任何摘要算法生成 MAC 。


using System;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;

public sealed class Encryptor<TBlockCipher, TDigest>
 where TBlockCipher : IBlockCipher, new()
 where TDigest : IDigest, new()
{
 private Encoding encoding;

 private IBlockCipher blockCipher;

 private BufferedBlockCipher cipher;

 private HMac mac;

 private byte[] key;

 public Encryptor(Encoding encoding, byte[] key, byte[] macKey)
 {
 this.encoding = encoding;
 this.key = key;
 this.Init(key, macKey, new Pkcs7Padding());
 }

 public Encryptor(Encoding encoding, byte[] key, byte[] macKey, IBlockCipherPadding padding)
 {
 this.encoding = encoding;
 this.key = key;
 this.Init(key, macKey, padding);
 }

 private void Init(byte[] key, byte[] macKey, IBlockCipherPadding padding)
 {
 this.blockCipher = new CbcBlockCipher(new TBlockCipher());
 this.cipher = new PaddedBufferedBlockCipher(this.blockCipher, padding);
 this.mac = new HMac(new TDigest());
 this.mac.Init(new KeyParameter(macKey));
 }

 public string Encrypt(string plain)
 {
 return Convert.ToBase64String(EncryptBytes(plain));
 }

 public byte[] EncryptBytes(string plain)
 {
 byte[] input = this.encoding.GetBytes(plain);

 var iv = this.GenerateIV();

 var cipher = this.BouncyCastleCrypto(true, input, new ParametersWithIV(new KeyParameter(key), iv));
 byte[] message = CombineArrays(iv, cipher);

 this.mac.Reset();
 this.mac.BlockUpdate(message, 0, message.Length);
 byte[] digest = new byte[this.mac.GetUnderlyingDigest().GetDigestSize()];
 this.mac.DoFinal(digest, 0);

 var result = CombineArrays(digest, message);
 return result;
 }

 public byte[] DecryptBytes(byte[] bytes)
 {
//split the digest into component parts
 var digest = new byte[this.mac.GetUnderlyingDigest().GetDigestSize()];
 var message = new byte[bytes.Length - digest.Length];
 var iv = new byte[this.blockCipher.GetBlockSize()];
 var cipher = new byte[message.Length - iv.Length];

 Buffer.BlockCopy(bytes, 0, digest, 0, digest.Length);
 Buffer.BlockCopy(bytes, digest.Length, message, 0, message.Length);
 if (!IsValidHMac(digest, message))
 {
 throw new CryptoException();
 }

 Buffer.BlockCopy(message, 0, iv, 0, iv.Length);
 Buffer.BlockCopy(message, iv.Length, cipher, 0, cipher.Length);

 byte[] result = this.BouncyCastleCrypto(false, cipher, new ParametersWithIV(new KeyParameter(key), iv));
 return result;
 }

 public string Decrypt(byte[] bytes)
 {
 return this.encoding.GetString(DecryptBytes(bytes));
 }

 public string Decrypt(string cipher)
 {
 return this.Decrypt(Convert.FromBase64String(cipher));
 }

 private bool IsValidHMac(byte[] digest, byte[] message)
 {
 this.mac.Reset();
 this.mac.BlockUpdate(message, 0, message.Length);
 byte[] computed = new byte[this.mac.GetUnderlyingDigest().GetDigestSize()];
 this.mac.DoFinal(computed, 0);

 return AreEqual(digest,computed);
 }

 private static bool AreEqual(byte [] digest, byte[] computed)
 {
 if(digest.Length!= computed.Length)
 {
 return false;
 }

 int result = 0;
 for (int i = 0; i <digest.Length; i++)
 {
 result |= digest[i] ^ computed[i];
 }

 return result == 0;
 }

 private byte[] BouncyCastleCrypto(bool forEncrypt, byte[] input, ICipherParameters parameters)
 {
 try
 {
 cipher.Init(forEncrypt, parameters);

 return this.cipher.DoFinal(input);
 }
 catch (CryptoException)
 {
 throw;
 }
 }

 private byte[] GenerateIV()
 {
 using (var provider = new RNGCryptoServiceProvider())
 {
//1st block
 byte[] result = new byte[this.blockCipher.GetBlockSize()];
 provider.GetBytes(result);

 return result;
 }
 }

 private static byte[] CombineArrays(byte[] source1, byte[] source2)
 {
 byte[] result = new byte[source1.Length + source2.Length];
 Buffer.BlockCopy(source1, 0, result, 0, source1.Length);
 Buffer.BlockCopy(source2, 0, result, source1.Length, source2.Length);

 return result;
 }
}

接下来,在新类上调用加密和解密方法,下面是使用twofish的示例:


var encrypt = new Encryptor<TwofishEngine, Sha1Digest>(Encoding.UTF8, key, hmacKey);

string cipher = encrypt.Encrypt("TEST"); 
string plainText = encrypt.Decrypt(cipher);

替换像TripleDES这样的块密码同样容易:


var des = new Encryptor<DesEdeEngine, Sha1Digest>(Encoding.UTF8, key, hmacKey);

string cipher = des.Encrypt("TEST");
string plainText = des.Decrypt(cipher);

最后,如果你想使用带有 SHA256 HMAC的AES,你可以执行以下操作:


var aes = new Encryptor<AesEngine, Sha256Digest>(Encoding.UTF8, key, hmacKey);

cipher = aes.Encrypt("TEST");
plainText = aes.Decrypt(cipher);

加密最难的部分是处理密钥而不是算法。 你必须考虑存储钥匙的位置,如果必须,如何交换。 这些算法都经受了时间的考验,而且很难破解。 有人想偷信息从你不会永远做密码分析在你的消息,他们将试图找出或你的钥匙在哪里。 所以 #1 明智地选择你的钥匙, #2 存储在一个安全的地方,如果你使用一个 Web.Config 然后iis可以加密部分 web.config, 最后如果你有交换钥匙确保协议交换的关键是安全的。

更新 2 更改了比较方法以减少计时攻击。 在这里查看更多信息 http://codahale.com/a-lesson-in-timing-attacks/ 。 也更新为默认为PKCS7填充并添加了新的构造函数,以允许最终用户选择要使用的填充。 感谢 @CodesInChaos的建议。

如果你正在使用 ASP.NET,现在可以在. NET 4.0中使用内置的功能。

System.Web.Security.MachineKey

.Net 4.5有 MachineKey.Protect()MachineKey.Unprotect()

.Net 4.0有 MachineKey.Encode()MachineKey.Decode() 。 你应该将MachineKeyProtection设置为'全部'。

除了 ASP.NET 之外,这个类似乎在每个应用程序重新启动时生成一个新的密钥,所以不工作。 快速peek在ILSpy在我看来它生成自己的默认值,如果适当的app.settings 失踪。 所以你实际上可以在 ASP.Net. 之外设置它

我一直未能找到一个 non-ASP.Net 等效外 System.Web 名称空间。

这里是一个简单的例子在 C# 使用aes加密字符串cbc模式随机iv和hmacpassword-derived键,显示基本的移动部件:


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

如果你在这里寻找PGP加密,在以下关于如何通过BouncyCastle使用PGP加密的示例中,PGPEncryptDecrypt 类似乎可以正常工作:

http://blogs.microsoft.co.il/kim/2009/01/23/pgp-zip-encrypted-files-with-c/#comment-611002

在这里粘贴太长,稍微修改: https://gist.github.com/zaus/c0ea1fd8dad5d9590af1

这是Brett放在这里的班级。 但是我犯了一个小编辑,因为我使用它时接收错误'Base-64字符数组长度无效'url字符串加密和解密。


public class CryptoURL
{
 private static byte[] _salt = Encoding.ASCII.GetBytes("Catto_Salt_Enter_Any_Value99");

///<summary>
///Encrypt the given string using AES. The string can be decrypted using 
///DecryptStringAES(). The sharedSecret parameters must match. 
///The SharedSecret for the Password Reset that is used is in the next line
///string sharedSecret ="OneUpSharedSecret9";
///</summary>
///<param name="plainText">The text to encrypt.</param>
///<param name="sharedSecret">A password used to generate a key for encryption.</param>
 public static string EncryptString(string plainText, string sharedSecret)
 {
 if (string.IsNullOrEmpty(plainText))
 throw new ArgumentNullException("plainText");
 if (string.IsNullOrEmpty(sharedSecret))
 throw new ArgumentNullException("sharedSecret");

 string outStr = null;//Encrypted string to return
 RijndaelManaged aesAlg = null;//RijndaelManaged object used to encrypt the data.

 try
 {
//generate the key from the shared secret and the salt
 Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);

//Create a RijndaelManaged object
 aesAlg = new RijndaelManaged();
 aesAlg.Key = key.GetBytes(aesAlg.KeySize/8);

//Create a decryptor to perform the stream transform.
 ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

//Create the streams used for encryption.
 using (MemoryStream msEncrypt = new MemoryStream())
 {
//prepend the IV
 msEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int));
 msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length);
 using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
 {
 using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
 {
//Write all data to the stream.
 swEncrypt.Write(plainText);
 }
 }

 outStr = HttpServerUtility.UrlTokenEncode(msEncrypt.ToArray());
//outStr = Convert.ToBase64String(msEncrypt.ToArray());
//you may need to add a reference. right click reference in solution explorer =>"add Reference" =>. NET tab => select"System.Web"
 }
 }
 finally
 {
//Clear the RijndaelManaged object.
 if (aesAlg!= null)
 aesAlg.Clear();
 }

//Return the encrypted bytes from the memory stream.
 return outStr;
 }

///<summary>
///Decrypt the given string. Assumes the string was encrypted using 
///EncryptStringAES(), using an identical sharedSecret.
///</summary>
///<param name="cipherText">The text to decrypt.</param>
///<param name="sharedSecret">A password used to generate a key for decryption.</param>
 public static string DecryptString(string cipherText, string sharedSecret)
 {
 if (string.IsNullOrEmpty(cipherText))
 throw new ArgumentNullException("cipherText");
 if (string.IsNullOrEmpty(sharedSecret))
 throw new ArgumentNullException("sharedSecret");

//Declare the RijndaelManaged object
//used to decrypt the data.
 RijndaelManaged aesAlg = null;

//Declare the string used to hold
//the decrypted text.
 string plaintext = null;

 byte[] inputByteArray;

 try
 {
//generate the key from the shared secret and the salt
 Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);

//Create the streams used for decryption. 
//byte[] bytes = Convert.FromBase64String(cipherText);
 inputByteArray = HttpServerUtility.UrlTokenDecode(cipherText);

 using (MemoryStream msDecrypt = new MemoryStream(inputByteArray))
 {
//Create a RijndaelManaged object
//with the specified key and IV.
 aesAlg = new RijndaelManaged();
 aesAlg.Key = key.GetBytes(aesAlg.KeySize/8);
//Get the initialization vector from the encrypted stream
 aesAlg.IV = ReadByteArray(msDecrypt);
//Create a decrytor to perform the stream transform.
 ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
 using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
 {
 using (StreamReader srDecrypt = new StreamReader(csDecrypt))

//Read the decrypted bytes from the decrypting stream
//and place them in a string.
 plaintext = srDecrypt.ReadToEnd();
 }
 }
 }
 catch (System.Exception ex)
 {
 return"ERROR";
//throw ex;

 }
 finally
 {
//Clear the RijndaelManaged object.
 if (aesAlg!= null)
 aesAlg.Clear();
 }

 return plaintext;
 }

 static string ConvertStringArrayToString(string[] array)
 {
//
//Concatenate all the elements into a StringBuilder.
//
 StringBuilder builder = new StringBuilder();
 foreach (string value in array)
 {
 builder.Append(value);
 builder.Append('.');
 }
 return builder.ToString();
 }

 private static byte[] ReadByteArray(Stream s)
 {
 byte[] rawLength = new byte[sizeof(int)];
 if (s.Read(rawLength, 0, rawLength.Length)!= rawLength.Length)
 {
 throw new SystemException("Stream did not contain properly formatted byte array");
 }

 byte[] buffer = new byte[BitConverter.ToInt32(rawLength, 0)];
 if (s.Read(buffer, 0, buffer.Length)!= buffer.Length)
 {
 throw new SystemException("Did not read byte array properly");
 }

 return buffer;
 }

}

在我的答案列表中复制了类似的问题:简单双向加密 C#

基于多个答案和评论。

  • 加密文本前的随机初始化向量( @jbtule )
  • 使用 TransformFinalBlock() 而非 MemoryStream ( @RenniePet )
  • 没有pre-filled键可以避免任何人复制&粘贴灾难
  • 适当的处置和使用模式

代码:


///<summary>
///Simple encryption/decryption using a random initialization vector
///and prepending it to the crypto text.
///</summary>
///<remarks>Based on multiple answers in http://stackoverflow.com/questions/165808/simple-two-way-encryption-for-c-sharp </remarks>
public class SimpleAes : IDisposable
{
///<summary>
///Initialization vector length in bytes.
///</summary>
 private const int IvBytes = 16;

///<summary>
///Must be exactly 16, 24 or 32 characters long.
///</summary>
 private static readonly byte[] Key = Convert.FromBase64String("FILL ME WITH 16, 24 OR 32 CHARS");

 private readonly UTF8Encoding _encoder;
 private readonly ICryptoTransform _encryptor;
 private readonly RijndaelManaged _rijndael;

 public SimpleAes()
 {
 _rijndael = new RijndaelManaged {Key = Key};
 _rijndael.GenerateIV();
 _encryptor = _rijndael.CreateEncryptor();
 _encoder = new UTF8Encoding();
 }

 public string Decrypt(string encrypted)
 {
 return _encoder.GetString(Decrypt(Convert.FromBase64String(encrypted)));
 }

 public void Dispose()
 {
 _rijndael.Dispose();
 _encryptor.Dispose();
 }

 public string Encrypt(string unencrypted)
 {
 return Convert.ToBase64String(Encrypt(_encoder.GetBytes(unencrypted)));
 }

 private byte[] Decrypt(byte[] buffer)
 {
//IV is prepended to cryptotext
 byte[] iv = buffer.Take(IvBytes).ToArray();
 using (ICryptoTransform decryptor = _rijndael.CreateDecryptor(_rijndael.Key, iv))
 {
 return decryptor.TransformFinalBlock(buffer, IvBytes, buffer.Length - IvBytes);
 }
 }

 private byte[] Encrypt(byte[] buffer)
 {
//Prepend cryptotext with IV
 byte[] inputBuffer = _rijndael.IV.Concat(buffer).ToArray();
 return _encryptor.TransformFinalBlock(inputBuffer, IvBytes, buffer.Length);
 }
}

这里是由 ASP Fragment最初的简单 Fragment


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


 private string Encrypt(string clearText)
 {
 string EncryptionKey ="yourkey";
 byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
 using (Aes encryptor = Aes.Create())
 {
 Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
 encryptor.Key = pdb.GetBytes(32);
 encryptor.IV = pdb.GetBytes(16);
 using (MemoryStream ms = new MemoryStream())
 {
 using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
 {
 cs.Write(clearBytes, 0, clearBytes.Length);
 cs.Close();
 }
 clearText = Convert.ToBase64String(ms.ToArray());
 }
 }
 return clearText;
 }

 private string Decrypt(string cipherText)
 {
 string EncryptionKey ="yourkey";
 cipherText = cipherText.Replace("","+");
 byte[] cipherBytes = Convert.FromBase64String(cipherText);
 using (Aes encryptor = Aes.Create())
 {
 Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
 encryptor.Key = pdb.GetBytes(32);
 encryptor.IV = pdb.GetBytes(16);
 using (MemoryStream ms = new MemoryStream())
 {
 using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
 {
 cs.Write(cipherBytes, 0, cipherBytes.Length);
 cs.Close();
 }
 cipherText = Encoding.Unicode.GetString(ms.ToArray());
 }
 }
 return cipherText;
 }

...