1

I can't decrypt a video file that I encrypted it using Rijndael. Have a look at my encryption routine:

  using (FileStream _streamInput = new FileStream(inputPath,FileMode.Open,FileAccess.Read)) {
            using (FileStream _streamOutput = new FileStream(outputPath,FileMode.Create,FileAccess.Write)) {
                RijndaelManaged _cryptoRM = new RijndaelManaged();
                UnicodeEncoding _encodingUnicode = new UnicodeEncoding();
                byte[] _key = _encodingUnicode.GetBytes(String.IsNullOrEmpty(customPassword)?_mediaPass:customPassword);
                using (CryptoStream _streamCrypto = new CryptoStream(_streamOutput,
                                                                     _cryptoRM.CreateEncryptor(_key,_key),
                                                                     CryptoStreamMode.Write)) {
                    long _bufferLength = _streamInput.Length;

                    if (_bufferLength>_encryptedBlock) {
                        byte[] _encryptedBuffer        = new byte[_encryptedBlock];
                        byte[] _unencryptedBufferBlock = new byte[_encryptedBlock];

                        // encrypted block
                        _streamInput.Read(_encryptedBuffer,0,(int)_encryptedBlock);
                        _streamCrypto.Write(_encryptedBuffer,0,(int)_encryptedBlock);

                        // rest
                        int _readBytesCount = 0;
                        while ((_readBytesCount=_streamInput.Read(_unencryptedBufferBlock,0,_encryptedBlock))!=0) {
                            _streamOutput.Write(_unencryptedBufferBlock,0,(int)_readBytesCount);
                        }
                    }
                    _streamCrypto.Dispose();
                }
                _cryptoRM.Dispose();
                _streamOutput.Dispose();
            }
            _streamInput.Dispose();
        }

And this is my decryption routine:

        using (FileStream _streamInput = new FileStream(inputPath, FileMode.Open, FileAccess.Read))
        {
            using (FileStream _streamOutput = new FileStream(outputPath, FileMode.Create, FileAccess.Write))
            {
                 RijndaelManaged _cryptoRM = new RijndaelManaged();
                 UnicodeEncoding _encodingUnicode = new UnicodeEncoding();
                 byte[] _key = _encodingUnicode.GetBytes(PrepareEncryptionKey(String.IsNullOrEmpty(customPassword)?_mediaPass:customPassword,""));


                try
                {

                        using (CryptoStream _streamCrypto = new CryptoStream(_streamInput, _cryptoRM.CreateDecryptor(_key, _key), CryptoStreamMode.Read))
                        {
                            try
                            {
                                int _readBytesCount = 0;


                                //encrypted block
                                byte[] _buffer = new byte[_encryptedBlock];
                                byte[] _bufferUnencrypted = new byte[_encryptedBlock];

                                int decrypt_length = _streamCrypto.Read(_buffer, 0, _encryptedBlock);                                   
                                _streamOutput.Write(_buffer, 0, decrypt_length);

                                // rest
                                while ((_readBytesCount = _streamInput.Read(_bufferUnencrypted, 0, _encryptedBlock)) != 0)
                                {
                                    _streamOutput.Write(_bufferUnencrypted, 0, _readBytesCount);
                                }
                            }
                            catch { }
                            _streamCrypto.Dispose();
                        }

                }
                catch { }
                _cryptoRM.Dispose();
                _streamOutput.Dispose();
            }
            _streamInput.Dispose();
        }

Other points: - No error is being thrown but the video is simply not playing. - The size of the decrypted file is the same of the encrypted file.

EDIT:

 private static string PrepareEncryptionKey(string key, string part)
    {
        if (part == "")
        {
            if (key.Length != 8)
            {
                return key.PadRight(8, '~');
            }
            else
            {
                return key;
            }
        }
        else
        {
            if (key.Length != (8 - part.Length))
            {
                if (key.Length > (8 - part.Length))
                {
                    return key.Substring(0, (8 - part.Length)) + part;
                }
                else
                {
                    return key.PadRight((8 - part.Length), '~') + part;
                }
            }
            else
            {
                return key + part;
            }
        }
    }
gtamorim
  • 140
  • 8
  • 1
    You say the size is same, what about the content? if you compare input before encryption with result after decryption? is it also same or different? – mybrave Feb 14 '13 at 12:29
  • Try to set _streamInput.Position = 0; – Andrew Feb 14 '13 at 12:48
  • I haven't really evaluated the content. Both files (encrypted and "decrypted") aren't playable. – gtamorim Feb 14 '13 at 13:00
  • _streamInput.Position didn't help. If you check the code you'll see the during encryption only the first block is being encrypted. – gtamorim Feb 14 '13 at 13:02
  • 1) You're not checking the return value of `Read`. It probably works due to your length check, but I'm not sure if it's guaranteed to work. 2) you're using the password directly as key and IV 3) You're not encrypting the file, only part of it oO doesn't look very secure. 4) Ciphertext is longer than Plaintext due to padding. I don't think your code takes that into account. You need to disable padding – CodesInChaos Feb 14 '13 at 13:38
  • Thanks, @CodesInChaos. Do you think I would be able to retrieve the files already encrypted with this approach? – gtamorim Feb 14 '13 at 13:40
  • 1) What's the value of `_encryptedBlock`? 2) Is the size of the encryption file the same as the size of the original size? You wrote that *decrypting* doesn't change the size. But does *encrypting* change the size? – CodesInChaos Feb 14 '13 at 14:54
  • 1) _encryptedBlock = 30535; 2) Decrypting with the aforementioned routine did not change the size, but also did not "decrypt". The "original" file is actually a stream of data acquired from the camera. – gtamorim Feb 14 '13 at 15:01
  • Understand there should be three versions of the file: 1/ original, 2/ encrypted, 3/ decrypted. Is the 1/ equal to 3/? – mybrave Feb 14 '13 at 15:07
  • Maybe stupid question but why is there used in encryption method byte[] _key = _encodingUnicode.GetBytes(String.IsNullOrEmpty(customPassword)?_mediaPass:customPassword); and in decryption byte[] _key = _encodingUnicode.GetBytes(PrepareEncryptionKey(String.IsNullOrEmpty(customPassword)?_mediaPass:customPassword,"")); ? – mybrave Feb 14 '13 at 15:08
  • @mybrave I was having a problem with the size of the key. I used the method PrepareEncryptionKey just to make sure the size is correct. Regarding the versions of the file, I only have the encrypted file (2). I don't have the original file because the file is encrypted during its creation (in fact there is a temp file but it is securely deleted during the process and I am not able to retrieve it). – gtamorim Feb 14 '13 at 15:15
  • Don't call `Dispose()` directly - your `using` statements take care of that for you. – Jesse C. Slicer Feb 14 '13 at 15:33
  • @user2022280 looks like you may decrypt with different key than you use for encryption. Can you do unit test with the same code and without deletion of the original file and keys used before? – mybrave Feb 14 '13 at 16:13
  • @mybrave Yes, I can do that. But still don't know where to go from there. Thanks for any other insights. – gtamorim Feb 14 '13 at 16:25
  • @user2022280 - this way you can confirm if you have problem in the code or just use different key for encryption. At least in one test please test 100% same key - without any padding etc. – mybrave Feb 14 '13 at 16:32
  • @mybrave I see. I'll give it a go. Thanks. But I am really concerned over the decryption part. I need to decrypt this one block, but it seems like I am reading the wrong part of the file. – gtamorim Feb 14 '13 at 16:53

1 Answers1

1

It seems your both methods needs fixes:

1/ encrypt part - you cannot write output data directly to _streamOutput but to _streamCrypto. Otherwise you will write exactly what you have taken from input file. As per your original code, you would encrypt just first block of data.

while ((_readBytesCount = _streamInput.Read(_unencryptedBufferBlock, 0, encryptedBlockSize)) != 0)
{
    _streamCrypto.Write(_unencryptedBufferBlock, 0, (int)_readBytesCount);
}

2/ decrypt part - you cannot read from input stream directly but from _streamCrypto

while ((_readBytesCount = _streamCrypto.Read(_bufferUnencrypted, 0, encryptedBlockSize)) != 0)
{
    _streamOutput.Write(_bufferUnencrypted, 0, _readBytesCount);
}

3/ PrepareEncryptionKey method should be used in both encryption and decryption method. This will ensure you have it same in both methods.

mybrave
  • 1,662
  • 3
  • 20
  • 37
  • 1. That was the exactly intention of the code: to encrypt only the first block. The problem is I can't get it decrypted. Try by using the encryption method above to a file and then try to decrypt it. I have some files already encrypted with this method but I need to get them decrypted. Thanks for your aid, anyway. – gtamorim Feb 18 '13 at 10:32
  • Ok, then I would try to encrypt one more, check if after encryption it is of same size, and if your decryption method decrypts it correctly. you can do comparison of original file and file you receive after decryption. if they differ you either use differnt key/IV combination or have error in your code which you will need to debug. – mybrave Feb 25 '13 at 09:44