Search code examples
c#encryptionfilestreamcryptostream

How to start from arbitrary index (offset) in cryptoStream readByte()


I'm using the code bellow to Encrypt and Decrypt a file:

// Encryption

UnicodeEncoding UE = new UnicodeEncoding();

byte[] key = UE.GetBytes("password");

FileStream fsCrypt = new FileStream("cryptFile", FileMode,create);

RijndaelManaged RMCrypto = new RijndaelManaged();

CryptoStream cs = new CryptoStream(fsCrypt,
                RMCrypto.CreateEncryptor(key, key),
                CryptoStreamMode.Write);

FileStream fsIn = new FileStream("FileName", FileMode.Open);

int data;
while ((data = fsIn.ReadByte()) != -1)
      cs.WriteByte((byte)data);

fsIn.Close();
cs.Close();
fsCrypt.Close();

// Decryption

UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes("password");

FileStream fsCrypt = new FileStream("filename", FileMode.Open);

RijndaelManaged RMCrypto = new RijndaelManaged();

CryptoStream cs = new CryptoStream(fsCrypt,
RMCrypto.CreateDecryptor(key, key),
CryptoStreamMode.Read);

int data;
while ((data = cs.ReadByte()) != -1)
     memorystream.WriteByte((byte)data);

It works well, without any problem!

For some reasons I've added 10 bytes at the first of the encrypted file! Actually I've created a 10 bytes file (the file size is EXACTLY 10 Bytes), then I've appended the encrypted file to this file.

Note that the 10 bytes file is not encrypted, and is created using simple filestream, and it could be read in notepad.

Now in decryption code, how could I eliminate the first 10 bytes and decrypt remain data in the file?

I've tried to call ReadByte() for 10 times, and then goto the WHILE part and decrypt file, but it doesn't work and I get length invalid exception.

Thanks in advance.


Solution

  • Posting my comment as an answer as requested.

    You say

    I've tried to call ReadByte() for 10 times, and then goto the WHILE part and decrypt file, but it doesn't work and I get length invalid exception.

    but you don't say exactly which stream you call ReadByte() 10 times on, and when exactly you call it.

    Make sure you're calling it on fsCrypt before you instantiate the new CryptoStream.

    Note also that that you can probably just call fsCrypt.Position = 10; or fsCrypt.Seek(10, SeekOrigin.Begin), instead of reading 10 dummy bytes, since FileStream supports seeking.

    For example:

    byte[] key = Encoding.Unicode.GetBytes("password");
    
    FileStream fsCrypt = File.OpenRead("filename");
    fsCrypt.Position = 10; // Skip the 10 useless bytes at the start
    
    RijndaelManaged rijndaelManaged = new RijndaelManaged();
    
    // Disposing CryptoStream will also dispose the FileStream passed to it
    using (CryptoStream cryptoStream = new CryptoStream(fsCrypt, rijndaelManaged.CreateDecryptor(key, key), CryptoStreamMode.Read))
    {
        cryptoStream.CopyTo(memoryStream);
    }
    

    As an aside: DO NOT USE THE KEY AS THE IV!

    The IV needs to be different every time you encrypt something, but can be public. A common technique is to randomly generate an IV every time you want to encrypt something, and put it as the first N bytes of the encrypted stream. When it comes to decrypting, read the first N bytes of the encrypted stream yourself (before creating the CryptoStream), set that as the IV, open the CryptoStream, and read the rest.