This task involves two methods, the event handler method for the Encrypt File button, buttonEncryptFile_Click, and the EncryptFile method. The first method displays a dialog box for selecting a file and passes the file name to the second method which performs the encryption.
The encrypted content, key, and IV are all saved to one FileStream referred to as the encryption package.
The EncryptFile method does the following:
-
Creates a RijndaelManaged symmetric algorithm to encrypt the content.
-
Creates an instance of the RSACryptoServiceProvider to encrypt the RijndaelManaged key.
-
Uses a CryptoStream to read and encrypt the FileStream of the source file, in blocks of bytes, into a destination FileStream for the encrypted file.
-
Determines the lengths of the encrypted key and IV and creates byte arrays of their length values.
-
Writes the Key, IV, and their length values to the encrypted package.
The encryption package the following format:
-
Key length, bytes 0 - 3
-
IV length, bytes 4 - 7
-
Encrypted key
-
IV
-
Cipher text
By having the lengths of the key and IV, you can determine the starting points and lengths of all parts of the encryption package for decrypting the file.
Add the following code example as the Click event handler for the Encrypt File button: buttonEncryptFile_Click.
Private Sub buttonEncryptFile_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles buttonEncryptFile.Click
If rsa Is Nothing Then
MsgBox("Key not set.")
Else
' Display a dialog box to select a file to encrypt.
OpenFileDialog1.InitialDirectory = SrcFolder
If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
Try
Dim fName As String = OpenFileDialog1.FileName
If (Not (fName) Is Nothing) Then
Dim fInfo As FileInfo = New FileInfo(fName)
' Use just the file name without path.
Dim name As String = fInfo.Name
EncryptFile(name)
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
End If
End Sub
private void buttonEncryptFile_Click(object sender, System.EventArgs e)
{
if (rsa == null)
MessageBox.Show("Key not set.");
else
{
// Display a dialog box to select a file to encrypt.
openFileDialog1.InitialDirectory = SrcFolder;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
string fName = openFileDialog1.FileName;
if (fName != null)
{
FileInfo fInfo = new FileInfo(fName);
// Pass the file name without the path.
string name = fInfo.Name;
EncryptFile(name);
}
}
}
}
Add the following EncryptFile method to the form.
Private Sub EncryptFile(ByVal inFile As String)
' Create instance of Rijndael for
' symetric encryption of the data.
Dim rjndl As RijndaelManaged = New RijndaelManaged
rjndl.KeySize = 256
rjndl.BlockSize = 256
rjndl.Mode = CipherMode.CBC
Dim transform As ICryptoTransform = rjndl.CreateEncryptor
' Use RSACryptoServiceProvider to
' enrypt the Rijndael key.
Dim keyEncrypted() As Byte = rsa.Encrypt(rjndl.Key, False)
' Create byte arrays to contain
' the length values of the key and IV.
Dim LenK() As Byte = New Byte((4) - 1) {}
Dim LenIV() As Byte = New Byte((4) - 1) {}
Dim lKey As Integer = keyEncrypted.Length
LenK = BitConverter.GetBytes(lKey)
Dim lIV As Integer = rjndl.IV.Length
LenIV = BitConverter.GetBytes(lIV)
' Write the following to the FileStream
' for the encrypted file (outFs):
' - length of the key
' - length of the IV
' - ecrypted key
' - the IV
' - the encrypted cipher content
' Change the file's extension to ".enc"
Dim outFile As String = (EncrFolder _
+ (inFile.Substring(0, inFile.LastIndexOf(".")) + ".enc"))
Using outFs As FileStream = New FileStream(outFile, FileMode.Create)
outFs.Write(LenK, 0, 4)
outFs.Write(LenIV, 0, 4)
outFs.Write(keyEncrypted, 0, lKey)
outFs.Write(rjndl.IV, 0, lIV)
' Now write the cipher text using
' a CryptoStream for encrypting.
Using outStreamEncrypted As CryptoStream = New CryptoStream(outFs, transform, CryptoStreamMode.Write)
' By encrypting a chunk at
' a time, you can save memory
' and accommodate large files.
Dim count As Integer = 0
Dim offset As Integer = 0
' blockSizeBytes can be any arbitrary size.
Dim blockSizeBytes As Integer = (rjndl.BlockSize / 8)
Dim data() As Byte = New Byte((blockSizeBytes) - 1) {}
Dim bytesRead As Integer = 0
Using inFs As FileStream = New FileStream(inFile, FileMode.Open)
Do
count = inFs.Read(data, 0, blockSizeBytes)
offset = (offset + count)
outStreamEncrypted.Write(data, 0, count)
bytesRead = (bytesRead + blockSizeBytes)
Loop Until (count = 0)
outStreamEncrypted.FlushFinalBlock()
inFs.Close()
End Using
outStreamEncrypted.Close()
End Using
outFs.Close()
End Using
End Sub
private void EncryptFile(string inFile)
{
// Create instance of Rijndael for
// symetric encryption of the data.
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 256;
rjndl.Mode = CipherMode.CBC;
ICryptoTransform transform = rjndl.CreateEncryptor();
// Use RSACryptoServiceProvider to
// enrypt the Rijndael key.
byte[] keyEncrypted = rsa.Encrypt(rjndl.Key, false);
// Create byte arrays to contain
// the length values of the key and IV.
byte[] LenK = new byte[4];
byte[] LenIV = new byte[4];
int lKey = keyEncrypted.Length;
LenK = BitConverter.GetBytes(lKey);
int lIV = rjndl.IV.Length;
LenIV = BitConverter.GetBytes(lIV);
// Write the following to the FileStream
// for the encrypted file (outFs):
// - length of the key
// - length of the IV
// - ecrypted key
// - the IV
// - the encrypted cipher content
// Change the file's extension to ".enc"
string outFile = EncrFolder + inFile.Substring(0, inFile.LastIndexOf(".")) + ".enc";
using (FileStream outFs = new FileStream(outFile, FileMode.Create))
{
outFs.Write(LenK, 0, 4);
outFs.Write(LenIV, 0, 4);
outFs.Write(keyEncrypted, 0, lKey);
outFs.Write(rjndl.IV, 0, lIV);
// Now write the cipher text using
// a CryptoStream for encrypting.
using (CryptoStream outStreamEncrypted = new CryptoStream(outFs, transform, CryptoStreamMode.Write))
{
// By encrypting a chunk at
// a time, you can save memory
// and accommodate large files.
int count = 0;
int offset = 0;
// blockSizeBytes can be any arbitrary size.
int blockSizeBytes = rjndl.BlockSize / 8;
byte[] data = new byte[blockSizeBytes];
int bytesRead = 0;
using (FileStream inFs = new FileStream(inFile, FileMode.Open))
{
do
{
count = inFs.Read(data, 0, blockSizeBytes);
offset += count;
outStreamEncrypted.Write(data, 0, count);
bytesRead += blockSizeBytes;
}
while (count > 0);
inFs.Close();
}
outStreamEncrypted.FlushFinalBlock();
outStreamEncrypted.Close();
}
outFs.Close();
}
}