Jul 16, 2011 10:12 AM
(This post was last modified: Jan 7, 2012 02:57 AM by hgdfhsdgdfgdfh.)
Forget using static and UNSECURE IV's and unsecure algorithms.
Features of this AES class:
- Uses always 256-bit AES
- As secure as possible (uses standardized algorithms)
- "Polymorphic" / unique output (CBC cipher mode with random IV)
- Simple to use
- Works with .NET 2.0
Why its secure:
First, it uses AES, algorithm approved by US government to encrypt TOP SECRET information.
Secondly, it uses standard PBKDF2 algorithm to derive encryption key from password key with RANDOM 256-bit salt and RANDOM IV (= dictionary attacks practically impossible).
Salt and IV are automatically stored concatenated after the actual ciphertext (its not a security risk). You dont have to care about them. Decryption function automatically strips them and uses them in encryption. New completely random salt and IV is generated for each crypt automatically.
REMEMBER TO USE ENOUGH BIG PASSWORD/KEY (I SUGGEST AT LEAST 256-BITS = 32 BYTES!)
VB.NET
C#
Example (note the BAD key):
Features of this AES class:
- Uses always 256-bit AES
- As secure as possible (uses standardized algorithms)
- "Polymorphic" / unique output (CBC cipher mode with random IV)
- Simple to use
- Works with .NET 2.0
Why its secure:
First, it uses AES, algorithm approved by US government to encrypt TOP SECRET information.
Secondly, it uses standard PBKDF2 algorithm to derive encryption key from password key with RANDOM 256-bit salt and RANDOM IV (= dictionary attacks practically impossible).
Salt and IV are automatically stored concatenated after the actual ciphertext (its not a security risk). You dont have to care about them. Decryption function automatically strips them and uses them in encryption. New completely random salt and IV is generated for each crypt automatically.
REMEMBER TO USE ENOUGH BIG PASSWORD/KEY (I SUGGEST AT LEAST 256-BITS = 32 BYTES!)
VB.NET
Code
'
'* Copyright (C) 2011, Dextrey (0xDEADDEAD)
'* Removing this copyright notice is prohibited without permission from author
'* Using this code in your own software product, commercial or not is allowed
'
Imports System.Collections.Generic
Imports System.Text
Namespace DexCrypt
Class PolyAES
Const saltSize As Integer = 32
Private algo As System.Security.Cryptography.SymmetricAlgorithm
Private rngAlgo As System.Security.Cryptography.RNGCryptoServiceProvider
Private salt As Byte()
Public Sub New()
Me.algo = New System.Security.Cryptography.RijndaelManaged()
Me.algo.Mode = System.Security.Cryptography.CipherMode.CBC
Me.rngAlgo = New System.Security.Cryptography.RNGCryptoServiceProvider()
End Sub
Private Sub InitializeSecureParameters(key As Byte())
' init rijndael IV
Me.algo.GenerateIV()
salt = New Byte(saltSize - 1) {}
rngAlgo.GetBytes(salt)
Dim pwDeriveAlg As New System.Security.Cryptography.Rfc2898DeriveBytes(key, salt, 2000)
Me.algo.Key = pwDeriveAlg.GetBytes(32)
End Sub
Private Sub LoadSecureParameters(key As Byte(), encIv As Byte(), encSalt As Byte())
Me.algo.IV = encIv
Me.salt = encSalt
Dim pwDeriveAlg As New System.Security.Cryptography.Rfc2898DeriveBytes(key, salt, 2000)
Me.algo.Key = pwDeriveAlg.GetBytes(32)
End Sub
Public Function Encrypt(plainText As String, key As String) As String
Return Convert.ToBase64String(Me.Encrypt(UnicodeEncoding.UTF8.GetBytes(plainText), UnicodeEncoding.UTF8.GetBytes(key)))
End Function
Public Function Decrypt(cipherText As String, key As String) As String
Return UnicodeEncoding.UTF8.GetString(Me.Decrypt(Convert.FromBase64String(cipherText), UnicodeEncoding.UTF8.GetBytes(key)))
End Function
Public Function Encrypt(plainText As Byte(), key As Byte()) As Byte()
InitializeSecureParameters(key)
Dim encTransform As System.Security.Cryptography.ICryptoTransform = algo.CreateEncryptor()
Return ConcatDataToCipherText(ConcatDataToCipherText(encTransform.TransformFinalBlock(plainText, 0, plainText.Length), salt), algo.IV)
End Function
Public Function Decrypt(cipherText As Byte(), key As Byte()) As Byte()
Dim cipherTextWithSalt As Byte() = New Byte(0) {}
Dim encSalt As Byte() = New Byte(0) {}
Dim origCipherText As Byte() = New Byte(0) {}
Dim encIv As Byte() = New Byte(0) {}
SliceCipherTextIntoParts(cipherText, 16, cipherTextWithSalt, encIv)
SliceCipherTextIntoParts(cipherTextWithSalt, saltSize, origCipherText, encSalt)
LoadSecureParameters(key, encIv, encSalt)
Dim decTransform As System.Security.Cryptography.ICryptoTransform = algo.CreateDecryptor()
Dim plainText As Byte() = decTransform.TransformFinalBlock(origCipherText, 0, origCipherText.Length)
Return plainText
End Function
Private Function ConcatDataToCipherText(cipherText As Byte(), iv As Byte()) As Byte()
Dim origLength As Integer = cipherText.Length
Array.Resize(cipherText, cipherText.Length + iv.Length)
Buffer.BlockCopy(iv, 0, cipherText, origLength, iv.Length)
Return cipherText
End Function
Private Sub SliceCipherTextIntoParts(cipherText As Byte(), secondPartLen As Integer, ByRef origCipherText As Byte(), ByRef iv As Byte())
Array.Resize(iv, secondPartLen)
Buffer.BlockCopy(cipherText, CInt(cipherText.Length - secondPartLen), iv, 0, secondPartLen)
Array.Resize(origCipherText, CInt(cipherText.Length - secondPartLen))
Buffer.BlockCopy(cipherText, 0, origCipherText, 0, CInt(cipherText.Length - secondPartLen))
End Sub
End Class
End NamespaceC#
Code
/*
* Copyright (C) 2011, Dextrey (0xDEADDEAD)
* Removing this copyright notice is prohibited without permission from author
* Using this code in your own software product, commercial or not is allowed
*/
using System;
using System.Collections.Generic;
using System.Text;
namespace DexCrypt
{
class PolyAES
{
const int saltSize = 32;
System.Security.Cryptography.SymmetricAlgorithm algo;
System.Security.Cryptography.RNGCryptoServiceProvider rngAlgo;
byte[] salt;
public PolyAES()
{
this.algo = new System.Security.Cryptography.RijndaelManaged();
this.algo.Mode = System.Security.Cryptography.CipherMode.CBC;
this.rngAlgo = new System.Security.Cryptography.RNGCryptoServiceProvider();
}
private void InitializeSecureParameters(byte[] key)
{
// init rijndael IV
this.algo.GenerateIV();
salt = new byte[saltSize];
rngAlgo.GetBytes(salt);
System.Security.Cryptography.Rfc2898DeriveBytes pwDeriveAlg = new System.Security.Cryptography.Rfc2898DeriveBytes(key, salt, 2000);
this.algo.Key = pwDeriveAlg.GetBytes(32);
}
private void LoadSecureParameters(byte[] key, byte[] encIv, byte[] encSalt)
{
this.algo.IV = encIv;
this.salt = encSalt;
System.Security.Cryptography.Rfc2898DeriveBytes pwDeriveAlg = new System.Security.Cryptography.Rfc2898DeriveBytes(key, salt, 2000);
this.algo.Key = pwDeriveAlg.GetBytes(32);
}
public string Encrypt(string plainText, string key)
{
return Convert.ToBase64String(this.Encrypt(UnicodeEncoding.UTF8.GetBytes(plainText), UnicodeEncoding.UTF8.GetBytes(key)));
}
public string Decrypt(string cipherText, string key)
{
return UnicodeEncoding.UTF8.GetString(this.Decrypt(Convert.FromBase64String(cipherText), UnicodeEncoding.UTF8.GetBytes(key)));
}
public byte[] Encrypt(byte[] plainText, byte[] key)
{
InitializeSecureParameters(key);
System.Security.Cryptography.ICryptoTransform encTransform = algo.CreateEncryptor();
return ConcatDataToCipherText(ConcatDataToCipherText(encTransform.TransformFinalBlock(plainText, 0, plainText.Length), salt), algo.IV);
}
public byte[] Decrypt(byte[] cipherText, byte[] key)
{
byte[] cipherTextWithSalt = new byte[1];
byte[] encSalt = new byte[1];
byte[] origCipherText = new byte[1];
byte[] encIv = new byte[1];
SliceCipherTextIntoParts(cipherText, 16, ref cipherTextWithSalt, ref encIv);
SliceCipherTextIntoParts(cipherTextWithSalt, saltSize, ref origCipherText, ref encSalt);
LoadSecureParameters(key, encIv, encSalt);
System.Security.Cryptography.ICryptoTransform decTransform = algo.CreateDecryptor();
byte[] plainText = decTransform.TransformFinalBlock(origCipherText, 0, origCipherText.Length);
return plainText;
}
private byte[] ConcatDataToCipherText(byte[] cipherText, byte[] iv)
{
int origLength = cipherText.Length;
Array.Resize(ref cipherText, cipherText.Length + iv.Length);
Buffer.BlockCopy(iv, 0, cipherText, origLength, iv.Length);
return cipherText;
}
private void SliceCipherTextIntoParts(byte[] cipherText, int secondPartLen, ref byte[] origCipherText, ref byte[] iv)
{
Array.Resize(ref iv, secondPartLen);
Buffer.BlockCopy(cipherText, (int)(cipherText.Length - secondPartLen), iv, 0, secondPartLen);
Array.Resize(ref origCipherText, (int)(cipherText.Length - secondPartLen));
Buffer.BlockCopy(cipherText, 0, origCipherText, 0, (int)(cipherText.Length - secondPartLen));
}
}
}Example (note the BAD key):
Code
Dim enc As New PolyAES()
Dim dec As New PolyAES()
Console.WriteLine(enc.Encrypt("Hello, World!", "key123456"))
Console.WriteLine(dec.Decrypt(enc.Encrypt("Hello, World!", "key123456"), "key123456"))Code
PolyAES enc = new PolyAES();
PolyAES dec = new PolyAES();
Console.WriteLine(enc.Encrypt("Hello, World!", "key123456"));
Console.WriteLine(dec.Decrypt(enc.Encrypt("Hello, World!", "key123456"), "key123456"));

