More organizations today understand that sensitive information should be stored encrypted in their repositories (Examples: user passwords, credit cards, SSN etc). Also there are regulations and security standards such as the PCI:DSS which requires the encryption of credit card numbers.
Thus, developers in such organizations encounter the issues of encryption frequently and are required to find appropriate solutions.
There are a lot of ways to encrypt/decrypt information by using buld-in .NET libraries for encryption.
I decided to present you here the shortest way that i found for doing that.
The following code is an example of the short way to encrypt/decrypt data using AES algorithm.
Please notice that in this example i stored the encryption key in the code, but of course in the real life the key should be stored in a secure repository with appropriate ACL privileges.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;
namespace aes3
{
class aes3
{
static void Main(string[] args)
{
RijndaelManaged AesEncryption = new RijndaelManaged();
string plainStr = "AES me"; // The text that would be encrypted
AesEncryption.KeySize = 256; // 192, 256
AesEncryption.BlockSize = 128;
AesEncryption.Mode = CipherMode.CBC;
AesEncryption.Padding = PaddingMode.PKCS7;
// The key should be generated prior and also should be stored in secure repository
// with appropriate ACL priviledges.
string keyStr = "cGFzc3dvcmQAAAAAAAAAAA==";
string ivStr = "cGFzc3dvcmQAAAAAAAAAAA==";
byte[] ivArr = Convert.FromBase64String(keyStr);
byte[] keyArr = Convert.FromBase64String(ivStr);
AesEncryption.IV = ivArr;
AesEncryption.Key = keyArr;
// This array will contain the plain text in bytes
byte[] plainText = ASCIIEncoding.UTF8.GetBytes(plainStr);
// Creates Symmetric encryption and decryption objects
ICryptoTransform crypto = AesEncryption.CreateEncryptor();
ICryptoTransform decrypto = AesEncryption.CreateDecryptor();
// The result of the encrypion and decryption
byte[] cipherText = crypto.TransformFinalBlock(plainText, 0, plainText.Length);
byte[] decryptedText = decrypto.TransformFinalBlock(cipherText,0,cipherText.Length);
Console.Write("The plain text\"{0}\" in the encrypted format is:{1} \n",plainStr,Convert.ToBase64String(cipherText));
Console.Write("The encrypted text \"{0}\" is decrypted to: {1}",Convert.ToBase64String(cipherText), ASCIIEncoding.UTF8.GetString(decryptedText));
Console.Read();
}
}
}
very useful, thank you !
ReplyDeleteThx...
ReplyDeleteYossi, thanks for posting but I should let you know this isn't production-ready. I like that you use the TransformFinalBlock method to write the transformed data - other examples online add unnecessary MemoryStreams and/or Cryptostreams, but you need to use a password-based key derivation function to create the hash and salt (PBKDF) for your RijndaelManaged/AesManaged instance. For example:
ReplyDelete```
// ...
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, 32, 10000); //use some sufficiently long and random password stored elsewhere
AesEncryption.Key = key.GetBytes(32);
AesEncryption.IV = key.GetBytes(16);
//...
```
More on this subject here - https://www.owasp.org/index.php/Using_Rfc2898DeriveBytes_for_PBKDF2.
Then store the unique salt somewhere with the encrypted data for decrypting later. Many times this is a Salt column in the same data row as the encrypted data.
Here is a repository with good code for reference and usage, with the best cryptographic practices -> https://github.com/alecgn/crypthash-net
ReplyDelete