A Simple Crypto-Safe For Strings In C#

Encrypting a text is not enough, its integrity must also be secured. The easiest way to do this is to add a checksum to the original before encryption (and remove it again after successful decryption).

If the checksum calculated after decryption does not match the decrypted one, the password is incorrect.

Very Simple ;-)

I wrote this small class "SimpleCrypt" (or call it "Crypto-Safe" ;-) ) for my own project, but I think it could be helpful for many others too.

Usage

  • The user password is set by the constructor
  • Encryption works with any string (length >= 0 ). The result is an AES  encrypted string in Base64 format, that is sealed with an MD5 hash (128 bit).
  • Decryption checks Base64 format and integrity of the hash.

Here is some Test data

Used Password is "PASSWORD":

Example

The string ABC  is encrypted to h6EHx1dEYy/cjNZJihvkgGslpwi0gTNGtM5lt0j2Jxc=

Have fun.

The encryption

/* The Input String (UTF8) is sealed with a MD5-128-Bit-Hash and then Crypted to a Base64 String */
public string EncryptToBase64(string originalText)
{
	var userBytes = Encoding.UTF8.GetBytes(originalText); // UTF8 saves Space
	var userHash = MD5.Create().ComputeHash(userBytes);
	SymmetricAlgorithm crypt = Aes.Create(); // (Default: AES-CCM (Counter with CBC-MAC))
	crypt.Key = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(Password)); // MD5: 128 Bit Hash
	crypt.IV = new byte[16]; // by Default. IV[] to 0.. is OK simple crypt
	using var memoryStream = new MemoryStream();
	using var cryptoStream = new CryptoStream(memoryStream, crypt.CreateEncryptor(), CryptoStreamMode.Write);
	cryptoStream.Write(userBytes, 0, userBytes.Length); // User Data
	cryptoStream.Write(userHash, 0, userHash.Length); // Add HASH
	cryptoStream.FlushFinalBlock();
	var resultString = Convert.ToBase64String(memoryStream.ToArray());
	return resultString;
}

Decryption

/* Try to get original (decrypted) String. Password (and Base64-format) must be correct */
public string DecryptFromBase64(string encryptedText)
{
	var encryptedBytes = Convert.FromBase64String(encryptedText);
	SymmetricAlgorithm crypt = Aes.Create();
	crypt.Key = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(Password));
	crypt.IV = new byte[16];
	using var memoryStream = new MemoryStream();
	using var cryptoStream = new CryptoStream(memoryStream, crypt.CreateDecryptor(), CryptoStreamMode.Write);
	cryptoStream.Write(encryptedBytes, 0, encryptedBytes.Length);
	cryptoStream.FlushFinalBlock();
	var allBytes = memoryStream.ToArray();
	var userLen = allBytes.Length - 16;
	if (userLen < 0) throw new Exception("Invalid Len");   // No Hash?
	var userHash = new byte[16];
	Array.Copy(allBytes, userLen, userHash, 0, 16); // Get the 2 Hashes
	var decryptHash = MD5.Create().ComputeHash(allBytes, 0, userLen);
	if (userHash.SequenceEqual(decryptHash) == false) throw new Exception("Invalid Hash"); 
	var resultString = Encoding.UTF8.GetString(allBytes,0, userLen);
	return resultString;
}

Output