I have simple symmetric encrypt/decrypt application that works fine:
namespace Crypto
{
class Program
{
public static void EncryptSomeText()
{
string original ="My secretdata!";
using (SymmetricAlgorithm symmetricAlgorithm =
new AesManaged())
{
byte[] encrypted = Encrypt(symmetricAlgorithm, original);
string roundtrip = Decrypt(symmetricAlgorithm, encrypted);
// Displays: My secret data!
Console.WriteLine("Original:{ 0}", original);
Console.WriteLine("RoundTrip:{ 0}", roundtrip);
}
}
static byte[] Encrypt(SymmetricAlgorithm aesAlg, string plainText)
{
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt =
new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
return msEncrypt.ToArray();
}
}
}
static string Decrypt(SymmetricAlgorithm aesAlg, byte[] cipherText)
{
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt =
new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
return srDecrypt.ReadToEnd();
}
}
}
}
static void Main(string[] args)
{
SymmetricAlgorithm sma = SymmetricAlgorithm.Create();
byte[] b = Encrypt(sma,"bla bla");
string s= Decrypt(sma, b);
Console.WriteLine("Decrypted {0}", s);
}
}
}
I'm just wondering regarding key creation. Does it means that it is created in automatic way during symmetric algorithm creation? Is it generated each time different? I suppose, user should pass key for this purpose.
SymmetricAlgorithm sma = SymmetricAlgorithm.Create();
Random key is generated when you access Key property of your SymmetricAlgorithm, assuming you did not set that Key before that to some predefined key. It's not generated during construction of SymmetricAlgorithm itself.
var sma = SymmetricAlgorithm.Create();
// no key generated here yet
var key = sma.Key; // generated key
// accessing `Key` causes random key generation
var sma = SymmetricAlgorithm.Create();
// no key here
sma.Key = myKey;
// you set the key, so no random key is generated
The same is true for IV (nonce) value.
Generating random key makes sense only once, then you have to share it between encrypting\decrypting party in some safe way and use it for future encryptions\decryptions. While you are there, note that IV value should be random for each encryption, so usually you just prepend that IV value to the encrypted binary array and before decrypting you cut that IV from the beginning of encrypted array and use for decryption.
On this github page there is utility class written in Java which performs encryption/decryption using symmetric algorithm, below could be one of encryption flows using symmetric algorithm :
generate secret key using the selected algorithm (DES, 3DES, AES etc)
generate secure random number of seed bytes which is computed with available the seed generation algorithm
probably text message to be encrypted is not the multiples of 8 byte blocks that's why message must be padded with additional bytes to make the text message to be multiples of 8-byte blocks.(e.g. PKCS5Padding padding scheme )
use random generated secure seed bytes as initialization vector as block cipher
initialize cipher function with the symmetric key and block cipher
finish encryption
apply binary to text encoding with selected standard for initialization vector(IV) and encrypted binary data
define message format before sending in order to split the message into IV and encrypted for decryption on recipient side
Related
I would like to encrypt data in iOS app with a SymetricKey and the CryptoKit and decrypt on server side with C# in Net Core.
iOS code:
class Security {
static let keyStr = "d5a423f64b607ea7c65b311d855dc48f" //32
static let iv="31348c0987c7" //12
class func encode(_ text:String)->String {
let key=SymmetricKey(data: Security.keyStr.data(using: .utf8)!)
let nonce=try! AES.GCM.Nonce(data: iv.data(using: .utf8)!)
let encrypted=try! AES.GCM.seal(text.data(using: .utf8)!, using: key, nonce: nonce)
return encrypted.combined!.base64EncodedString()
}
}
I pass the result of the encryption to my backend and I would like to decrypt
C# Code:
public string decrypt(string encryptedText)
{
string keyStr = "d5a423f64b607ea7c65b311d855dc48f";
string iv = "31348c0987c7";
string plaintext = "";
Debug.WriteLine(encryptedText);
using (Aes aesAlg = Aes.Create())
{
Debug.WriteLine(AesGcm.IsSupported);
var key = System.Text.Encoding.UTF8.GetBytes(keyStr);
var iV = System.Text.Encoding.UTF8.GetBytes(iv);
aesAlg.Key = key;
aesAlg.IV = iV;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(request.pswd)))
{
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();
}
}
}
}
Debug.WriteLine(plaintext);
}
So for example word: Test gets encrypted as: MzEzNDhjMDk4N2M3CI68IDEJeBR4OFtWO3GPO3TIgos=
When I get to line:
aesAlg.IV = iV;
I get an error "Specified initialization vector (IV) does not match the block size for this algorithm."
It seems as if C# needs byte[16], but in iOS I seem to be stuck with 12.
I got stuck at this point. Any idea greately appreciated.
Thank you.
The posted Swift code applies AES in GCM mode, s. AES.GCM. The posted C# code also uses AES, however not the GCM mode, but the default CBC mode (s. Aes, Mode).
The CBC mode applies a 16 bytes IV, while the GCM mode uses a 12 bytes nonce. That is what the error message is pointing to.
For successful decryption, AES in GCM mode must also be used on the C# side. In .NET AES in GCM mode is supported with the AesGcm class (as of .NET Core 3.0).
Note also that the data given by the Swift code is the Base64 encoding of the concatenation of 12 bytes nonce, ciphertext and 16 bytes tag (in that order), which must be separated in the C# code, where the portions are processed individually.
A possible C# implementation that decrypts the ciphertext generated by the posted Swift code is:
byte[] nonceCiphertextTag = Convert.FromBase64String("MzEzNDhjMDk4N2M3CI68IDEJeBR4OFtWO3GPO3TIgos=");
byte[] key = Encoding.UTF8.GetBytes("d5a423f64b607ea7c65b311d855dc48f");
Span<byte> nonceCiphertextTagSpan = nonceCiphertextTag.AsSpan();
Span<byte> nonce = nonceCiphertextTagSpan[..12];
Span<byte> ciphertext = nonceCiphertextTagSpan[12..^16];
Span<byte> tag = nonceCiphertextTagSpan[^16..];
byte[] plaintext = new byte[ciphertext.Length];
using AesGcm aesGcm = new AesGcm(key);
aesGcm.Decrypt(nonce, ciphertext, tag, plaintext); // throws an 'CryptographicException: The computed authentication tag did not match the input authentication tag' if authentication fails
Console.WriteLine(Encoding.UTF8.GetString(plaintext)); // Test
Edit: An alternative to the native .NET class AesGcm is C#/BouncyCastle. Maybe this is supported in your environment:
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
...
byte[] nonceCiphertextTag = Convert.FromBase64String("MzEzNDhjMDk4N2M3CI68IDEJeBR4OFtWO3GPO3TIgos=");
byte[] key = Encoding.UTF8.GetBytes("d5a423f64b607ea7c65b311d855dc48f");
Span<byte> nonceCiphertextTagSpan = nonceCiphertextTag.AsSpan();
byte[] nonce = nonceCiphertextTagSpan[..12].ToArray();
byte[] ciphertextTag = nonceCiphertextTagSpan[12..].ToArray();
GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());
AeadParameters aeadParameters = new AeadParameters(new KeyParameter(key), 128, nonce);
gcmBlockCipher.Init(false, aeadParameters);
byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(ciphertextTag.Length)];
int length = gcmBlockCipher.ProcessBytes(ciphertextTag, 0, ciphertextTag.Length, plaintext, 0);
gcmBlockCipher.DoFinal(plaintext, length); // throws an 'InvalidCipherTextException: mac check in GCM failed' if authentication fails
Console.WriteLine(Encoding.UTF8.GetString(plaintext)); // Test
Note that unlike the native AesGcm class, C#/BouncyCastle requires the concatenation of ciphertext and tag, so only the nonce needs to be separated.
I am searching for C# Code to reproduce the following openssl command.
openssl enc -d -aes-256-cbc -in my_encrypted_file.csv.enc -out my_decrypted_file.csv -pass file:key.bin
Additional information:
The encrypted file in present as byte[]
The key.bin is a byte[] with length of 256 (the key is obtained by a more simple decryption of yet another file, which i managed to realize in C#).
I have been trying out various examples found by searching the web.
The problem is, that all of these examples require an IV (initialization vector). Unfortunately, I don't have an IV and no one on the team knows what this is or how it could be defined.
The openssl command does not seem to need one, so I am a bit confused about this.
Currently, the code, I am trying with, looks as follows:
public static string DecryptAesCbc(byte[] cipheredData, byte[] key)
{
string decrypted;
System.Security.Cryptography.Aes aes = System.Security.Cryptography.Aes.Create();
aes.KeySize = 256;
aes.Key = key;
byte[] iv = new byte[aes.BlockSize / 8];
aes.IV = iv;
aes.Mode = CipherMode.CBC;
ICryptoTransform decipher = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream ms = new MemoryStream(cipheredData))
{
using (CryptoStream cs = new CryptoStream(ms, decipher, CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs))
{
decrypted = sr.ReadToEnd();
}
}
return decrypted;
}
}
The code fails saying that my byte[256] key has the wrong length for this kind of algorithm.
Thanks for any help with this!
Cheers, Mike
The posted OpenSSL statement uses the -pass file: option and thus a passphrase (which is read from a file), see openssl enc. This causes the encryption process to first generate a random 8 bytes salt and then, together with the passphrase, derive a 32 bytes key and 16 bytes IV using the (not very secure) proprietary OpenSSL function EVP_BytesToKey. This function uses several parameters, e.g. a digest and an iteration count. The default digest for key derivation is MD5 and the iteration count is 1. Note that OpenSSL version 1.1.0 and later uses SHA256 as default digest, i.e. depending on the OpenSSL version used to generate the ciphertext, the appropriate digest must be used for decryption. Preceding the ciphertext is a block whose first 8 bytes is the ASCII encoding of Salted__, followed by the 8 bytes salt.
Therefore, the decryption must first determine the salt. Based on the salt, together with the passphrase, key and IV must be derived and then the rest of the encrypted data can be decrypted. Thus, first of all an implementation of EVP_BytesToKey in C# is required, e.g. here. Then a possible implementation could be (using MD5 as digest):
public static string DecryptAesCbc(byte[] cipheredData, string passphrase)
{
string decrypted = null;
using (MemoryStream ms = new MemoryStream(cipheredData))
{
// Get salt
byte[] salt = new byte[8];
ms.Seek(8, SeekOrigin.Begin);
ms.Read(salt, 0, 8);
// Derive key and IV
OpenSslCompat.OpenSslCompatDeriveBytes db = new OpenSslCompat.OpenSslCompatDeriveBytes(passphrase, salt, "MD5", 1);
byte[] key = db.GetBytes(32);
byte[] iv = db.GetBytes(16);
using (Aes aes = Aes.Create())
{
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
aes.Key = key;
aes.IV = iv;
// Decrypt
ICryptoTransform decipher = aes.CreateDecryptor(aes.Key, aes.IV);
using (CryptoStream cs = new CryptoStream(ms, decipher, CryptoStreamMode.Read))
{
using (StreamReader sr = new StreamReader(cs, Encoding.UTF8))
{
decrypted = sr.ReadToEnd();
}
}
}
}
return decrypted;
}
Note that the 2nd parameter of DecryptAesCbc is the passphrase (as string) and not the key (as byte[]). Also note that StreamReader uses an encoding (UTF-8 by default), which requires compatible data (i.e. text data, but this should be met for csv files). Otherwise (i.e. for binary data as opposed to text data) StreamReader must not be used.
I'm writing a ClickOnce application that runs a batch file process with service account credentials. I need to store the service account credentials so that the program can add the username/password to the process.startinfo property before running the process. The users do not know this password, so there's no prompt for them to enter in a password. I believe this means I cannot store the hash and verify the password that way, the hash value I generate must be reversible so that it can add the correct password to the startinfo property. I searched around this site and came up with a Frankenstein-type solution that works, but it's not very secure. Currently, I used this method to encrypt the password, stored the encrypted value, then use the decrypt method to obtain the password during runtime (the encrypt method is never ran during runtime, I ran it in Visual Studio during debug, copied the value, then used that value in the decrypt method below this):
// used to generate decrypted acct creds
private void EncryptText(string plaintext)
{
string outsrt = null;
RijndaelManaged aesAlg = null;
try
{
// generate key from secret and salt
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedsecret, _salt);
aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream mEncrypt = new MemoryStream())
{
// prepend the IV
mEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int));
mEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length);
using (CryptoStream csEncrypt = new CryptoStream(mEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
// write all data to the stream
swEncrypt.Write(plaintext);
}
}
outsrt = Convert.ToBase64String(mEncrypt.ToArray());
}
}
finally
{
if (aesAlg != null)
aesAlg.Clear();
}
Console.WriteLine(outsrt);
}
Here's the decrypt method:
private string GetServiceAcctPW()
{
// 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("EncryptedValueHere");
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();
}
}
}
catch(Exception e)
{
Console.WriteLine("Error decrypting password");
Console.WriteLine(e.StackTrace);
logger.WriteToLog(Logger.LogCodes.ERROR, "Error decrypting service account password");
MessageBox.Show("An error occurred while trying to start the installation process\nPlease contact the Service Desk for further assistance");
}
finally
{
// Clear the RijndaelManaged object.
if (aesAlg != null)
aesAlg.Clear();
}
return plaintext;
}
This code works just fine, however, I know it's not secure. My code review guy said he was able to crack it with dotPeek in an hour because it's only adding a layer of obfuscation. What would be the best/proper way to store these credentials within the application?
The encryption key is on a dedicated server.
The password is sent to the server along with an id to be encrypted and the encrypted password returned for DB storage.
When the the password is needed a request is made to the dedicated server with the id and a decrypted password is returned.
The password is never saved to disk and the key is never available off the dedicated server.
The dedicated server is kind-of-like a poor-mans HSM.
This is encryption, not hashing. The encryption key is secret along with a random IV that that is saved with the id on the dedicated server. The key is not available and not related to the password so there is no better attack than brute force against the encryption key which is essentially to large to be attacked by brute force.
The server needs to be very secure, only a couple of two factor logins and not available to the Internet.
Why does this code return the weak key error?
static public byte[] TDESDecrypt(byte[] toDecrypt, byte[] key, CipherMode mode = CipherMode.ECB, PaddingMode padding = PaddingMode.None)
{
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = key;
tdes.Mode = mode;
tdes.Padding = padding;
ICryptoTransform cTransform = tdes.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toDecrypt, 0, toDecrypt.Length);
tdes.Clear();
return resultArray;
}
When I try to execute the line "tdes.Key = key", I get the error
deriveSessionKeyIS System.Security.Cryptography.CryptographicException:
Specified key is a known weak key for TripleDES and cannot be used
Why? The key I'm trying is random, but one of the tested keys, for example, is FB13347FE570DC4FFB13347FE570DC4F. Where is the problem?
You can read in wikipedia for example about what is the weak key in cryptography. For triple DES there is a method (TripleDES.IsWeakKey) which checks triple DES key for weakness. In you case, key FB13347FE570DC4FFB13347FE570DC4F is symmetric in a sense that first 8 bytes of it are exactly equal last 8 bytes. That means if you encrypt something with that key, and then encrypt that encrypted info one more time - you will restore original text (because of how this concrete encryption algorithm works), which is obviously dangerous.
So in short .NET protects you from doing dangerous things resulting in cryptographic weakness. If you will use standard GenerateKey() function to generate key (or just don't set Key explicitly) - weak keys won't be generated.
A bit more information about why that key is weak for triple DES. 3DES is named like this because it essentially uses 3 keys and applies pure DES encryption\decryption with those keys 3 times. Each key is 8 bytes long, so 3DES key size is 8*3 = 24 bytes. However, algorithm also allows for first and third keys to be the same, and as such allows to use 16-byte keys (like in your example). In that case first half of those 16-bytes are used as a third key. This option provides less security but is still viable.
Now, when in your case first half and second half of your 16-bytes key are the same, so all three keys which will be used by 3DES are the same. Given that 3DES works like this:
DES encrypt with 3rd(DES Decrypt with 2nd(DES Encrypt with 1st(plaintext)))
You see that in your case you fall back to using simple DES, which defeats whole purpose of using 3DES in the first place.
It is a weak 3DES key because the additional 8-byte will again be repeated as the last 8-bits. Thus the 3DES encryption has reverted to DES and that is weak.
3DES does three operations, in the most common form of ede the data is first encrypted with the first 8-bytes of the key, then decrypted with the second 8-bytes and finally encrypted with the final 8-bytes (which in this case are the first 8-bytes). Note that after the first two operations the data is back to the original data thus the only encryption that is actually performed is the last encryption and that is 8-bytes which is a 56-bit key. That is a weak 3DES key.
I found this solution on MSDN Forum. This solution works perfectly with weak keys.
With the code from the forum I made this:
using System.Security.Cryptography;
using System.IO;
using System.Reflection;
static class MyDES
{
public static byte[] Encrypt(byte[] data, byte[] key, byte[] IV)
{
MemoryStream mStream = new MemoryStream();
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.Mode = CipherMode.ECB;
des.Padding = PaddingMode.None;
CryptoStream cStream = new CryptoStream(mStream,
des.CreateWeakEncryptor(key, IV),
CryptoStreamMode.Write);
cStream.Write(data, 0, data.Length);
cStream.FlushFinalBlock();
byte[] ret = mStream.ToArray();
cStream.Close();
mStream.Close();
return ret;
}
public static byte[] Decrypt(byte[] data, byte[] key, byte[] IV)
{
MemoryStream msDecrypt = new MemoryStream(data);
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.Mode = CipherMode.ECB;
des.Padding = PaddingMode.None;
CryptoStream csDecrypt = new CryptoStream(msDecrypt,
des.CreateWeakDecryptor(key, IV),
CryptoStreamMode.Read);
byte[] fromEncrypt = new byte[data.Length];
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
return fromEncrypt;
}
#region DESCryptoExtensions
public static ICryptoTransform CreateWeakEncryptor(this DESCryptoServiceProvider cryptoProvider, byte[] key, byte[] iv)
{
MethodInfo mi = cryptoProvider.GetType().GetMethod("_NewEncryptor", BindingFlags.NonPublic | BindingFlags.Instance);
object[] Par = { key, cryptoProvider.Mode, iv, cryptoProvider.FeedbackSize, 0 };
ICryptoTransform trans = mi.Invoke(cryptoProvider, Par) as ICryptoTransform;
return trans;
}
public static ICryptoTransform CreateWeakEncryptor(this DESCryptoServiceProvider cryptoProvider)
{
return CreateWeakEncryptor(cryptoProvider, cryptoProvider.Key, cryptoProvider.IV);
}
public static ICryptoTransform CreateWeakDecryptor(this DESCryptoServiceProvider cryptoProvider, byte[] key, byte[] iv)
{
return CreateWeakEncryptor(cryptoProvider, key, iv);
}
public static ICryptoTransform CreateWeakDecryptor(this DESCryptoServiceProvider cryptoProvider)
{
return CreateWeakDecryptor(cryptoProvider, cryptoProvider.Key, cryptoProvider.IV);
}
#endregion
}
I have large xml file with more than 30 000 lines. It has content like
<?xml version="1.0"?>
<Nodes>
<Node>some node name </Node>
<Node>some node name 2 </Node>
...
</Nodes>
I want to send this xml file with encrypted content to the client manually. Client app (wpf) will load this file and encrypt this file on demand without user intervention (all possible keys will be predefined earlier on this client app).
What method should I use to encrypt and decrypt xml file content?
I was thinking to use
http://aspnettutorialonline.blogspot.com/2012/05/encryption-and-decryption-in-aspnet.html
but since I do not have much experience with this subject I'm asking is this good solution or you would recommend something else?
AES encryption is very easy with .NET...
private readonly ICryptoTransform encryptor;
private readonly ICryptoTransform decryptor;
private readonly UTF8Encoding encoder;
var rm = new RijndaelManaged();
encryptor = rm.CreateEncryptor(key, vector);
decryptor = rm.CreateDecryptor(key, vector);
encoder = new UTF8Encoding();
public string Encrypt(string unencrypted)
{
return Convert.ToBase64String(Encrypt(encoder.GetBytes(unencrypted)));
}
public byte[] Encrypt(byte[] buffer)
{
var encryptStream = new MemoryStream();
using (var cs = new CryptoStream(encryptStream, encryptor, CryptoStreamMode.Write))
{
cs.Write(buffer, 0, buffer.Length);
}
return encryptStream.ToArray();
}
key and vector are byte[] arrays as expected by the RijndaelManaged.CreateEncryptor() and RijndaelManaged.CreateDecryptor() methods...
The key and vector values will end up being a part of your client app code so hiding the values and obfuscating will protect only against non-sofisticated attackers but if all you need is to hide the xml contents from the non-technical end-users that might be sufficient...
.Net provides many crypto-systems. Depending on your needs you can chose between DES, 3DES, AES or RSA(which is in efficient in your case). DES is the least secure, 3DES is better but I'd go for the AES. to Encrypt:
using System.Security.Cryptography;
...
class AES {
private AesCryptoServiceProvider aes;
public AES (Byte[] IV, Byte[] Key) {
aes = AesCryptoServiceProvider();
aes.Key = Key; // 256 Bits Long
// AES Key can be generated using SHA256
aes.IV = IV; // 128 Bits Long
// IV can be generated using MD5
}
public Byte[] Encrypt(Byte[] FileStream) {
ICryptoTransform Transform = aes.CreateEncryptor();
return Transform.TransformFinalBlock(FileStream, 0, FileStream.Lenght);
}
public Byte[] Decrypt (Byte[] FileStream){
ICryptoTransform Transform = aes.CreateDecryptor();
return Transform.TransformFinalBlock(FileStream, 0, FileStream.Lenght);
}
}