Criptografar e descriptografar uma seqüência de caracteres em c #?

Como posso criptografar e descriptografar uma string em c #?

EDIT 2013-Oct : Embora eu tenha editado esta resposta ao longo do tempo para resolver as deficiências, por favor veja a resposta da jbtule para uma solução mais robusta e bem informada.

https://stackoverflow.com/a/10366194/188474

Resposta Original:

Aqui está um exemplo de trabalho derivado da documentação “Classe RijndaelManaged” e o Kit de Treinamento MCTS .

EDITAR 2012-abril : Esta resposta foi editada para pré-pendurar a sugestão do IV por jbule e como ilustrado aqui:

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

Boa sorte!

 public class Crypto { //While an app specific salt is not the best practice for //password based encryption, it's probably safe enough as long as //it is truly uncommon. Also too much work to alter this answer otherwise. private static byte[] _salt = __To_Do__("Add a app specific salt here"); ///  /// Encrypt the given string using AES. The string can be decrypted using /// DecryptStringAES(). The sharedSecret parameters must match. ///  /// The text to encrypt. /// A password used to generate a key for encryption. 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; } ///  /// Decrypt the given string. Assumes the string was encrypted using /// EncryptStringAES(), using an identical sharedSecret. ///  /// The text to decrypt. /// A password used to generate a key for decryption. 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; } } 

Exemplos modernos de criptografia simétrica autenticada de uma string.

A prática recomendada geral para criptografia simétrica é usar Criptografia Autenticada com Dados Associados (AEAD), no entanto, isso não faz parte das bibliotecas de criptografia padrão .net. Portanto, o primeiro exemplo usa o AES256 e, em seguida, o HMAC256 , uma etapa Criptografa, em seguida , o MAC , que requer mais sobrecarga e mais chaves.

O segundo exemplo usa a prática mais simples do AES256- GCM usando o Bouncy Castle de fonte aberta (via nuget).

Ambos os exemplos têm uma function principal que recebe uma cadeia de mensagens secretas, chave (s) e uma carga útil não secreta opcional e retorna uma cadeia criptografada autenticada opcionalmente anexada aos dados não secretos. O ideal seria usá-los com chaves de 256 bits geradas aleatoriamente, ver NewKey() .

Os dois exemplos também possuem methods auxiliares que usam uma senha de cadeia para gerar as chaves. Esses methods auxiliares são fornecidos como uma conveniência para combinar com outros exemplos, no entanto, eles são muito menos seguros porque a força da senha será muito mais fraca do que uma chave de 256 bits .

Update: Adicionado byte[] sobrecarrega, e apenas o Gist tem a formatação completa com 4 espaços de recuo e documentação da API devido aos limites de resposta do StackOverflow.


Criptografia Interna do .NET (AES) -Então-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; ///  /// Helper that generates a random key on each call. ///  ///  public static byte[] NewKey() { var key = new byte[KeyBitSize / 8]; Random.GetBytes(key); return key; } ///  /// Simple Encryption (AES) then Authentication (HMAC) for a UTF8 Message. ///  /// The secret message. /// The crypt key. /// The auth key. /// (Optional) Non-Secret Payload. ///  /// Encrypted Message ///  /// Secret Message Required!;secretMessage ///  /// Adds overhead of (Optional-Payload + BlockSize(16) + Message-Padded-To-Blocksize + HMac-Tag(32)) * 1.33 Base64 ///  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); } ///  /// Simple Authentication (HMAC) then Decryption (AES) for a secrets UTF8 Message. ///  /// The encrypted message. /// The crypt key. /// The auth key. /// Length of the non secret payload. ///  /// Decrypted Message ///  /// Encrypted Message Required!;encryptedMessage 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); } ///  /// Simple Encryption (AES) then Authentication (HMAC) of a UTF8 message /// using Keys derived from a Password (PBKDF2). ///  /// The secret message. /// The password. /// The non secret payload. ///  /// Encrypted Message ///  /// password ///  /// Significantly less secure than using random binary keys. /// Adds additional non secret payload for key generation parameters. ///  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); } ///  /// Simple Authentication (HMAC) and then Descryption (AES) of a UTF8 Message /// using keys derived from a password (PBKDF2). ///  /// The encrypted message. /// The password. /// Length of the non secret payload. ///  /// Decrypted Message ///  /// Encrypted Message Required!;encryptedMessage ///  /// Significantly less secure than using random binary keys. ///  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); } } } 

Castelo insuflável 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; ///  /// Helper that generates a random new key on each call. ///  ///  public static byte[] NewKey() { var key = new byte[KeyBitSize / 8]; Random.NextBytes(key); return key; } ///  /// Simple Encryption And Authentication (AES-GCM) of a UTF8 string. ///  /// The secret message. /// The key. /// Optional non-secret payload. ///  /// Encrypted Message ///  /// Secret Message Required!;secretMessage ///  /// Adds overhead of (Optional-Payload + BlockSize(16) + Message + HMac-Tag(16)) * 1.33 Base64 ///  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); } ///  /// Simple Decryption & Authentication (AES-GCM) of a UTF8 Message ///  /// The encrypted message. /// The key. /// Length of the optional non-secret payload. /// Decrypted Message 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); } ///  /// Simple Encryption And Authentication (AES-GCM) of a UTF8 String /// using key derived from a password (PBKDF2). ///  /// The secret message. /// The password. /// The non secret payload. ///  /// Encrypted Message ///  ///  /// Significantly less secure than using random binary keys. /// Adds additional non secret payload for key generation parameters. ///  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); } ///  /// Simple Decryption and Authentication (AES-GCM) of a UTF8 message /// using a key derived from a password (PBKDF2) ///  /// The encrypted message. /// The password. /// Length of the non secret payload. ///  /// Decrypted Message ///  /// Encrypted Message Required!;encryptedMessage ///  /// Significantly less secure than using random binary keys. ///  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); } } } 

Aqui está um exemplo usando o RSA.

Importante: Há um limite para o tamanho dos dados que você pode criptografar com a criptografia RSA, KeySize - MinimumPadding . por exemplo, 256 bytes (assumindo 2048 chaves de bits) – 42 bytes (preenchimento mínimo de OEAP) = 214 bytes (tamanho máximo de texto plano)

Substitua your_rsa_key pela sua chave RSA.

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

For more info, visit MSDN – RSACryptoServiceProvider

If you are using ASP.Net you can now use built in functionality in .Net 4.0 onwards.

System.Web.Security.MachineKey

.Net 4.5 has MachineKey.Protect() and MachineKey.Unprotect() .

.Net 4.0 has MachineKey.Encode() and MachineKey.Decode() . You should just set the MachineKeyProtection to ‘All’.

Outside of ASP.Net this class seems to generate a new key with every app restart so doesn’t work. With a quick peek in ILSpy it looks to me like it generates its own defaults if the appropriate app.settings are missing. So you may actually be able to set it up outside ASP.Net.

I haven’t been able to find a non-ASP.Net equivalent outside the System.Web namespace.

BouncyCastle is a great Crypto library for .NET, it’s available as a Nuget package for install into your projects. I like it a lot more than what’s currently available in the System.Security.Cryptography library. It gives you a lot more options in terms of available algorithms, and provides more modes for those algorithms.

This is an example of an implementation of TwoFish , which was written by Bruce Schneier (hero to all us paranoid people out there). It’s a symmetric algorithm like the Rijndael (aka AES). It was one of the three finalists for the AES standard and sibling to another famous algorithm written by Bruce Schneier called BlowFish.

First thing with bouncycastle is to create an encryptor class, this will make it easier to implement other block ciphers within the library. The following encryptor class takes in a generic argument T where T implements IBlockCipher and has a default constructor.

UPDATE: Due to popular demand I have decided to implement generating a random IV as well as include an HMAC into this class. Although from a style perspective this goes against the SOLID principle of single responsibility, because of the nature of what this class does I reniged. This class will now take two generic parameters, one for the cipher and one for the digest. It automatically generates the IV using RNGCryptoServiceProvider to provide good RNG entropy, and allows you to use whatever digest algorithm you want from BouncyCastle to generate the 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 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++) { // compute equality of all bytes before returning. // helps prevent timing attacks: // https://codahale.com/a-lesson-in-timing-attacks/ 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; } } 

Next just call the encrypt and decrypt methods on the new class, here's the example using twofish:

 var encrypt = new Encryptor(Encoding.UTF8, key, hmacKey); string cipher = encrypt.Encrypt("TEST"); string plainText = encrypt.Decrypt(cipher); 

It's just as easy to substitute another block cipher like TripleDES:

 var des = new Encryptor(Encoding.UTF8, key, hmacKey); string cipher = des.Encrypt("TEST"); string plainText = des.Decrypt(cipher); 

Finally if you want to use AES with SHA256 HMAC you can do the following:

 var aes = new Encryptor(Encoding.UTF8, key, hmacKey); cipher = aes.Encrypt("TEST"); plainText = aes.Decrypt(cipher); 

The hardest part about encryption actually deals with the keys and not the algorithms. You'll have to think about where you store your keys, and if you have to, how you exchange them. These algorithms have all withstood the test of time, and are extremely hard to break. Someone who wants to steal information from you isn't going to spend eternity doing cryptanalysis on your messages, they're going to try to figure out what or where your key is. So #1 choose your keys wisely, #2 store them in a safe place, if you use a web.config and IIS then you can encrypt parts of the the web.config , and finally if you have to exchange keys make sure that your protocol for exchanging the key is secure.

Update 2 Changed compare method to mitigate against timing attacks. See more info here http://codahale.com/a-lesson-in-timing-attacks/ . Also updated to default to PKCS7 padding and added new constructor to allow end user the ability to choose which padding they would like to use. Thanks @CodesInChaos for the suggestions.

Disclaimer: This solution should only be used for data at rest that is not exposed to the public (for example – a configuration file or DB). Only in this scenario, the quick-and-dirty solution can be considered better than @jbtule’s solution, due to lower maintanance.

Original post: I found jbtule ‘s answer a bit complicated for a quick and dirty secured AES string encryption and Brett ‘s answer had a bug with the Initialization Vector being a fixed value making it vulnerable to padding attacks, so I fixed Brett’s code and added a random IV that is added to the chipered string, creating a different encrypted value each and every encryption of the same value:

Encryption:

 public static string Encrypt(string clearText) { byte[] clearBytes = Encoding.Unicode.GetBytes(clearText); using (Aes encryptor = Aes.Create()) { byte[] IV = new byte[15]; rand.NextBytes(IV); Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, IV); 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(IV) + Convert.ToBase64String(ms.ToArray()); } } return clearText; } 

Decryption:

 public static string Decrypt(string cipherText) { byte[] IV = Convert.FromBase64String(cipherText.Substring(0, 20)); cipherText = cipherText.Substring(20).Replace(" ", "+"); byte[] cipherBytes = Convert.FromBase64String(cipherText); using (Aes encryptor = Aes.Create()) { Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, IV); 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; } 

Replace EncryptionKey with your key. In my implementation, the key is being saved in the configuration file (web.config\app.config) as you shouldn’t save it hard coded. The configuration file should be also encrypted so the key won’t be saved as clear text in it.

 protected static string _Key = ""; protected static string EncryptionKey { get { if (String.IsNullOrEmpty(_Key)) { _Key = ConfigurationManager.AppSettings["AESKey"].ToString(); } return _Key; } } 

Encryption

 public string EncryptString(string inputString) { MemoryStream memStream = null; try { byte[] key = { }; byte[] IV = { 12, 21, 43, 17, 57, 35, 67, 27 }; string encryptKey = "aXb2uy4z"; // MUST be 8 characters key = Encoding.UTF8.GetBytes(encryptKey); byte[] byteInput = Encoding.UTF8.GetBytes(inputString); DESCryptoServiceProvider provider = new DESCryptoServiceProvider(); memStream = new MemoryStream(); ICryptoTransform transform = provider.CreateEncryptor(key, IV); CryptoStream cryptoStream = new CryptoStream(memStream, transform, CryptoStreamMode.Write); cryptoStream.Write(byteInput, 0, byteInput.Length); cryptoStream.FlushFinalBlock(); } catch (Exception ex) { Response.Write(ex.Message); } return Convert.ToBase64String(memStream.ToArray()); } 

Decryption:

 public string DecryptString(string inputString) { MemoryStream memStream = null; try { byte[] key = { }; byte[] IV = { 12, 21, 43, 17, 57, 35, 67, 27 }; string encryptKey = "aXb2uy4z"; // MUST be 8 characters key = Encoding.UTF8.GetBytes(encryptKey); byte[] byteInput = new byte[inputString.Length]; byteInput = Convert.FromBase64String(inputString); DESCryptoServiceProvider provider = new DESCryptoServiceProvider(); memStream = new MemoryStream(); ICryptoTransform transform = provider.CreateDecryptor(key, IV); CryptoStream cryptoStream = new CryptoStream(memStream, transform, CryptoStreamMode.Write); cryptoStream.Write(byteInput, 0, byteInput.Length); cryptoStream.FlushFinalBlock(); } catch (Exception ex) { Response.Write(ex.Message); } Encoding encoding1 = Encoding.UTF8; return encoding1.GetString(memStream.ToArray()); } 

With the reference of Encrypt and Decrypt a String in c# , I found one of good solution :

 static readonly string PasswordHash = "P@@Sw0rd"; static readonly string SaltKey = "S@LT&KEY"; static readonly string VIKey = "@1B2c3D4e5F6g7H8"; 

For Encrypt

 public static string Encrypt(string plainText) { byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8); var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros }; var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey)); byte[] cipherTextBytes; using (var memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) { cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); cryptoStream.FlushFinalBlock(); cipherTextBytes = memoryStream.ToArray(); cryptoStream.Close(); } memoryStream.Close(); } return Convert.ToBase64String(cipherTextBytes); } 

For Decrypt

 public static string Decrypt(string encryptedText) { byte[] cipherTextBytes = Convert.FromBase64String(encryptedText); byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8); var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.None }; var decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey)); var memoryStream = new MemoryStream(cipherTextBytes); var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read); byte[] plainTextBytes = new byte[cipherTextBytes.Length]; int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); memoryStream.Close(); cryptoStream.Close(); return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount).TrimEnd("\0".ToCharArray()); } 

To support mattmanser answer . Here’s an example using MachineKey class to encrypt/decrypt URL safe values.

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

Here is a simple example of encrypting strings in C# using AES CBC mode with random IV and HMAC and password-derived keys, to show the basic moving parts:

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

If you got here looking for PGP encryption, in the following comment on an example of how to use PGP encryption via BouncyCastle, the PGPEncryptDecrypt class seems to work basically out of the box:

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

Too long to paste here, slightly modified: https://gist.github.com/zaus/c0ea1fd8dad5d9590af1

An alternative to BouncyCastle for AES-GCM encryption is libsodium-net . It wraps the libsodium C library. One nice advantage is that it uses the AES-NI extension in CPUs for very fast encryption. The down side is that it won’t work at all if the CPU doesn’t have the extension. There’s no software fall back.

This is the class that was placed here by Brett. However I made a slight edit since I was receiving the error ‘Invalid length for a Base-64 char array’ when using it for URL strings to encrypt and decrypt.

 public class CryptoURL { private static byte[] _salt = Encoding.ASCII.GetBytes("Catto_Salt_Enter_Any_Value99"); ///  /// 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"; ///  /// The text to encrypt. /// A password used to generate a key for encryption. 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; } ///  /// Decrypt the given string. Assumes the string was encrypted using /// EncryptStringAES(), using an identical sharedSecret. ///  /// The text to decrypt. /// A password used to generate a key for decryption. 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; } } 

Encryption is a very common matter in programming. I think it is better to install a package to do the task for you. Maybe a simple open source Nuget project like Simple Aes Encryption

The key is in the config file and therefore it is easy to change in the production environment, and I don’t see any drawbacks

    

Copied in my answer here from a similar question: Simple two-way encryption for C# .

Based on multiple answers and comments.

  • Random initialization vector prepended to crypto text (@jbtule)
  • Use TransformFinalBlock() instead of MemoryStream (@RenniePet)
  • No pre-filled keys to avoid anyone copy & pasting a disaster
  • Proper dispose and using patterns

Código:

 ///  /// Simple encryption/decryption using a random initialization vector /// and prepending it to the crypto text. ///  /// Based on multiple answers in https://stackoverflow.com/questions/165808/simple-two-way-encryption-for-c-sharp  public class SimpleAes : IDisposable { ///  /// Initialization vector length in bytes. ///  private const int IvBytes = 16; ///  /// Must be exactly 16, 24 or 32 characters long. ///  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); } } 

Here is simple Snippet originally by ASP Snippets

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

AES Algorithm:

 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; } } 
  using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; // This is for password validation using System.Security.Cryptography; using System.Configuration; // This is where the hash functions reside namespace BullyTracker.Common { public class HashEncryption { //public string GenerateHashvalue(string thisPassword) //{ // MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); // byte[] tmpSource; // byte[] tmpHash; // tmpSource = ASCIIEncoding.ASCII.GetBytes(thisPassword); // Turn password into byte array // tmpHash = md5.ComputeHash(tmpSource); // StringBuilder sOutput = new StringBuilder(tmpHash.Length); // for (int i = 0; i < tmpHash.Length; i++) // { // sOutput.Append(tmpHash[i].ToString("X2")); // X2 formats to hexadecimal // } // return sOutput.ToString(); //} //public Boolean VerifyHashPassword(string thisPassword, string thisHash) //{ // Boolean IsValid = false; // string tmpHash = GenerateHashvalue(thisPassword); // Call the routine on user input // if (tmpHash == thisHash) IsValid = true; // Compare to previously generated hash // return IsValid; //} public string GenerateHashvalue(string toEncrypt, bool useHashing) { byte[] keyArray; byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt); System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader(); // Get the key from config file string key = (string)settingsReader.GetValue("SecurityKey", typeof(String)); //System.Windows.Forms.MessageBox.Show(key); if (useHashing) { MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); hashmd5.Clear(); } else keyArray = UTF8Encoding.UTF8.GetBytes(key); TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); tdes.Key = keyArray; tdes.Mode = CipherMode.ECB; tdes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tdes.CreateEncryptor(); byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); tdes.Clear(); return Convert.ToBase64String(resultArray, 0, resultArray.Length); } ///  /// DeCrypt a string using dual encryption method. Return a DeCrypted clear string ///  /// encrypted string /// Did you use hashing to encrypt this data? pass true is yes ///  public string Decrypt(string cipherString, bool useHashing) { byte[] keyArray; byte[] toEncryptArray = Convert.FromBase64String(cipherString); System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader(); //Get your key from config file to open the lock! string key = (string)settingsReader.GetValue("SecurityKey", typeof(String)); if (useHashing) { MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); hashmd5.Clear(); } else keyArray = UTF8Encoding.UTF8.GetBytes(key); TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); tdes.Key = keyArray; tdes.Mode = CipherMode.ECB; tdes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tdes.CreateDecryptor(); byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); tdes.Clear(); return UTF8Encoding.UTF8.GetString(resultArray); } } } 

for simplicity i made for myself this function that i use for non crypto purposes : replace “yourpassphrase” with your password …

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Security.Cryptography; using System.IO; namespace My { public class strCrypto { // This constant string is used as a "salt" value for the PasswordDeriveBytes function calls. // This size of the IV (in bytes) must = (keysize / 8). Default keysize is 256, so the IV must be // 32 bytes long. Using a 16 character string here gives us 32 bytes when converted to a byte array. private const string initVector = "r5dm5fgm24mfhfku"; private const string passPhrase = "yourpassphrase"; // email password encryption password // This constant is used to determine the keysize of the encryption algorithm. private const int keysize = 256; public static string encryptString(string plainText) { //if the plaintext is empty or null string just return an empty string if (plainText == "" || plainText == null ) { return ""; } byte[] initVectorBytes = Encoding.UTF8.GetBytes(initVector); byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null); byte[] keyBytes = password.GetBytes(keysize / 8); RijndaelManaged symmetricKey = new RijndaelManaged(); symmetricKey.Mode = CipherMode.CBC; ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes); MemoryStream memoryStream = new MemoryStream(); CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write); cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); cryptoStream.FlushFinalBlock(); byte[] cipherTextBytes = memoryStream.ToArray(); memoryStream.Close(); cryptoStream.Close(); return Convert.ToBase64String(cipherTextBytes); } public static string decryptString(string cipherText) { //if the ciphertext is empty or null string just return an empty string if (cipherText == "" || cipherText == null ) { return ""; } byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector); byte[] cipherTextBytes = Convert.FromBase64String(cipherText); PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, null); byte[] keyBytes = password.GetBytes(keysize / 8); RijndaelManaged symmetricKey = new RijndaelManaged(); symmetricKey.Mode = CipherMode.CBC; ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes); MemoryStream memoryStream = new MemoryStream(cipherTextBytes); CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read); byte[] plainTextBytes = new byte[cipherTextBytes.Length]; int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); memoryStream.Close(); cryptoStream.Close(); return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount); } } 

}

A good algorithm to securely hash data is BCrypt :

Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.

There’s a nice .NET implementation of BCrypt that is available also as a NuGet package .

I want to give you my contribute, with my code for AES Rfc2898DeriveBytes ( here the documentation) algorhytm, written in C# (.NET framework 4) and fully working also for limited platforms, as .NET Compact Framework for Windows Phone 7.0+ (not all platforms support every criptographic method of the .NET framework!).

I hope this can help anyone!

 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; } } } } 
 using System; using System.Data; using System.Configuration; using System.Text; using System.Security.Cryptography; namespace Encription { class CryptorEngine { public static string Encrypt(string ToEncrypt, bool useHasing) { byte[] keyArray; byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(ToEncrypt); //System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader(); string Key = "Bhagwati"; if (useHasing) { MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(Key)); hashmd5.Clear(); } else { keyArray = UTF8Encoding.UTF8.GetBytes(Key); } TripleDESCryptoServiceProvider tDes = new TripleDESCryptoServiceProvider(); tDes.Key = keyArray; tDes.Mode = CipherMode.ECB; tDes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tDes.CreateEncryptor(); byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); tDes.Clear(); return Convert.ToBase64String(resultArray, 0, resultArray.Length); } public static string Decrypt(string cypherString, bool useHasing) { byte[] keyArray; byte[] toDecryptArray = Convert.FromBase64String(cypherString); //byte[] toEncryptArray = Convert.FromBase64String(cypherString); //System.Configuration.AppSettingsReader settingReader = new AppSettingsReader(); string key = "Bhagwati"; if (useHasing) { MD5CryptoServiceProvider hashmd = new MD5CryptoServiceProvider(); keyArray = hashmd.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); hashmd.Clear(); } else { keyArray = UTF8Encoding.UTF8.GetBytes(key); } TripleDESCryptoServiceProvider tDes = new TripleDESCryptoServiceProvider(); tDes.Key = keyArray; tDes.Mode = CipherMode.ECB; tDes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tDes.CreateDecryptor(); try { byte[] resultArray = cTransform.TransformFinalBlock(toDecryptArray, 0, toDecryptArray.Length); tDes.Clear(); return UTF8Encoding.UTF8.GetString(resultArray,0,resultArray.Length); } catch (Exception ex) { throw ex; } } } } 

You have to use the namespace using System.Security.Cryptography; and useHashing is a bool type either true or false. String variable “key” should be same for Encryption and for Decryption

 //Encryption public string EncryptText(string toEncrypt, bool useHashing) { try { byte[] keyArray; byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt); string key = "String Key Value"; //Based on this key stirng is encrypting //System.Windows.Forms.MessageBox.Show(key); //If hashing use get hashcode regards to your key if (useHashing) { MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); //Always release the resources and flush data //of the Cryptographic service provide. Best Practice hashmd5.Clear(); } else keyArray = UTF8Encoding.UTF8.GetBytes(key); TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); //set the secret key for the tripleDES algorithm tdes.Key = keyArray; //mode of operation. there are other 4 modes. We choose ECB(Electronic code Book) tdes.Mode = CipherMode.ECB; //padding mode(if any extra byte added) tdes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tdes.CreateEncryptor(); //transform the specified region of bytes array to resultArray byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); //Release resources held by TripleDes Encryptor tdes.Clear(); //Return the encrypted data into unreadable string format return Convert.ToBase64String(resultArray, 0, resultArray.Length); } catch (Exception e) { throw e; } } //Decryption public string DecryptText(string cipherString, bool useHashing) { try { byte[] keyArray; //get the byte code of the string byte[] toEncryptArray = Convert.FromBase64String(cipherString); string key = "String Key Value"; //Based on this key string is decrypted if (useHashing) { //if hashing was used get the hash code with regards to your key MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); //release any resource held by the MD5CryptoServiceProvider hashmd5.Clear(); } else { //if hashing was not implemented get the byte code of the key keyArray = UTF8Encoding.UTF8.GetBytes(key); } TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); //set the secret key for the tripleDES algorithm tdes.Key = keyArray; //mode of operation. there are other 4 modes. //We choose ECB(Electronic code Book) tdes.Mode = CipherMode.ECB; //padding mode(if any extra byte added) tdes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tdes.CreateDecryptor(); byte[] resultArray = cTransform.TransformFinalBlock (toEncryptArray, 0, toEncryptArray.Length); //Release resources held by TripleDes Encryptor tdes.Clear(); //return the Clear decrypted TEXT return UTF8Encoding.UTF8.GetString(resultArray); } catch (Exception ex) { throw ex; } }