Using CryptoStream

J

jp2msft

I have a routine that can encrypt or decrypt a file.

What I want is to add a small buffer (the public key) to the start of the
file. This way, I can check a file before performing my operation on it to
ensure I am not about to encrypt something that has already been encrypted.

Unfortunately, the CryptoStream does not allow me to position the starting
position.

I can write my key to the new buffer, but I can not add the encrypted data
to it afterwards.

Is there a way around this? Should I encrypt the file and append the file
with my key? I suppose I could check the end of each file for my encryption
key, but I have not tested that - and adding it to the first of the file
would certainly be faster!

Here is my chopped down (untested) code:

// int m_MB = 1024 * 1024; // 1 MB buffer
// ICryptoTransform m_Decrypter
// byte[] m_bEncHeader ... is my public key!
// byte[] m_HeadBuf = new byte[m_bEncHeader.Length];
// bool BufferMatch(byte[] A, byte[] B) ... returns true if each byte matches
if (File.Exists(file) == true) {
int len = -1;
string activeFile = "~tmp";
byte[] buf = new byte[m_MB];
FileStream m_copyFS = null;
FileStream m_workFS = null;
File.Copy(file, activeFile, true);
m_copyFs = new FileStream(activeFile, FileMode.Open, FileAccess.Read);
len = m_copyFs.Read(m_HeadBuf, 0, m_HeadBuf.Length);
if ((0 < len) && (BufferMatch(m_HeadBuf, m_bEncHeader) == true)) {
m_workFs = new FileStream(file, FileMode.Create, FileAccess.Write);
CryptoStream cs = new CryptoStream(m_workFs, m_Decrypter,
CryptoStreamMode.Write);
cs.Position = len; // this line throws my exception
do {
len = m_copyFs.Read(buf, 0, m_MB);
cs.Write(buf, 0, len);
} while (0 < len);
cs.Close();
}
m_copyFs.Close();
m_workFs.Close();
File.Delete(activeFile);
}
 
J

jp2msft

Hi Pete!
What happens if someone has data that starts out just like your "already
been encrypted" header? Or worse, what happens if someone _intentionally_
includes such a header in order to circumvent your encryption (by causing
your code to not encrypt something that should have been encrypted?).

I don't know. This is the only way I know of to tell if any given file type
(Bitmap, MS Word document, ZIP file, etc) is already encrypted or not. I am
physically replacing the existing file with the encrypted version (FILEA.EXT
gets turned into a new FILEA.EXT). If you have a better idea of how to check
that this is some file that I have already encrypted, I'd be happy to hear it.
Why would adding it to the beginning of the file be faster? Assuming the
data you want to append is fixed size, then using the file length and the
size of the data, it's trivial to read from that specific section of the
file to see what's there.

Ok... it would be faster for me to code! :) I'm sure the program doesn't
care what I'm doing!
 
P

Peter Morris

As far as I know, the only reliable way to know for sure that a file has
been encrypted is to try to decrypt it. If you get valid output, then it
was. Otherwise, it wasn't.

True, but it would be better if it didn't even try to decrypt it if it can't
possibly be encrypted (because the signature isn't there), it's faster. I
would recommend having the signature at the start, something long enough to
be unlikely to be encountered accidentally (like a constant GUID value), and
to additionally handle the possibility that the file is corrupted.
 
P

Peter Morris

To do this (years ago in Delphi, so don't ask for source code) I wrote a
SubStream class.

It took a Stream as a parameter in its constructor + an integer indicating
the offset. I just overrode the Position / Length etc to return
InnerStream.Position - Offset, and InnerStreamLength - Offset. In the Seek
method I just adjusted the value passed by the user of my class by the
Offset.

The wrapper made it look like you were working on a whole stream, whereas in
fact you are working on a subset of it. I used it to implement a signed
stream :)
 
A

Anthony Jones

Peter Morris said:
True, but it would be better if it didn't even try to decrypt it if it
can't possibly be encrypted (because the signature isn't there), it's
faster. I would recommend having the signature at the start, something
long enough to be unlikely to be encountered accidentally (like a constant
GUID value), and to additionally handle the possibility that the file is
corrupted.


When handling the possibility that the file is corrupt ask yourself would
you bother adding such a thing if you were not encrypting, if the answer is
no then don't bother now. If you do want to bother then you'll need to
place that at the end of the stream not the beginning.
 
P

Peter Morris

When handling the possibility that the file is corrupt ask yourself would
you bother adding such a thing if you were not encrypting, if the answer
is no then don't bother now.

Usually my answer is "Yes". I typically put in exception handling and throw
exceptions when something expected goes wrong etc. I'd just prefer the
check to fail at the start rather than part of the way through.
If you do want to bother then you'll need to place that at the end of the
stream not the beginning.

Doesn't really make a difference that I am aware of, except at the beginning
you don't need to seek.
 
A

Anthony Jones

Peter Morris said:
Usually my answer is "Yes". I typically put in exception handling and
throw exceptions when something expected goes wrong etc. I'd just prefer
the check to fail at the start rather than part of the way through.

I generaly assume the infrastructure I'm using is already robust enough for
most things.
Doesn't really make a difference that I am aware of, except at the
beginning you don't need to seek.


Well the item you need to add the store that would verify the stream isn't
corrupt would be some form of hash. The value of that hash would only be
know once you've read all of the input stream. If you place this hash at
the start of your output stream you can't write any of your output stream
until you've read all the input. If you place the hash at the end of the
output stream you can read and write in chunks whilst building the hash,
when all input has been read and remaining output is flushed tag on the
hash.
 
P

Peter Morris

Well the item you need to add the store that would verify the stream isn't
corrupt would be some form of hash. The value of that hash would only be
know once you've read all of the input stream. If you place this hash at
the start of your output stream you can't write any of your output stream
until you've read all the input. If you place the hash at the end of the
output stream you can read and write in chunks whilst building the hash,
when all input has been read and remaining output is flushed tag on the
hash.

Ah, misunderstanding then. You are talking about a hash to determine the
data *is* valid, whereas I am talking about a signature at the start of the
file to indicate the data cannot possibly be valid. My goal was to
determine the file is "definitely not one of my encrypted files" quickly so
that no additional time is spent trying to decrypt it when it will
definitely fail.
 
J

jp2msft

Thanks everyone for the help!

Just an FYI: I use a Hash generator to create the Public Key that is
appended to the end of every file that is encrypted.

True, some clever person might realize that all of my encrypted files end in
the same sequence, then discover that it is the Public Key.

However, unless they have the randomly generated Initialization Vector that
I keep stored in my application, the files will be pretty difficult to figure
out.

Maybe not the most secure, but that's all I'm giving my client (which is a
buddy of mine that probably won't be paying me anything anyway).

Regards,
~Joe
 
P

Peter Morris

You said:
I said

So I was merely saying that a good additional thing to do is to sign the
start of the file so that
A: You know it has already been encrypted
B: You don't bother spending time trying to decrypt something that cannot
possibly be encrypted

Are you the original poster?

I think you know I am not, on account we have different names and different
IP addresses.
If so, you're making conflicting statements. The original post said you
are trying to avoid _encrypting_ something that's already been encrypted.
If you're not the original poster, then it seems to me that your replies
(which seem to imply that you are the OP) are confusing the issue.

Actually it was you who mentioned decrypting. I only said that the OP
should consider attaching a signature to the front of the file in order to
sign it. So if you think the thread started to diverge too much or conflict
as a result of switching from encrypting to decrypting I think you need to
find a mirror before casting an accusing finger :-D

In any case, it's true. For a great number of algorithms or goals, code
that does it wrong can be written such that it executes much faster than
code that does it right.

When the Enigma machine was used during WWII it was considered unbreakable
by the Germans because there were just so many possible combinations. The
automated approach used to break it at Bletchley park wasn't to find which
settings the Enigma *could* be using but to find a quick process of
eliminating all of the combinations it *couldn't* be. Anything that was
left was investigated manually.

You are implying my approach is wrong, that really isn't very polite of you.
You suggested decrypting it was the only accurate way of determining whether
or not the file is already encrypted. I merely suggested what I consider is
an enhancement, by ensuring that the decryption fails immediately due to a
missing signature rather than potentially getting some considerable way into
a large file before realising it is invalid. My approach wont help in all
cases, but in 99.9% of them it would make it faster. Please do feel free to
educate me and prove me wrong conclusively though, I like being educated.
 
P

Peter Morris

You are wrong about what I know and don't know. Several people that use
this newsgroup post under a variety of email addresses.

I don't believe for one second that you thought I was the original poster.
What's the difference? Either way you have to look at something in the
stream. The "time spent" trying to decrypt something that could be known
to not be encrypted some other way is hardly a problem. As soon as the
decrypted stream can be recognized as invalid, you're done.

So, at some point you need to write a plugin for Windows Explorer to show a
small padlock icon against each encrypted file. You open a folder
containing family photos, there are approximately 50 in there, all about 1MB
in size. Which approach is better?

A: Scan the first 16 bytes of each file for a GUID signature.
B: Check to see if it is possible to decrypt the whole file.

I am pretty sure that you would say something along the lines of "He didn't
say he needs to do that", but planning for the future is one of the things
that programmers are supposed to do as long as it doesn't take too much
work. I reckon 30 mins max to get a signed stream (I know, I've done it
before). 30 minutes well invested in my opinion. So, to answer your
question, *that* is the difference.
 
P

Peter Morris

It is unfortunate that you have decided to take such an unreasonable
attitude.

I don't have an attitude, and I don't feel I am being unreasonable either.
You will not be able to find a single post of mine in which I wrote
something I knew to be untrue

This statement really made me laugh :) On the one hand you think it is
unreasonable that I expect you to know that I was not the original poster
due to two facts that are readily available to anyone who cares to
right-click the messages and select "properties"

A: Different name
B: Different IP address

and then you go on to think it is reasonable for me to know what is going on
in your mind? How on Earth would I know if you had ever posted information
you knew to be untrue? I cannot read your mind. I really hope you are able
to look at this and see it yourself :)

don't know why it is you think I'd lie to you about something like that,

I just got the impression you were being arsey with me....

Are you the original poster? If so, you're making conflicting
statements. The original post said you are trying to avoid _encrypting_
something that's already been encrypted. If you're not the original
poster, then it seems to me that your replies (which seem to imply that
you are the OP) are confusing the issue.
<<<

"Are you the original poster? If you are then you aren't making any sense,
if you aren't then you need to shut up". If you were to have told me that I
was confusing *you* that's fine, telling me I am "confusing the issue" is
akin to telling me that I am confusing everyone, and that is what got my
back up. You are not the representative of the popular opinion of the
group.

but until you're ready to treat me and others with a bit more respect, I
don't see any need to continue this discussion.

Well I'm sorry you feel I have treated you with disrespect. None was
intended at all. However please do look at the kind of statements you
yourself have made. Excluding the example I have illustrated above you have
also said

01: "I'm _saying_ that your approach is wrong, no implying about it."
My reading of this statement is 100% that you are being rude to me. You are
not saying that "in your opinion" I am wrong, you are making it sound as if
it is a fact, which it certainly isn't. You have your opinion, I have mine,
other people have their own. I hope you can see here for example how you
have been deliberately rude to me.

02: "but until you're ready to treat me and others with a bit more respect"
Here again you are portraying yourself as the speaker of the people, the
person who represents the opinion of the majority. Not only have I not
knowlingly been rude to you, but I don't believe I have been rude to anybody
else either, and yet here you are telling me that I have been disrespectful
to you and also other people.

To be quite frank I respect your opinion on many technical things, I
appreciate your feedback on posts and also the technical depth in which you
are prepared to go in order to help myself and other people. However, I
feel that you not only post things which can be condesceding but you also
read insult where there is none.

Back on topic: The approach I suggested (quickly eliminate the impossible)
helped to quicly break thousands of encyphered Nazi messages during world
war two. It was hardly my own brain child, and has quite a good track
record. I am still interested in whether or not you still feel your
approach of always trying to decrypt the entire file is the ideal approach
to take in light of the scenario I painted, which in my opinion is a very
probable future request. I agree with you that you can only tell if the
file *definitely is* encrypted by fully decrypting it, but my suggestion all
along has been to quickly determine that the file *certainly isn't*
encrypted. In no way does my suggestion contract yours, or exclude it, it
merely complements it. I would be much more interested in persuing this
part of the thread for the benefit of everyone.


Regards
 
A

Anthony Jones

Peter Morris said:
I don't have an attitude, and I don't feel I am being unreasonable either.
....
etc. etc.


Lads this getting boring. If you insist on continuing with this petty
bickering could you please liven it up a bit and keep each post short, it'll
be more interesting and give the rest of us a laugh.

Ta.
 
P

Peter Morris

Lads this getting boring. If you insist on continuing with this petty
bickering could you please liven it up a bit and keep each post short,
it'll be more interesting and give the rest of us a laugh.

As I said at the end, I'd be much more interested in continuing the
technical part of the thread.
 
P

Peter Morris

Oh man, get over yourself! You were rude to me, it is unquestionable. I
had the decency to apologise for making you feel like I was being
disrespectful (which, if I did, was unintentional) and all you can
concentrate on is bitching more? Just re-read this thread and look at your
attitude!

"Bzzzzt", wth is that all about? You honestly don't think that is not rude?
If your social skills are that bad I strongly suggest you stay at home!

In the past you have said I was wrong, I have asked why, you have shown me,
I have accepted it; I can live with it. All I have seen in this thread is
that when you say someone is wrong and cannot then show why you resort to
being rude and avoiding the point. It's really immature, and a big shame.
I've had enough.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top