Encryption Decryption Implementation Hazards


In this article I will explain, how wrong implementation of Encryption/Decryption techniques can be hazardous to your security implementation and the correct way to approach the security techniques implementation

Recently on a forum I had put up a question that what was the flaw in the application.
Refer:
http://dotnetspider.com/forum/264667-A-flaw-my-application.aspx
http://dotnetspider.com/forum/264721-A-flaw-my-encrypting-decrypting-application.aspx

In this article I will explain, how wrong implementation of Encryption/Decryption techniques can be hazardous to your security implementation and the correct way to approach the security techniques implementation

If you come to the parts of the code of application that I posted on :
http://dotnetspider.com/resources/40632-Retrive-username-password-with-password-username.aspx
enc class
AND
dec fun

The two functions, from the classes that are used in the above examples are from:


file_encrypt.EncryptFile(inFile, outFile, My_username);
Details in : http://dotnetspider.com/resources/40625-Encrypt-Files-Using-RFC-Rijndael.aspx

file_decrypt.DecryptFile(inFile, outFile, username_box.Text);
Details in: http://dotnetspider.com/resources/40626-Decrypt-Files.aspx


See the part where I have marked with a red box.
If you review the piece of code carefully the place that I have marked its deleting a file.
But why is it deleting a file?
I am deleting the file because I am creating a temporary file in which the raw data is stored, which is in non-encrypted format.

While Encryption I am writing the data to a normal text file, then I am encrypting the file into a new file and deleting the normal text file.

While Decryption I am decrypting the encrypted file by creating a new text file, storing the decrypted data into the new text file,
reading/storing the data from new text file, and deleting the new text file.

Here is where a direct attack is possible, because at some point of time when I am running that application a file is created
which store the data in non-encrypted format.

This is an example where the Encryption/Decryption Techniques goes messy.
There is no problem with the Encryption/Decryption functions
They are still very strong functions.
The problem is that I didn't implemented the Encryption/Decryption functions properly in the application.

For Encryption/Decryption functions refer:

Encryption Function:
http://dotnetspider.com/resources/40648-File-encryption-Using-RFC-Rijndael.aspx

Decryption Function:
http://dotnetspider.com/resources/40626-Decrypt-Files.aspx


The Encryption/Decryption functions that are mentioned here were for Encryption/Decryption of files only
But in the application I used it for retriving Username/Password, which can use the Encryption/Decryption functions mentioned, but not without creating temporary files.

So our New Problem Domain


How to Retrive the user name and password with out creating a temporary file.

The solution is:
If we see the functions

file_encrypt.EncryptFile(inFile, outFile, My_username);
File.Delete(inFile);
/////////////////////////////////////
file_decrypt.DecryptFile(inFile, outFile, username_box.Text);
File.Delete(outFile);


The "inFile" in EncryptFile() method is the temporary file, the solution for it would be that it should be MemoryStream rather than a File/fileStream.

Similarly, the "outFile" in DecryptFile() method is the temporary file, the solution for it would be that
it should be MemoryStream rather than a File/fileStream

So We have to do a minor change in the Encryption/Decryption functions:
I will put the whole Encryption/Decryption functions change here and the class files as an attachment for your reference

The Encryption Function in the class



///
/// This takes an input Byte and encrypts it into the output file
///

/// the byte to encrypt
/// the file to write the encrypted data to
/// the password for use as the key
/// the method to call to notify of progress
public static void EncryptToFile(byte[] inFile, string outFile, string password)
{

using(MemoryStream fin = new MemoryStream(inFile))
{
using (FileStream fout = File.OpenWrite(outFile))
{
long lSize = fin.Length; // the size of the input file for storing
int size = (int)lSize; // the size of the input file for progress
byte[] bytes = new byte[BUFFER_SIZE]; // the buffer
int read = -1; // the amount of bytes read from the input file
int value = 0; // the amount overall read from the input file for progress

// generate IV and Salt
byte[] IV = GenerateRandomBytes(16);
byte[] salt = GenerateRandomBytes(16);

// create the crypting object
SymmetricAlgorithm sma = CryptoHelp.CreateRijndael(password, salt);
sma.IV = IV;

// write the IV and salt to the beginning of the file
fout.Write(IV, 0, IV.Length);
fout.Write(salt, 0, salt.Length);


// create the hashing and crypto streams
HashAlgorithm hasher = SHA256.Create();
using (CryptoStream cout = new CryptoStream(fout, sma.CreateEncryptor(), CryptoStreamMode.Write),
chash = new CryptoStream(Stream.Null, hasher, CryptoStreamMode.Write))
{
// write the size of the file to the output file
BinaryWriter bw = new BinaryWriter(cout);
bw.Write(lSize);

// write the file cryptor tag to the file
bw.Write(FC_TAG);

// read and the write the bytes to the crypto stream in BUFFER_SIZEd chunks
while ((read = fin.Read(bytes, 0, bytes.Length)) != 0)
{
cout.Write(bytes, 0, read);
chash.Write(bytes, 0, read);
value += read;
}
// flush and close the hashing object

chash.Flush();
chash.Close();

// read the hash
byte[] hash = hasher.Hash;

// write the hash to the end of the file
cout.Write(hash, 0, hash.Length);

// flush and close the cryptostream
cout.Flush();
cout.Close();
}
}
}
}


The Decryption Function in the class



///
/// takes an input file and decrypts it to the output file
///

/// the file to decrypt
/// the to write the decrypted data to
/// the password used as the key
/// the data stored in the file
public static string DecryptFromFile(string inFile, string password, out string My_data)
{
// NOTE: The encrypting algo was so much easier...

byte[] bytes = new byte[BUFFER_SIZE];

// create and open the file streams
using (FileStream fin = File.OpenRead(inFile))
//fout = File.OpenWrite(outFile))
{
int size = (int)fin.Length; // the size of the file for progress notification
//byte[] bytes = new byte[BUFFER_SIZE]; // byte buffer
int read = -1; // the amount of bytes read from the stream
int value = 0;
int outValue = 0; // the amount of bytes written out

// read off the IV and Salt
byte[] IV = new byte[16];
fin.Read(IV, 0, 16);
byte[] salt = new byte[16];
fin.Read(salt, 0, 16);

// create the crypting stream
SymmetricAlgorithm sma = CryptoHelpd.CreateRijndael(password, salt);
sma.IV = IV;

value = 32; // the value for the progress
long lSize = -1; // the size stored in the input stream

// create the hashing object, so that we can verify the file
HashAlgorithm hasher = SHA256.Create();

// create the cryptostreams that will process the file
using (CryptoStream cin = new CryptoStream(fin, sma.CreateDecryptor(), CryptoStreamMode.Read),
chash = new CryptoStream(Stream.Null, hasher, CryptoStreamMode.Write))
{
// read size from file
BinaryReader br = new BinaryReader(cin);
lSize = br.ReadInt64();
ulong tag = br.ReadUInt64();

if (FC_TAG != tag)
throw new CryptoHelpException("File Corrupted!");

//determine number of reads to process on the file
long numReads = lSize / BUFFER_SIZE;

// determine what is left of the file, after numReads
long slack = (long)lSize % BUFFER_SIZE;

// read the buffer_sized chunks
for (int i = 0; i < numReads; ++i)
{
read = cin.Read(bytes, 0, bytes.Length);
chash.Write(bytes, 0, read);
value += read;
outValue += read;

}

// now read the slack
if (slack > 0)
{
read = cin.Read(bytes, 0, (int)slack);

chash.Write(bytes, 0, read);
value += read;
outValue += read;

}
// flush and close the hashing stream
chash.Flush();
chash.Close();

// read the current hash value
byte[] curHash = hasher.Hash;

// get and compare the current and old hash values
byte[] oldHash = new byte[hasher.HashSize / 8];
read = cin.Read(oldHash, 0, oldHash.Length);
if ((oldHash.Length != read) || (!CheckByteArrays(oldHash, curHash)))
throw new CryptoHelpException("File Corrupted!");
}

// make sure the written and stored size are equal
if (outValue != lSize)
throw new CryptoHelpException("File Sizes don't match!");
}

MemoryStream stream = new MemoryStream(bytes);

// convert stream to string
StreamReader reader = new StreamReader(stream);

int NumberOfLines = 3;

//Make our array for each line
string[] ListLines = new string[NumberOfLines];

//Read the number of lines and put them in the array
for (int i = 1; i < NumberOfLines; i++)
{
ListLines[i] = reader.ReadLine();
}

My_data = ListLines[1];
return "";
}


THE END



I am also attaching the Encryption/Decryption Classes I discussed here.

Any doubts, give a response.

Cheers
Paul


Attachments

  • classfiles (40832-5917-EncDec-class.rar)
  • Comments

    No responses found. Be the first to comment...


  • Do not include your name, "with regards" etc in the comment. Write detailed comment, relevant to the topic.
  • No HTML formatting and links to other web sites are allowed.
  • This is a strictly moderated site. Absolutely no spam allowed.
  • Name:
    Email: