var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase");
假设加密和解密阶段是分开的(发生在程序的不同部分),有什么办法可以检查解密阶段"Secret Passphrase"
是否正确?
我注意到使用错误的密码短语进行解密会导致decrypted.toString()
为空字符串。那么如果原始消息也是一个空字符串呢?我还没有其他任何参数来检查密码是否确实正确吗?
附注
我当前的解决方案:始终创建一个非空控件值,使用密码加密。如果控制值解密为"",则密码短语不正确。
编辑:事实证明我的解决方案并不奏效。非常相似的密码短语将消息解密为不同的值,这些值仍然与空字符串不同。安全性没有受到损害,但我仍然无法确定密码是否正确。 this is my very cool key!
和this is my very cool key!!
都返回一个字符串,即使只有第一个字符串是用于加密的实际密码短语。
编辑2:从错误的密码短语返回的字符串无效UTF-8。因此,调用value.toString(CryptoJS.enc.Utf8)
会返回错误。我可以使用此错误来检查密码是否正确。不过,这个解决方案非常糟糕!
答案 0 :(得分:6)
您刚刚发现了消息机密性和消息完整性/身份验证之间的微妙但重要的区别。
保密性是您目前所做的事情,它确保在没有关联密钥的情况下无法在传输过程中读取消息,但它无法确保在传输过程中消息未被更改(攻击)早期加密系统涉及修改加密消息以注入或揭示有关加密系统的信息。你的问题就是这个问题的一个变种,如果你碰巧找到一个解密邮件的密钥"投降"到"炸弹"然后就没有办法知道他们的钥匙被切换了。
Integrity需要确保解密的内容首先是实际加密的内容,并且还可以根据所使用的模型确保身份验证(加密它)。最好通过使用mode of operation本质上支持GCM来实现完整性,但从粗略的一瞥中,crypto-js不支持任何完整性模式。
这为您提供了一种手动方法,需要生成并发送HMAC以及加密消息。
var message = "Message";
var passphrase = "Secret Passphrase";
var encrypted = CryptoJS.AES.encrypt(message, passphrase).toString();
var hmac = CryptoJS.HmacSHA256(encrypted, CryptoJS.SHA256(passphrase)).toString();
var transitmessage = hmac + encrypted;
//other side
var transithmac = transitmessage.substring(0, 64);
var transitencrypted = transitmessage.substring(64);
var decryptedhmac = CryptoJS.HmacSHA256(transitencrypted, CryptoJS.SHA256(passphrase)).toString();
alert(transithmac == decryptedhmac);
var decrypted = CryptoJS.AES.decrypt(transitencrypted, passphrase).toString(CryptoJS.enc.Utf8);
alert(decrypted.toString(CryptoJS.enc.Utf8));
理论上,在HMAC呼叫之前,IV也应该加在加密消息之前,但我不确定如何使用crypto-js恢复IV,我希望保持这个例子足够简单,除非你期望成为NSA的目标,因为IV已经修改了加密的消息。