Encrypting a public Key

  • Thread starter Thread starter Jim Heising
  • Start date Start date
J

Jim Heising

I'm running into some strange behavior using the
System.Security.Cryptography Class and I'm wondering if anyone can
help. Here's my situaion:

I have a file that I want to encrypt so that only users on certain
computers can access it. Here's what I'm doing currently:

1) I encrypt the hidden data with a computer generated Key (MasterKey)
and IV using the RijndaelManaged class.

2) Then for each computer I want to access it, I create a key for that
computer (ClientKey) by creating a SHA256Managed hash of the computer
and domain name.

3) Then I take the original MasterKey and encrypt (RijndaelManaged) it
for each computer with it's corresponding ClientKey.

4) To decrypt the file, the client computer simply uses it's ClientKey
to decrypt the MasterKey, then uses the MasterKey to decrypt the data
in the file.

This works great in principal, but I'm having a fairly simple (but
weird problem).

I can encrypt the main data with the MasterKey (no problem here).
I can encrypt the MasterKey with the ClientKey (no problem here).
I can then decrypt the MasterKey with the ClientKey, sort of (problem
here).

I can decrypt the MasterKey with the ClientKey without getting an
error, but the returned data is not the same as what I sent it. So for
example if the MasterKey is "123456789", when I encrypt it with the
ClientKey and then decrypt back with ClientKey I get "14578" when I
should get back "123456789". The strange thing is that the resulting
decrypted value is similar to the original value, but shorter and not
exactly the same.

The strange thing is that if I encrypt any sort of arbitrary data,
like a string "Test123" and run it through this process it works fine!
So I know my encrypt and decrypt code is working. It only seems to
break when I'm encrypting a Key. I wouldn't think this would matter
since to the encryptor it's all just a byte array (shouldn't matter
what the data is).

So the major question is: Why would I be able to encrypt and decrypt
(with the above process) an arbitrary byte string, but when I try to
encrypt a key (which was generated by a SHA256 hash) I get bogus data
(but no error) when I decrypt it? Am I running into some sort of
mathematical annomoly here?

Any help would be greatly appreciated!
 
Jim Heising said:
I can decrypt the MasterKey with the ClientKey without getting an
error, but the returned data is not the same as what I sent it. So for
example if the MasterKey is "123456789", when I encrypt it with the
ClientKey and then decrypt back with ClientKey I get "14578" when I
should get back "123456789". The strange thing is that the resulting
decrypted value is similar to the original value, but shorter and not
exactly the same.

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
 
I've seen something like this once. It involved encrypting and decrypting
across character definitions.

One application used UTF-8 characters and the other used utf-16. The
difference in character widths (data to represent it, not the drawn
characters) caused the decrypted string to differ only slightly from the
original but, of course, that was enough.
 
mklapp said:
I've seen something like this once. It involved encrypting and decrypting
across character definitions.

One application used UTF-8 characters and the other used utf-16. The
difference in character widths (data to represent it, not the drawn
characters) caused the decrypted string to differ only slightly from the
original but, of course, that was enough.

I suspect it wasn't UTF-8 vs UTF-16 then - those would look entirely
different. Point taken though, and I suspect the same kind of thing.
Hard to know without the code though.
 
There is a more fundamental problem with your scheme: "the secret is the
algorithm itself".

Anybody who knows:
Your steps 1, 2, 3 and 4, as you describe them
The domain and computer name for the destination of the message
can decrypt the message if he can intercept it!!!

To solve this, you have two ways:
Used a shared secret between the parties that communicate (some kind of
password that you enter once on every computer -- and that does not get
exchanged over the network -- or only once at a time where you can be sure
that nobody's spying).
Or, better, use private/public keys.

Bruno.
 
Hi Jim,

I agree with Bruno... your algorithm is flawed. It is impossible to stop a
"man in the middle" attack. In fact, not only can someone in the middle
easily intercept and decrypt the data simply by knowing the destination,
they could change it, and send it along, without the destination knowing
that the changed data didn't come from the original sender.

The fact that you are bothering to encrypt this data tells me that you want
it to be secure.

On each machine that will receive data, create a public/private key pair.
Store the private key in a protected keyring. Send the public key to any
system that will send data.

On the sending side, look for the public key of the partner machine. If
your data isn't huge, encrypt it with the public key. If the data is so
large that encrypting it takes an inconveniently long period of time, you
can create a random number, use it as a session key so that you can use a
less expensive symmetric encryption algorithm, and then only encrypt the
session key with the public key.

Either way, when you are done encrypting the data, generate a hash of it.
Encrypt the hash with your private key. Attach the encrypted hash as a
signature. Send your id, the encrypted main text, and the signature, to the
destination machine.

The destination machine will use your id to look up the public key, or it
will ask you directly, at that time, for your public key.
Use the public key to decrypt the signature. That will give you back a
hash. Calculate your own hash of the cyphertext. If your calculated hash
matches the decrypted hash, then you can be sure that the sender is the
owner of the private key. (no one could have faked that).

Now, using the client machine's private key, decrypt the main block of
encrypted text. (or the session key, if you used the "large batch"
algorithm... in that case, take the session key and decrypt the main block
of encrypted text). Now, discard the session key.

This way, anyone who intercepts the message cannot read it (because the
interceptor doesn't have the client machine's private key) and the
interceptor cannot send a false message to the receiver, since the receiver
will ask the actual sender for their public key and will use that public key
to verify the signature. Since the interceptor doesn't have the private key
of the sender, the receiver cannot be fooled into thinking the counterfeit
data is real.

There are many good books on Public Key Infrastructure. This is a very
light touch on it.

Good Luck,
--- Nick
 
Back
Top