See the title for question.
In a nut shell, what I am trying 开发者_StackOverflow社区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!
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.
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.
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.
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.
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.
精彩评论