Introduction
Crypto Gear application is developed in the
concept of Cryptography in WPF C# .NET which is to encrypt files and decrypt files, giving security for
data from unauthorized access. In
this application the user Interface is much more concentrated on look and
feel and ease of access.
Background
This article is very much useful for those
interested in UI design and development. Mostly WPF is preferred for developing stunning
user interfaces. And we could design controls of our own.
Using the code
Here is the application crypto gear used for file security.
It uses namespaces System.IO and System.Security.Cryptography.
We use
a ListView in this application. To add items in the ListView, we must have create a property class for
binding in the Listview. The ObservableCollection class is used for selecting items in the ListView.
ObservableCollection<FileHandle> Lst = new ObservableCollection<FileHandle>();
private void btAdd_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog op = new Microsoft.Win32.OpenFileDialog();
op.Multiselect = true;
FileInfo n;
if (op.ShowDialog() == true)
{
foreach (string fil in op.FileNames)
{
n = new FileInfo(fil);
if (n.Extension != ".enc")
{
s1 = n.Name;
s2 = n.FullName;
Lst.Add(new FileHandle(s1, s2));
LstEnc.ItemsSource = Lst;
}
else
{
System.Windows.MessageBox.Show(n.Name + " : File Is Already Encrypted",
"Crypto Gear", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
RemoveDuplicates();
}
}
Here is the property class for displaying data in the ListView:
class FileHandle
{
public System.Drawing.Image filico;
private string FileName;
private string FilePath;
public System.Drawing.Image FileIco
{
get
{
return filico;
}
set
{
filico = value;
}
}
public string FirstCol
{
get { return FileName; }
set { FileName = value; }
}
public string LastCol
{
get { return FilePath; }
set { FilePath = value; }
}
public FileHandle(string fn,string fp)
{
FileName = fn;
FilePath = fp;
}
}
Here is the data binding code for the ListView:
<ListView Margin="101,39,297,32" Name="LstEnc" >
<ListView.View>
<GridView>
<GridViewColumn Header="Files To Be Encrypted" Width="500">
<GridViewColumn.CellTemplate>
<DataTemplate>
<DockPanel Height="50" Width="Auto">
<Image Height="30" Width="40" Name="FileIcons"
Source="{Binding FileIco}" Stretch="Fill" />
<StackPanel>
<TextBlock FontFamily="verdana" FontSize="15"
FontWeight="Bold" Height="25" HorizontalAlignment="Left"
Name="FileName" Padding="3" Text="{Binding FirstCol}"
TextAlignment="Center" VerticalAlignment="Center"
Width="Auto" Foreground="Black" />
<TextBlock FontFamily="ArialBlack" FontSize="12"
ForceCursor="False" Height="17"
HorizontalAlignment="Left" Name="FilePath"
Padding="3" Text="{Binding LastCol}"
TextAlignment="Center" TextDecorations="None"
VerticalAlignment="Center" Width="Auto" Foreground="Black">
<TextBlock.BindingGroup>
<BindingGroup Name="s2" NotifyOnValidationError="True" />
</TextBlock.BindingGroup>
</TextBlock>
</StackPanel>
</DockPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Encryption Algorithm (Rijindael)
AES is based on a design principle known as a substitution-permutation network.
It is fast in both software and hardware.[6].
Unlike its predecessor, DES, AES does not use a Feistel network.
AES has a fixed block size of 128
bits and a key size of 128,
192, or 256 bits, whereas Rijndael is specified with block and key sizes in any multiple of 32 bits, both with a minimum of 128 and a maximum of 256 bits.
AES operates on a 4×4 column-major order matrix of bytes,
termed the state (versions of Rijndael with a larger block size have additional columns in the state). Most AES calculations are done
in a special finite field.
Here is the code sample:
private void Encrypt(string strInputFile, string strOutputFile, byte[] bytKey, byte[] bytIV)
{
RemoveDuplicates();
System.Windows.Forms.Application.DoEvents();
s2 = "In Progress";
FileInfo FileO = new FileInfo(strOutputFile);
if (FileO.Exists)
{
if (MessageBox.Show("Encrypted File Already Exist, want to replace?",
FileO.Name, MessageBoxButton.YesNo, MessageBoxImage.Exclamation) == MessageBoxResult.Yes)
{
FileO.Delete();
}
else
{
s2 = "Skipped";
cl = new CryptFile(FileO.Name, s2, 100, "r");
LstView.Items[FileListIndex] = cl;
goto Exit;
}
}
FileInfo FileI = new FileInfo(strInputFile);
cl = new CryptFile(FileI.Name,s2,0,"");
LstView.Items[FileListIndex] = cl;
System.Windows.Forms.Application.DoEvents();
try
{
FileStream fsInput;
FileStream fsOutput;
fsInput = new FileStream(strInputFile, FileMode.Open, FileAccess.Read);
fsOutput = new FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write);
fsOutput.SetLength(0);
byte[] bytBuffer = new byte[4097];
long lngBytesProcessed = 0;
long lngFileLength = fsInput.Length;
int intBytesInCurrentBlock = 0;
CryptoStream csCryptoStream = default(CryptoStream);
RijndaelManaged cspRijndael = new RijndaelManaged();
csCryptoStream = new CryptoStream(fsOutput,
cspRijndael.CreateEncryptor(bytKey, bytIV), CryptoStreamMode.Write);
while (lngBytesProcessed < lngFileLength)
{
if (IsPaused != true)
{
if (IsCancelled == false)
{
intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096);
csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock);
lngBytesProcessed = lngBytesProcessed + Convert.ToInt32(intBytesInCurrentBlock);
double prg = Convert.ToDouble(Convert.ToDouble(lngBytesProcessed) /
Convert.ToDouble(lngFileLength) * 100);
cl = new CryptFile(FileI.Name, s2,prg,"");
LstView.Items[FileListIndex] = cl;
}
else
{
csCryptoStream.Close();
fsInput.Close();
fsOutput.Close();
FileInfo Del = new FileInfo(strOutputFile);
Del.Delete();
break;
}
}
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new EmptyDelegate(delegate { }));
}
csCryptoStream.Close();
fsInput.Close();
fsOutput.Close();
FilesTODelete.Add(strInputFile);
s2 = "Encrypted";
cl = new CryptFile(FileI.Name, s2, 100, "a");
LstView.Items[FileListIndex] = cl;
}
catch
{
MessageBox.Show("Encryption Failed", "Crypto Gear",
MessageBoxButton.OK, MessageBoxImage.Error);
s2 = "Error, Skipped";
cl = new CryptFile(FileI.Name, s2, 100, "r");
LstView.Items[FileListIndex] = cl;
}
Exit: FileO = null;FileListIndex++;
}
private void Decrypt(string strInputFile, string strOutputFile, byte[] bytKey, byte[] bytIV)
{
RemoveDuplicates();
System.Windows.Forms.Application.DoEvents();
s2 = "In Progress";
FileInfo FileO = new FileInfo(strOutputFile);
if (FileO.Exists)
{
if (MessageBox.Show("File Already Exist, want to replace?", FileO.Name,
MessageBoxButton.YesNo, MessageBoxImage.Exclamation) == MessageBoxResult.Yes)
{
FileO.Delete();
}
else
{
s2 = "Skipped";
cl = new CryptFile(FileO.Name, s2, 100, "r");
LstView.Items[FileListIndex] = cl;
goto Exit;
}
}
FileInfo FileI = new FileInfo(strInputFile);
cl = new CryptFile(FileI.Name, s2,0,"");
LstView.Items[FileListIndex] = cl;
FileStream fsInput;
FileStream fsOutput;
try
{
fsInput = new FileStream(strInputFile, FileMode.Open, FileAccess.Read);
fsOutput = new FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write);
fsOutput.SetLength(0);
byte[] bytBuffer = new byte[4097];
long lngBytesProcessed = 0;
long lngFileLength = fsInput.Length;
int intBytesInCurrentBlock = 0;
CryptoStream csCryptoStream = default(CryptoStream);
RijndaelManaged cspRijndael = new RijndaelManaged();
csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateDecryptor(bytKey, bytIV), CryptoStreamMode.Write);
while (lngBytesProcessed < lngFileLength)
{
if (IsPaused != true)
{
if (IsCancelled == false)
{
intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096);
csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock);
lngBytesProcessed = lngBytesProcessed + Convert.ToInt64(intBytesInCurrentBlock);
double prg = Convert.ToDouble(Convert.ToDouble(lngBytesProcessed) / Convert.ToDouble(lngFileLength) * 100);
cl = new CryptFile(FileI.Name, s2,prg,"");
LstView.Items[FileListIndex] = cl;
}
else
{
csCryptoStream.Close();
fsInput.Close();
fsOutput.Close();
FileInfo Del = new FileInfo(strOutputFile);
Del.Delete();
break;
}
}
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new EmptyDelegate(delegate { }));
}
try
{
csCryptoStream.Close();
FilesTODelete.Add(strInputFile);
s2 = "Decrypted";
cl = new CryptFile(FileI.Name, s2, 100, "a");
LstView.Items[FileListIndex] = cl;
}
catch
{
FileInfo Del = new FileInfo(strOutputFile);
s2 = "Wrong Password!";
cl = new CryptFile(FileI.Name, s2, 100, "r");
LstView.Items[FileListIndex] = cl;
fsInput.Close();
fsOutput.Close();
Del.Delete();
}
fsInput.Close();
fsOutput.Close();
}
catch
{
s2 = "Error, Skipped";
MessageBox.Show("Decryption Failed", "Crypto Gear", MessageBoxButton.OK, MessageBoxImage.Error);
FileInfo Del = new FileInfo(strOutputFile);
cl = new CryptFile(FileI.Name, s2, 100, "r");
LstView.Items[FileListIndex] = cl;
}
Exit: FileO = null; FileListIndex++;
}