如何检查解密是否正确?

时间:2016-06-06 17:20:47

标签: javascript encryption cryptojs

我正在聊天室为多个用户加密邮件,每个用户可能有不同的加密和密钥/密码。因此,用户的密钥不适用于所有消息;返回错误。

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");
}

我目前正在捕捉错误,但有时解密会返回混乱的字母和符号。我目前这样做的方式效率不高。还有更好的方法吗?

4 个答案:

答案 0 :(得分:6)

验证加密需要什么,请参阅Wikipedia

基本上HMAC使用加密密钥加密数据并将结果附加到加密数据。

在解密之前,HMAC使用解密密钥对加密数据进行比较,并与附加的HMAC值进行比较。 (使用恒定时间比较功能。)

enter image description here

答案 1 :(得分:1)

在每封邮件的开头加上一个前缀,例如

encrypt("ABCD" + message);

然后在解密时,检查结果是否以"ABCD"开头。

这不是万无一失的,因为不正确的解密可能会有相同的前缀,但这种可能性很小(为了减少机会,可以花更长的时间)。

然而,存在安全隐患,因为如果有人知道每条消息都以相同的前缀开头,它可以帮助他们分析并尝试打破加密(类似于在尝试打破简单时如何使用已知的字母频率) Caesar cypher)。

稍微好一点的方法是生成随机字符串,然后在加密前将其放在字符串中的两个位置。然后检查它们是否匹配。

random = random_string(10);
encrypt(random + message + random);

然后在解密后,检查第一个和最后10个字符是否匹配。

答案 2 :(得分:0)

这是有道理的,如果字节不完全适合CryptoJS.enc.Utf8,大多数情况下你会收到错误。但有时,就像你说的那样,用户可能会幸运(或不幸)并提交一个解密为有效Utf8字节的密钥,而且它并不真正知道其中的差异。我很想知道这种情况发生的频率。

我的解决方案是解析解密后的字符串并查找一些“指示符”,表明该消息看起来像一个普通的英语句子,而不是随机字符串的随机字符串。我要做的第一件事就是检查字符串中的空格数。这可能是唯一的最佳指标。

答案 3 :(得分:0)

我不是安全专家。您可以考虑在Information Security上提出问题以获得更好的意见(首先阅读他们的常见问题解答),但是:

1)您不应该首先尝试使用错误的密钥解密消息。这不是应该发生的事情。如果邮件是针对特定用户的,并且是使用其密钥加密的,那么请在邮件中包含 的信息,并在接收端检查邮件是否适合您< / EM>:

发送:

var message = { user: 1122, body: encryptedMessage };
send(message);

Recieving:

if (message.user == myUserId) {
    decyptMessage(message.body);
} else {
    // this message isn't for you
}

2)如果由于某种原因不起作用,那么您需要在消息中插入一些内容,以确认它是否已正确解除。 checksum可以达到这个目的:

发送:

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
}

您可以使用固定长度的校验和,例如,最后两个字符始终是校验和,或者您可以使用某些字符(否则会以其他方式出现)作为分隔符。

我更喜欢校验和比为每条消息添加前缀(或后缀)一些已知字符串的想法,因为每条消息的校验和都是不同的(好吧,不完全 - 但你不能预测它)。