Summary
The United States Federal Information Processing Standard (FIPS) defines encryption policies that all U.S. Government computer systems must use. Since Microsoft chooses not to document which encryption routines are FIPS-compliant, and which are not, I had to rely on trial-and-error to come up with a completely FIPS-compliant encryption algorithm.
Source Code
Utilities.cs
using System;
using System.IO;
using System.Text;
using System.Security.Permissions;
using System.Security.Cryptography;
namespace KXM.Fx.Encryption
{
/// <summary>
/// FIPS-Compliant encryption utilities.
/// </summary>
public class Utilities
{
protected static string Encrypt(string strPlainText, string strKey)
{
KeyIV3Des kiv = new KeyIV3Des(strKey);
TripleDESCryptoServiceProvider des3 = new TripleDESCryptoServiceProvider();
ICryptoTransform des3Enc = des3.CreateEncryptor(kiv.Key, kiv.IV);
return Encrypt(strPlainText, des3Enc);
} //END: EncryptStringDes3(string, string)
protected static string Decrypt(string strEncryptedText, string strKey)
{
ICryptoTransform dec3Des;
KeyIV3Des kiv = new KeyIV3Des(strKey);
TripleDESCryptoServiceProvider des3 = null;
string strReturn = "";
try
{
des3 = new TripleDESCryptoServiceProvider();
dec3Des = des3.CreateDecryptor(kiv.Key, kiv.IV);
strReturn = Utilities.Decrypt(strEncryptedText, dec3Des);
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (des3 != null)
des3.Clear();
if (kiv != null)
kiv.Clear();
}
return strReturn;
} //END: DectryptStringDes3(string, string)
/// <summary>
/// Encrypts a string using the ICryptoTransform provided.
/// </summary>
/// <param name="strPlainText">The string to encrypt.</param>
/// <param name="trans">The ICryptoTransform that will perform the encryption.</param>
/// <returns>An encrypted string</returns>
public static string Encrypt(string strPlainText, ICryptoTransform trans)
{
// Convert the string to its unicode bytes
byte[] buf = UnicodeEncoding.Unicode.GetBytes(strPlainText);
// Create a memory stream
MemoryStream memStream = new MemoryStream();
// Create a CryptoStream to encrypt the data and write it to the memory stream.
CryptoStream cryptStream = new CryptoStream(memStream, trans, CryptoStreamMode.Write);
// Write the data to the memory stream, encrypting it in the process
cryptStream.Write(buf, 0, buf.Length);
cryptStream.FlushFinalBlock();
// Save the data in the memorystream into a string to be returned.
string strRet = Convert.ToBase64String(memStream.GetBuffer(), 0, (int)memStream.Length);
// Close the streams
cryptStream.Close();
memStream.Close();
// Return the encrypted string.
return strRet;
} //END: EncryptAndBase64(string, ICryptoTransform)
/// <summary>
/// Decrypts a string using the ICryptoTransform provided.
/// </summary>
/// <param name="strEncryptedText">The encrypted string.</param>
/// <param name="trans">The ICryptoTransform that will perform the encryption.</param>
/// <returns>A plain-text (unencrypted) string.</returns>
public static string Decrypt(string strEncryptedText, ICryptoTransform trans)
{
// Convert the string to its bytes
byte[] buf = Convert.FromBase64String(strEncryptedText);
// Create a memory stream
MemoryStream memStream = new MemoryStream();
// Create a CryptoStream to decrypt the data and write it to the memory stream.
CryptoStream cryptStream = new CryptoStream(memStream, trans, CryptoStreamMode.Write);
// Write the data to the memory stream, decrypting it in the process
cryptStream.Write(buf, 0, buf.Length);
cryptStream.FlushFinalBlock();
// Save the data in the memorystream into a string to be returned.
string strRet = UnicodeEncoding.Unicode.GetString(memStream.GetBuffer(), 0, (int)memStream.Length);
// Close the streams
cryptStream.Close();
memStream.Close();
// Return the decrypted string.
return strRet;
} //END: DecryptFromBase64(string, ICryptoTransform)
} // END CLASS Utilities
} // END NAMESPACE KXM.Fx.Encryption
KeyIV3Des.cs
using System;
using System.Security.Cryptography;
namespace KXM.Fx.Encryption
{
/// <summary>
/// Represents a Key and Initialization Vector generated from a string.
/// </summary>
public class KeyIV3Des
{
#region Fields
private byte[] key3des;
private byte[] iv3des;
#endregion
#region Properties
/// <summary>
/// A byte array that can be used as a key in Triple DES encryption
/// </summary>
public byte[] Key
{
get { return key3des; }
}
/// <summary>
/// A byte array that can be used as an Initialization Vector in Triple DES encryption
/// </summary>
public byte[] IV
{
get { return iv3des; }
}
#endregion
/// <summary>
/// Creates a new instance of this class.
/// </summary>
/// <param name="txtKey">A String to use as a seed to generate the Key and IV.</param>
public KeyIV3Des(string strKey)
{
byte[] salt = System.Text.UTF8Encoding.UTF8.GetBytes(strKey);
SHA1CryptoServiceProvider hash = new SHA1CryptoServiceProvider();
for (int i = 0; i < 200; ++i)
{
salt = hash.ComputeHash(salt, 0, salt.Length);
hash.Initialize();
}
PasswordDeriveBytes pdb = new PasswordDeriveBytes(strKey, salt, "SHA1", 1000);
Array.Clear(salt, 0, salt.Length);
hash.Clear();
key3des = pdb.GetBytes(24);
iv3des = pdb.GetBytes(8);
} //END: KeyIV3Des(string)
/// <summary>
/// Clears the key values.
/// </summary>
public void Clear()
{
Array.Clear(key3des, 0, key3des.Length);
Array.Clear(iv3des, 0, iv3des.Length);
} //END: Clear()
} // END CLASS KeyIV3Des
} // END NAMESPACE KXM.Fx.Encryption
See Also
Microsoft KB Article 811833