views:

100

answers:

5

See the title for question.

In a nut shell, what I am trying to do is encrypt some data with the seed (keyword) provided by the user. Is there a way to know that the data has been decrypted wrong, or in other words that the seed is wrong?

Using .net 2.0, C#

Thanks!

+6  A: 

It's quite normal to make a hash part of the encrypted data. Say, you have some data you want to encrypt. You then create an MD5 hash of this and add this to the end of the data. Then, when you decrypt it, you take the hash of the end of the encrypted data and verify that the hash hasn't changed.

Pieter
But this doesn't help determine if the decryption was successful or not.
Les
Sure it does. When the hashes don't match, the decryption was not successful. What you'd be doing here is checking whether the data has been tampered with. Because the data is encrypted (including the hash), nobody can fake the hash. So, when the hashes match, you know for sure that the data has not been tampered with. Some systems, like EAS, incorporate such a mechanism. The above description is such a mechanism, which you can implement yourself.
Pieter
+1 @Pieter, I think I misread your answer earlier. I agree with you that if you create a hash digest of the original message and include it at the end, or some agreed upon spot, and then encrypt the entire message and hash, then the decrytor could know (to near certainty) that decryption was successful by recomputing the hash and checking to see if it matches. In other words, you can only tell that decryption is successful if the original unencrypted data has some agreed upon built in check value.
Les
A: 

The formal way to resolve that issue is to use a key wrap around the key (which would itself be encrypted). This is because you should only trust entirely private keys, not keys which are given to you. If you were to use an invalid key for encrypting data, then things go bad.

There are no built in routines (that I know of) that perform key wrapping in .NET, but in essence you can achieve the same thing by prefixing and postfixing the actual key with a string of 16 (or whatever your blocksize is) 'A' characters. When you decrypt the key you ensure that it is pre & postfixed with 'A' and flag it as an error if not.

If you have less formal requirements then another option is to use the key to decrypt a string which is known to be encrypted with the correct key. If once you've decrypted that string you get an unexpected result, then flag it as an error.

PaulG
Hash of complete data would be slightly better protection than a hash of a string: more data needs to be decrypted to verify validity of the password during bruteforce or dictionary attack.
Eugene Mayevski 'EldoS Corp
@Eugene. Is that reply for Pieter? I'm not talking about hashing anything.
PaulG
@PaulG no, it was leftover from me editing the text. It doesn't matter if it's a hash of the string or a string - the more the attacker needs to decrypt the better. Having to decrypt only the string will speed up the attack.
Eugene Mayevski 'EldoS Corp
@Eugene. If your security relies on being able to withstand a brute force attack for 50 lifetimes instead of 49.9 lifetimes, yes - you have a point.
PaulG
And hashing the whole plaintext has the advantage that the attacker cannot replace part of the cyphertext. And I don't really understand what you are trying to achieve.
CodeInChaos
@PaulG First of all, for average data the difference is not 2%, but 20 or even 200%. Second, dictionary attack takes much less than a lifetime. If it were a lifetime, companies like Elcomsoft would go bankrupt, and they stand quite well.
Eugene Mayevski 'EldoS Corp
@Eugene. Got a source for any of these stats? Just cycling through the keys for a 256bit key at a billion billion keys per second would take 3×10^51 years (source:http://en.wikipedia.org/wiki/Brute_force_attack).
PaulG
@PaulG time to refresh your cryptography knowledge. One doesn't need to test all keys in order to get the result. That number of years is needed for full test. That's first. The second is that the number is for one processor. Elcomsoft stuff uses GPUs that perform lots of calculations in parallel. The third is that one doesn't need to decrypt the data. One needs to decrypt encrypted session key. And while the session key can be 256 or 512 bytes, in real life the key used to encrypt the session key is much weaker.
Eugene Mayevski 'EldoS Corp
@Eugene. Sorry to be blunt, but half of 3*10^51 years is still a pretty long time. That time isn't 'for one processor', but for a device running through a billion bilion keys per second. I also don't know of any 256 *byte* keys, and no-one mentioned session keys. Your profile says you're employed by a specialist in security, so I'm keen to learn - show me the links of **anyone** offering to brute force AES.
PaulG
+4  A: 

Depends on your algorithm specifics. stream ciphers (like RC4) will not by themselves be able to detect any tampering. Block ciphers (AES) may detect some tampering because of the block padding algorithms (PKCS#5). This padding check is what causes ICryptoTransform.TransformFinalBlock` to throw exception that the decryption failed, but this detection is not cryptographically secure (in the worst case is 1/256 chances of not detecting tampering, if padding is one byte). This is not an omission of the .Net implementation, is a fundamental problem with using all encryption algorithms.

So given that the decryption operation itself basically cannot detect tampering (or the use of a bad key/IV) the solution is to add a digest of the message in the message. The industry standard is to use an HMAC digest, and have the key derivation process produce enough key material for the key/IV and HMAC secret (this is how TLS/SSL do it, which is pretty much 'industry standard', see 6.3 Key calculation of the RFC linked). The decryption step decrypts the message and then computes the HMAC of the message, comparing it with the original digest. If they match, the decryption was successful (correct key/IV used) and the message was not tampered with.

Remus Rusanu
A: 

One brute force way - depending of what are you doing with your data... Push it to any algorithm that expects it and see if it crashes. I have encrypted binary serialized data that I deserialize that way. Binary formatter throws an exception if data is decrypted wrongly and turned to noise.

Daniel Mošmondor
A: 

If you want to prevent tampering of the message use a HMAC.

Regular encryption doesn't tamper proofs messages. Learn from asp.net's team mistake, and put the extra validation in place - see how the asp.net padding oracle vulnerability related to getting different levels of access.

If you don't put the extra validation, it's likely you'll expose information that an attacker may use to try to game the system.

eglasius