Return to
HomePage
Encrypt a file via a block cipher using 3DES (C#)
Applies to
* .NET Framework 2.0
* C#
Summary
The purpose of this code is to demonstrate the proper use of a symmetric block cipher. This code sample demonstrates the use of Triple DES, which should primarily be used for backwards compatibility with other applications and replaced with AES in newer implementations of code.
Objectives
* To provide confidentiality of files which are transmitted over insecure or untrusted communication channels.
* To provide confidentiality of files in storage until they are needed by a user or application
* To provide backwards compatibility with other applications which only provide encryption using 3DES
Scenarios
* Application developer desires confidentiality for files in storage or in transit.
* 3DES should only be used in implementations which require backwards compatibility for interaction with applications that do not implement the new NIST encryption standard, AES.
Solution Example
private static void [EncryptFile(string] [sInputFilename,] string [sOutputFilename,] string sKey, string sIV)
{
// The default 3DES key size under the .NET framework is 192 (168). The following
// call will create a 3DES crypto provider and create a random initialization
// vector and key. The crypto mode defaults to CBC ensuring the proper chaining
// of data to mitigate repetition of cipher text blocks.
[TripleDESCryptoServiceProvider] tdes = [(TripleDESCryptoServiceProvider)] [TripleDESCryptoServiceProvider.Create();]
// One could override the default randomly generated key and initialization vector
// by setting the following properties to the Rijndael Crypto Provider, e.g.:
//
// tdes.Key = some_key_val;
// tdes.IV = some_iv_val;
// [tdes.KeySize] = 192;
//
// Similarly a developer may wish to change the default encryption mode, e.g.:
//
// tdes.Mode = [CipherMode.CFB;] // Defaults to CBC mode. Use of ECB mode is not recommended
// as it provides no feedback chaining of ciphertext
//Set secret key For 3DES algorithm.
tdes.Key = [ASCIIEncoding.ASCII.GetBytes(sKey);]
//Set initialization vector.
tdes.IV = [ASCIIEncoding.ASCII.GetBytes(sIV);]
[FileStream] fsPlaintext = new [FileStream(sInputFilename,] [FileMode.Open,] [FileAccess.Read);]
[FileStream] fsCiphertext = new [FileStream(sOutputFilename,] [FileMode.Create,] [FileAccess.Write);]
//Create an 3DES encryptor from the TripleDES instance.
[ICryptoTransform] tdesencrypt = [tdes.CreateEncryptor();]
//Create crypto stream set to read and do an 3DES encryption transform on incoming bytes.
[CryptoStream] cipherstream = new [CryptoStream(fsCiphertext,] tdesencrypt, [CryptoStreamMode.Write);]
byte[] bytearrayinput = new byte[fsPlaintext.Length];
fsPlaintext.Read(bytearrayinput, 0, bytearrayinput.Length);
cipherstream.Write(bytearrayinput, 0, bytearrayinput.Length);
cipherstream.Close();
fsPlaintext.Close();
fsCiphertext.Close();
}
Problem Example
The following example demonstrates an implementation of a Encryption routine containing several common secure coding issues.
private static void [ProblematicFileEncrypt(string] [sInputFilename,] string [sOutputFilename)]
{
[TripleDESCryptoServiceProvider] tdes = [(TripleDESCryptoServiceProvider)TripleDESCryptoServiceProvider.Create();]
//Set secret key For 3DES algorithm.
tdes.Key = ASCIIEncoding.ASCII.GetBytes("ASAMPLEKEYWEUSETOENCRYPT");
//We don't use an IV because the book doesn't show us an example using a
//more secure, chained mode!
// tdes.IV = ASCIIEncoding.ASCII.GetBytes("SAMPLEIV");
//Set encryption mode to an unchained value (because the book says so!)
tdes.Mode = [CipherMode.ECB;]
//Create a file stream to read the plaintext contents in.
[FileStream] fsPlaintext = new [FileStream(sInputFilename,] [FileMode.Open,] [FileAccess.Read);]
[FileStream] fsCiphertext = new [FileStream(sOutputFilename,] [FileMode.Create,] [FileAccess.Write);]
//Create an 3DES encryptor
[ICryptoTransform] tdesencrypt = [tdes.CreateEncryptor();]
//Create crypto stream set to read and do an 3DES encryption transform on incoming bytes.
[CryptoStream] cipherstream = new [CryptoStream(fsCiphertext,] tdesencrypt, [CryptoStreamMode.Write);]
//Write the contents of the encrypted file.
byte[] bytearrayinput = new byte[fsPlaintext.Length];
fsPlaintext.Read(bytearrayinput, 0, bytearrayinput.Length);
cipherstream.Write(bytearrayinput, 0, bytearrayinput.Length);
cipherstream.Close();
fsPlaintext.Close();
fsCiphertext.Close();
}
* Cleartext encryption key can be extracted by any user with access to the source code or compiled code
* Use of a weak encryption key, which can be brute-forced using a dictionary attack
* Insecure cipher mode (ECB), performs encryption of each block 64 bits independently with no feedback into subsequent blocks as CBC and other chained modes do. An attacker can rearrange or replace blocks with previous blocks they observe.
* ECB mode does not utilize an initialization vector, yielding the same encrypted value for each plaintext value. An attacker can thus observe patterns in the encrypted blocks and perform known plaintext attacks (Note: Initialization vectors need not remain secret however they should be random for each encrypted value of the plaintext)
Test Case
The following classes must be included in any project making use of the sample code provided above:
using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;
The following test case demonstrates the use of the
EncryptFile function
static void Main(string[] args)
{
Console.Out.WriteLine("Encrypting: " + args[0] + " to file: " + args[1]);
EncryptFile(args[0], args[1], sKey, sIV);
Console.Out.WriteLine("Decrypting: " + args[1] + " to file: " + args[0] + ".new");
DecryptFile(args[1], args[0] + ".new", sKey, sIV);
}
* sKey and sIV are retrieved from the
DataProtection API within Application code
Expected Result
Comparing the Decrypted file value with the original file text should yield the same text.
More Information
* The test case assumes use of the
DataProtection API implemented within the user code to securely store and retrieve encryption keys.
Additional Resources
* Protecting keys using the DPAPI: http://msdn.microsoft.com/library/en-us/dnpag2/html/paght000005.asp
* Cryptography (.NET): http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGGuidelines0003.asp?frame=true#pagguidelines0003_cryptography
Attributes
*
Applies To: .NET Framework 2.0, C#
*
Category: Cryptography
*
Author: George Gal
Return to
HomePage