如何检查解密是否正确?
How to check if the decryption is correct?
我正在为多个用户加密消息的聊天室工作,每个用户可能有不同的加密和 key/password。因此,用户的密钥不适用于所有消息; return 个错误。
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");
}
我目前正在捕获错误,但有时解密 return 会出现乱七八糟的字母和符号。我目前这样做的方式效率不高。有没有更好的方法?
这是有道理的,大多数情况下,如果字节不适合 CryptoJS.enc.Utf8
,您会收到错误消息。但有时,就像你说的那样,用户可能会幸运(或不幸)并提交一个解密为有效 Utf8
字节的密钥,但它并不知道其中的区别。我很想知道这种情况发生的频率。
我的解决方案是解析解密后的字符串并寻找一些 'indicators' 消息看起来像普通英文句子,而不是随机字符串的随机字符串。我要做的第一件事是检查字符串中的空格数。这可能是最好的指标。
我不是安全专家。您可能会考虑在 Information Security 上提问以获得更好的意见(请先阅读他们的常见问题解答),但是:
1) 您一开始就不应该尝试使用错误的密钥来解密消息。那不应该发生。如果消息是针对特定用户的并且使用他们的密钥加密,那么请在您的消息中包含它是给谁的,并在接收端检查消息是否是给您的:
发送中:
var message = { user: 1122, body: encryptedMessage };
send(message);
收到:
if (message.user == myUserId) {
decyptMessage(message.body);
} else {
// this message isn't for you
}
2) 如果由于某种原因不起作用,那么您需要在消息中插入一些内容,您可以使用这些内容来确认它是否被正确解密。 checksum 将实现此目的:
发送中:
var message = originalMessage + CalcChecksum(originalMessage);
send(encypt(message));
收到:
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
}
您可以使用固定长度的校验和,例如,最后两个字符始终是校验和,或者您可以使用某个字符(否则不会出现)作为分隔符。
比起为每条消息添加前缀(或后缀)一些已知字符串的想法,我更喜欢校验和,因为每条消息的校验和都会不同(好吧,不完全是 - 但你将无法预测它).
在每条消息的开头加上前缀,例如
encrypt("ABCD" + message);
然后你解密的时候,检查结果是否以"ABCD"
开头。
这并非万无一失,因为不正确的解密可能具有相同的前缀,但这种可能性很小(延长时间以减少机会)。
但是,这存在安全隐患,因为如果有人知道每条消息都以相同的前缀开头,就可以帮助他们分析并尝试破解加密(类似于尝试破解时使用已知字母频率的方式)一个简单的凯撒密码)。
稍微好一点的方法是生成一个随机字符串,然后把它放在字符串中的两个地方再加密。然后检查它们是否匹配。
random = random_string(10);
encrypt(random + message + random);
然后解密后,检查前10个字符和后10个字符是否匹配。
需要什么认证加密呢,见Wikipedia。
本质上是使用加密密钥对加密数据进行 HMAC,并将结果附加到加密数据。
在使用解密密钥对加密数据进行 HMAC 解密并与附加的 HMAC 值进行比较之前。 (使用常数时间比较函数。)
我正在为多个用户加密消息的聊天室工作,每个用户可能有不同的加密和 key/password。因此,用户的密钥不适用于所有消息; return 个错误。
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");
}
我目前正在捕获错误,但有时解密 return 会出现乱七八糟的字母和符号。我目前这样做的方式效率不高。有没有更好的方法?
这是有道理的,大多数情况下,如果字节不适合 CryptoJS.enc.Utf8
,您会收到错误消息。但有时,就像你说的那样,用户可能会幸运(或不幸)并提交一个解密为有效 Utf8
字节的密钥,但它并不知道其中的区别。我很想知道这种情况发生的频率。
我的解决方案是解析解密后的字符串并寻找一些 'indicators' 消息看起来像普通英文句子,而不是随机字符串的随机字符串。我要做的第一件事是检查字符串中的空格数。这可能是最好的指标。
我不是安全专家。您可能会考虑在 Information Security 上提问以获得更好的意见(请先阅读他们的常见问题解答),但是:
1) 您一开始就不应该尝试使用错误的密钥来解密消息。那不应该发生。如果消息是针对特定用户的并且使用他们的密钥加密,那么请在您的消息中包含它是给谁的,并在接收端检查消息是否是给您的:
发送中:
var message = { user: 1122, body: encryptedMessage };
send(message);
收到:
if (message.user == myUserId) {
decyptMessage(message.body);
} else {
// this message isn't for you
}
2) 如果由于某种原因不起作用,那么您需要在消息中插入一些内容,您可以使用这些内容来确认它是否被正确解密。 checksum 将实现此目的:
发送中:
var message = originalMessage + CalcChecksum(originalMessage);
send(encypt(message));
收到:
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
}
您可以使用固定长度的校验和,例如,最后两个字符始终是校验和,或者您可以使用某个字符(否则不会出现)作为分隔符。
比起为每条消息添加前缀(或后缀)一些已知字符串的想法,我更喜欢校验和,因为每条消息的校验和都会不同(好吧,不完全是 - 但你将无法预测它).
在每条消息的开头加上前缀,例如
encrypt("ABCD" + message);
然后你解密的时候,检查结果是否以"ABCD"
开头。
这并非万无一失,因为不正确的解密可能具有相同的前缀,但这种可能性很小(延长时间以减少机会)。
但是,这存在安全隐患,因为如果有人知道每条消息都以相同的前缀开头,就可以帮助他们分析并尝试破解加密(类似于尝试破解时使用已知字母频率的方式)一个简单的凯撒密码)。
稍微好一点的方法是生成一个随机字符串,然后把它放在字符串中的两个地方再加密。然后检查它们是否匹配。
random = random_string(10);
encrypt(random + message + random);
然后解密后,检查前10个字符和后10个字符是否匹配。
需要什么认证加密呢,见Wikipedia。
本质上是使用加密密钥对加密数据进行 HMAC,并将结果附加到加密数据。
在使用解密密钥对加密数据进行 HMAC 解密并与附加的 HMAC 值进行比较之前。 (使用常数时间比较函数。)