views:

159

answers:

4

it seems that my code adds 6 bytes to the result file after encrypt decrypt is called.. i tries it on a mkv file.. please help

here is my code

class TripleDESCryptoService : IEncryptor, IDecryptor
{
    public void Encrypt(string inputFileName, string outputFileName, string key)
    {
        EncryptFile(inputFileName, outputFileName, key);
    }

    public void Decrypt(string inputFileName, string outputFileName, string key)
    {
        DecryptFile(inputFileName, outputFileName, key);
    }

    static void EncryptFile(string inputFileName, string outputFileName, string sKey)
    {
        var outFile = new FileStream(outputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);

        // The chryptographic service provider we're going to use
        var cryptoAlgorithm = new TripleDESCryptoServiceProvider();
        SetKeys(cryptoAlgorithm, sKey);

        // This object links data streams to cryptographic values
        var cryptoStream = new CryptoStream(outFile, cryptoAlgorithm.CreateEncryptor(), CryptoStreamMode.Write);

        // This stream writer will write the new file
        var encryptionStream = new BinaryWriter(cryptoStream);

        // This stream reader will read the file to encrypt
        var inFile = new FileStream(inputFileName, FileMode.Open, FileAccess.Read);
        var readwe = new BinaryReader(inFile);

        // Loop through the file to encrypt, line by line
        var date = readwe.ReadBytes((int)readwe.BaseStream.Length);


        // Write to the encryption stream
        encryptionStream.Write(date);


        // Wrap things up
        inFile.Close();
        encryptionStream.Flush();
        encryptionStream.Close();
    }

    private static void SetKeys(SymmetricAlgorithm algorithm, string key)
    {
        var keyAsBytes = Encoding.ASCII.GetBytes(key);
        algorithm.IV = keyAsBytes.Take(algorithm.IV.Length).ToArray();
        algorithm.Key = keyAsBytes.Take(algorithm.Key.Length).ToArray();
    }

    static void DecryptFile(string inputFilename, string outputFilename, string sKey)
    {
        // The encrypted file
        var inFile = File.OpenRead(inputFilename);

        // The decrypted file
        var outFile = new FileStream(outputFilename, FileMode.OpenOrCreate, FileAccess.ReadWrite);

        // Prepare the encryption algorithm and read the key from the key file
        var cryptAlgorithm = new TripleDESCryptoServiceProvider();

        SetKeys(cryptAlgorithm, sKey);

        // The cryptographic stream takes in the encrypted file
        var encryptionStream = new CryptoStream(inFile, cryptAlgorithm.CreateDecryptor(), CryptoStreamMode.Read);

        // Write the new unecrypted file
        var cleanStreamReader = new BinaryReader(encryptionStream);
        var cleanStreamWriter = new BinaryWriter(outFile);
        cleanStreamWriter.Write(cleanStreamReader.ReadBytes((int)inFile.Length));
        cleanStreamWriter.Close();
        outFile.Close();
        cleanStreamReader.Close();
    }
}
A: 

I glanced over the code and found no problem, but I'm not very familiar with the classes you used so I may well be wrong. Instead, I'll give some general advice that applies to any bug:

Try to hunt down the problem. It's difficult to find a mistake in many lines of code. Create the shortest possible code that displays the faulty behavior.

For instance, try to write a string to the output stream. Is the size correct?

  • If no, you almost found the problem - something is wrong with file writing, the encryption stuff has nothing to do with the issue.
  • If yes, continue to add functionality in small steps until you discover the problem.

That's a standard debugging technique and extremely helpful, I suggest to use it every time you encounter a problem.

Aside from that, try to always have clean starting conditions, i.e. make sure the file written to was deleted. Try your code on different input and see if it fails with the exact same result every time or if there are differences.

Edit:

According to other responses, the 64 bit block is causing your trouble. With the ideas described earlier, you can easily exclude many other factors until only the encryption itself would be left.

Then you're able to ask "Why is TripeDES adding up to 7 bytes to the input?" which would a far more clear question than "What's wrong with my triple DES wrapper??" - and you would have gotten an answer to this simple question in less than a minute for sure!

mafutrct
A: 

Tiple-DES is a 64 bit block cipher. Without analyzing your code my guess is that your data isn't 64-bit aligned and that it has been padded with the default PKCS7 mode.

Jonas Elfström
A: 

I don't know which encryption mode you use, but ECB and CBC mode add padding bits at the end of the last block to increase it's size to 64 bit. Maybe that's where your bytes come from?

Juri Robl
if i'll use another mode it will not happen?
Chen Kinnrot
+1  A: 

Your code is not adding six bytes, 3DES is rounding up to a full block size. This is how block ciphers work. You will see this only in the resulting ciphertext, but not in the decrypted plaintext.

Again there is no need to worry, block ciphers must pad your plaintext to the next block size before it can encrypt the plaintext. When you decrypt the ciphertext, the padding is removed.

Also, I did a quick code review, and you have an error in the code - you are using the same key for the IV and the key, and you really should use different data. So I would add another arg to DecryptFile(), EncryptFile() and SetKeys() to allow for a different IV.

Michael Howard-MSFT
what is this IV, and they are not the same cause the size is not the same, IV is 8 byte and key is 24 byte..the decrypted file does have the extra 6 bytes, should i be worry and cut it?
Chen Kinnrot
Initialization Vector - it's used in some block cipher modes, such as Cipher Block Chaining (CBC) - don't worry too much about it! Just make sure it's not the same as the key - and that means totally different, use a separate random number than the key.So the only change I made to test your code was to remove IEncryptor and IDecryptor because they are not in the .NET Framework - what are they?
Michael Howard-MSFT