我正在尝试使用AES作为密码,用于我正在构建的应用程序。我使用JavaScript库(https://code.google.com/p/crypto-js/)来使用AES执行加密和解密。当我执行解密时,会发生这样的情况:
AES.decrypt(ct, right_key) == 'message decrypted !' //true
AES.decrypt(ct, wrong_key) == '' //true问题是,我在一个进程中使用这个解密,在这个过程中不应该有任何方法来确定密钥是对的还是错的。我希望这样的事情发生:
log(AES.decrypt(msg, wrong_key)) // 'random string fsdijw'因此,结果与预期的结果“兼容”,但不是预期的结果,而且根据解密的结果,无法理解密钥是对还是错。我问我的教授,他告诉我,AES在图书馆里的应用可能不是很好,但他对我的问题还不太清楚。
我想知道在第一个代码片段中描述的行为是否是预期的,或者实际上AES在那个库中实现得不好。如果是预期的话,是否还有其他密码算法不允许从解密的结果中了解密钥是对还是错?
发布于 2016-01-18 12:28:55
AES是块密码,使用错误的密钥时会返回错误的数据。它只在单个数据块(16字节)上工作。默认的CBC操作模式使您能够加密多个数据块。填充使您能够加密任意长度的明文。在解密之后,填充物必须以某种方式除去。
您看到的是一个空白输出,因为您的数据很短,填充移除的字节比必要的要多。下面是默认的PKCS#7填充是用CryptoJS实现:
unpad: function (data) {
// Get number of padding bytes from last byte
var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
// Remove padding
data.sigBytes -= nPaddingBytes;
}因此,它查看解密字节的最后一个字节,并从密文中删除同样多的字节。如果data.sigBytes是负的,它将处理它像0字节解密。如果您的消息超过255个字节,那么解密将保证打印某些内容,但不会像初始明文那样长。如果你总是想打印一些东西,那么你需要解密没有填充。
我不认为这个实现是错误的,因为PKCS#7填充是为256个填充字节指定的,但是data.sigBytes -= Math.min(nPaddingBytes, blocksize);可能会更好。
在您的情况下,零填充可能更适合,因为带有错误密钥的解密不太可能导致明文在结尾处以许多零字节结束,因此必须删除。但是,当您有可能加密以0x00字节结尾的明文时,不应该使用填充。
因此,结果与预期的结果“兼容”,但不是预期的结果,而且根据解密的结果,无法理解密钥是对还是错。
这在分组密码中通常是不可能的。带有错误密钥的解密可能导致一些任意明文字节,这些字节不需要使用有效的ASCII或UTF-8编码组成字符串,如果您试图强制使用它,您将得到错误,这些错误可用于区分正确的密钥和错误的密钥。
如果您总是将明文编码为十六进制,那么就可以使用任意的键了。
相关信息:
https://crypto.stackexchange.com/questions/32013
复制相似问题