问题
I'm working on chat room that encrypt messages for more than one users and each user might have different encryption and key/password. The user's key won't work with all the message, therefore; return errors.
var message ="secret message";
var encrypted = CryptoJS.AES.encrypt(message, "Secret Passphrase");
try {
var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase123").toString(CryptoJS.enc.Utf8);
if (decrypted.length > 0) {
alert(decrypted);
} else {
alert("false");
}
} catch(e) {
alert("false");
}
I'm currently catching the error, but sometimes the decryption returns with jumbled up letters and symbols. The current way I'm doing this is not efficient. Is there a better way?
回答1:
What is needed it authenticated encryption, see Wikipedia.
Essentially HMAC the encrypted data with the encryption key and append the result to the encrypted data.
Prior to decryption HMAC the encrypted data with the decryption key and compare to the appended HMAC value. (Use a constant time comparison function.)
回答2:
Put a prefix at the beginning of each message, e.g.
encrypt("ABCD" + message);
Then when you decrypt, check if the result begins with "ABCD"
.
This isn't foolproof, since it's possible that an incorrect decryption could have the same prefix, but it's very unlikely (make it longer to reduce the chance).
However, there's a security implication, since if someone knows that every message begins with the same prefix, it can help them analyze and try to break the encryption (similar to how you can use known letter frequencies when trying to break a simple Caesar cypher).
A slightly better method would be to generate a random string, and then put it in two places in the string before encrypting. Then check that they match.
random = random_string(10);
encrypt(random + message + random);
Then after decrypting, check if the first and last 10 characters match.
回答3:
This makes sense, most of the time you'll get an error if the bytes don't fit neatly into CryptoJS.enc.Utf8
. But on occasion, like you said the user might get lucky (or unlucky) and submit a key that decrypts to valid Utf8
bytes and it doesn't really know the difference. I'd be curious to know how often this happens.
My solution would be to parse the decrypted string and look for a few 'indicators' that the message looks like a normal English sentence, instead of a random string of random characters. First thing I would do would be to check for the number of spaces in the string. This would probably be the single best indicator.
回答4:
I'm not a security expert. You might consider asking a question on Information Security for a better opinion (read their FAQ first), but:
1) You shouldn't be trying to decrypt a message with the wrong key in the first place. That's just not something that should be happening. If a message is intended for a particular user and was encrypted using their key then include in your message who it's for and on the receiving end check if the message was for you:
Sending:
var message = { user: 1122, body: encryptedMessage };
send(message);
Recieving:
if (message.user == myUserId) {
decyptMessage(message.body);
} else {
// this message isn't for you
}
2) If for some reason that doesn't work, then you would need to insert something in the message that you can use to confirm that it's decypted properly. A checksum would achieve this:
Sending:
var message = originalMessage + CalcChecksum(originalMessage);
send(encypt(message));
Recieving:
var decrypted = decrypt(message);
var msg = getTheBodyPartOfTheMessage(decrypted);
var chk = getTheChecksumPartOfTheMessage(decrypted);
if (chk == CalcChecksum(msg) {
// this is a good message
} else {
// this message isn't for you
}
You can used a fixed length checksum so that, say, the last two characters are always the checksum or you could use some character (that won't otherwise appear) as a delimiter.
I like the checksum better than the idea of prefixing (or postfixing) some known string to every message because the checksum will be different for each message (well, not quite - but you won't be able to predict it).
来源:https://stackoverflow.com/questions/37663373/how-to-check-if-the-decryption-is-correct