Decryption fails after appending to a file encrypted with a crypto stream - c#

Hoping you can help out here. I'm creating a file an appending lines to this file using a Crypto stream.
If I write out all the lines at once then the file will encrypt/decrypt correctly.
But if I open the file in append mode, append a line, close then file. Then only the 1st line decrypts correctly, the other lines return back rubbish.
I am wondering if this is the correct behaviour. I'm trying to build up a text file of encrypted details users enter over the course of a day; and then batch processing them at the end of a day.
The overhead of decrypting and encrypting the whole file just to add a single line to it would seem to be excessive as I could end up with 1000's of lines over the course of a day.
I'm using the excact same Crypto Provider with the same Initialisaion Vector and key on all access to the file?
Am I doing something wrong or is it not possible to append to an encrypted file?
Cheers
Noel

Yes, this is expected behavior. One thing you can do is encrypt each record (text line) separately AND add a prefix that indicates beginning of the block and it's length. Then when reading from the file, read the prefix, check the record length and load the record. Repeat for each record.

I suspect the crypto you're using is a stream or chained cipher - meaning the output from one encrypted block is used to modify the next block. Directly appending to this kind of data and then attempting to decrypt the lot will not work because the dependency between the blocks will be broken.
A simple way to fix it is to add a marker or save some data for the offset+length of each record in the file. When you come to do the batch processing, you'll need to reset the CryptoProvider for each record.

Related

Creating a file that can be only used by my program. How do I differ it from other programs' files?

I create my file using File.WriteAllBytes(). Byte[] that is passed to File.WriteAllBytes() is encrypted by algorithm of my own. You need password that was used when file was encrypted (user of the program knows the password) to decrypt it. But when some file is opened by my program using File.ReadAllBytes() there are 3 situations:
File that is being opened is my program's file and user knows the password to open it.
File that is being opened is my program's file but user doesn't know the password to open it.
File that is being opened is not my program's file.
First one is easy to handle. 2nd and 3rd are same for my program because my program doesn't know the difference between encrypted byte[] and byte[] of some random file.
How do I differ these situations? I was thinking of adding some sequence of bytes to the end or beginning of byte[] before passing it to File.WriteAllBytes(). Is that safe? How do modern programs differ their files from other files?
You can give your file some structure before encryption, and check that the structure is there after decryption. If the structure is not there, it's not your file.
For example, you could compute a check sum, and store it in the first few bytes prior to the "payload" block of data. Encrypt the check sum along with the rest of the file.
When you decrypt, take the payload content, and compute its check sum again. Compare the stored result to the computed result to see if the two match. If they don't match, it's not your file. If they do match, very good chances are that it is your file.
This is not the only approach - the structure could be anything you wish, from placing a special sequence of bytes at a specific place to using a specific strict format (e.g. an XML) for your content, and then validating this format after the decryption.
[the file is] encrypted by algorithm of my own.
Be very careful with security through obscurity: coming up with an algorithm that is cryptographically secure is an extremely hard task.
Many many file format use "Magic numbers" in front of the file to determine their types. Use the first ... 4 bytes, write a custom sequence it it then read it when you load the file.

Find and replace data in file (without loading the entire thing)?

I want to replace some data in a file, however I do not know exactly where this 200MB file would contain it. Is it possible to find (and replace them with something else) these values without loading a 200mb+ file into the memory?
Searching the file is not a problem. What you need is to work with the FileStream which is available via File.Open method. You can read through the file up to the bytes you need to replace.
Problem arises when you need to insert something. The FileStream allows you to overwrite some or all of the file contents from a particular byte forth and to append new content to its end but it does not allow you to insert data in the middle of the file. In order to overcome this problem you are going to need a temporary file. If you agree to that you could do the following:
Open the FileStream on the original file.
Create a temporary file that will hold the draft version.
Search through the original file and copy all "good" data into temporary file up to the point where modifications are to be made.
Insert modified and new data into the temporary file.
Finish up the temporary file with the remaining "good" content from the original file.
Replace the original file with the temporary one.
Delete the temporary file.
You could use the Path.GetTempFileName method for convenient way of utilizing a temporary file.
P.S. If you modify an exe then you probably make replacements on text constants and you neither need to insert new bytes nor to remove any. In such a case you do not need to bother with the temporary file and the FileStream is all you need.
P.P.S. Working with the FileStream you decide on size of a buffer you read from file and write back. Keep in mind that this size is the tradeoff between memory consumption, I/O performance and complexity of your code. Choose wisely. I would make it per-byte for the first time and try to optimize increasing the buffer to say 64k when it works. You can count on the FileStream to buffer data; it is not performing disk I/O each time you request another byte from it. If you dive into buffering yourself then try not to fragment the Large Object Heap. The threshold for .NET 4.5 is 85000 bytes.
Just a thought, how about reading your file line by line or may be in chunk of bytes and see in each chunk if u have the data that needs to be replaced. Also while reading make sure get the file pointer till where you have read the file so that when u find the match then u can go back to that location and over write those exact bytes which u have targetted.

Editing specific line of text file in asp.net?

I have to change the specific line of the text file in asp.net.
Can I change/Replace the text in a particular line only??
I have used the replace function in text file but it is replacing text in entire file.
I want to replace only one line specified by me.
Waiting for the reply..
Thanks in advance..
File systems don't generally allow you to edit within a file other than directly overwriting byte-by-byte. If your text file uses the same number of bytes for every line, then you can very efficiently replace a line of text - but that's a relatively rare case these days.
It's more likely that you'll need to take one of these options:
Load the whole file into memory using File.ReadAllLines, change the relevant line, and then write it out again using File.WriteAllLines. This is inefficient in terms of memory, but really simple to code. If your file is small, it's a good option.
Open the input file and a new output file. Read a line of text at a time from the input, and either copying it to the output or writing a different line instead. Then close both files, delete the input file and rename the output file. This only requires a single line of text in memory at a time, but it's considerably more fiddly.
The second option has another benefit - you can shuffle the files around (using lots of rename steps) so that at no point do you ever have the possibility of losing the input file unless the output file is known to be complete and in the right place. That's even more complicated though.

Read and Encryption of a PDF file in c#

I want to read a the content of a PDF file and encrypt the content using AES256 encryption and post the content(encrypted) as a base64 string.
for that i have 2 solution
read the content using a stream reader(PDF formated data) the encrypt the content and the base64 encoding, Finally send the encrypted string
Read PDF content and convert it into text then encrpt and then send
Which is the best method, If i use first method then there will be any problem for failure
I need your opinion Please help me
Your first method seems absolutely fine and I would certainly go for that approach. What you are essentially doing is simple transmitting a file from one machine to another.
If you consider this without encryption all you should be aiming to do would be to send the file stream exactly the same as you read it, this ensures the receiver gets the file in it's original state and can reliable open the file as it will be in the exact same format as it started.
Now when we consider adding encryption, all we are doing is change the raw binary data of the file. As long as we decrypt the file at the other end using the same key parameters we can be sure that we will still have the same original raw file data we started with (assuming we don't get any data loss during connection - you could add a hash check for this if desired, for example)

Computing MD5SUM of large files in C#

I am using following code to compute MD5SUM of a file -
byte[] b = System.IO.File.ReadAllBytes(file);
string sum = BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(b));
This works fine normally, but if I encounter a large file (~1GB) - e.g. an iso image or a DVD VOB file - I get an Out of Memory exception.
Though, I am able to compute the MD5SUM in cygwin for the same file in about 10secs.
Please suggest how can I get this to work for big files in my program.
Thanks
I suggest using the alternate method:
MD5CryptoServiceProvider.ComputeHash(Stream)
and just pass in an input stream opened on your file. This method will almost certainly not read in the whole file in memory in one go.
I would also note that in most implementations of MD5 it's possible to add byte[] data into the digest function a chunk at a time, and then ask for the hash at the end.

Categories