我正在使用javascript函数,使用6位数PIN码在浏览器上加密和存储密码。虽然这很容易被强制强制,但服务器端代码通过在3次错误尝试后锁定帐户来防止这种情况。
以下示例使用AES,仅在引脚/键正确时才解密为纯文本。这允许攻击者尝试99,9999个组合并选择唯一的纯文本结果,绕过服务器端限制。
有人可以推荐一个javascript加密函数/库,即使使用错误的密钥也始终会解密为纯文本吗?
var encrypted = CryptoJS.AES.encrypt("password:abcdefg", "pin:123456");
$('#1').text(encrypted);
var decryptedCorrect = CryptoJS.AES.decrypt($('#1').text(), "pin:123456")
$('#3').text(decryptedCorrect.toString(CryptoJS.enc.Utf8));
var decryptedInCorrect = CryptoJS.AES.decrypt($('#1').text(), "pin:112233")
$('#4').text(decryptedInCorrect.toString(CryptoJS.enc.Utf8));

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<div>
Encrypted text: <span id="1"></span>
</div>
<br />
<div>
Decrypted with correct pin: <span id="3"></span>
</div>
<br />
<div>
Decrypted with incorrect pin: <span id="4"></span>
</div>
(Ideally the above should be some plain text value)
&#13;
答案 0 :(得分:2)
一般情况下,这不起作用。
为了防止像这样的暴力猜测攻击,你不仅需要每个密钥(或至少相当大一部分密钥)才能将密文解密为有效的明文,但你必须以某种方式安排每一个密钥。将密文解密成合理的明文的关键,足以令人信服,至少在粗略的检查中传递真正的明文。
特别是,在错误加密时产生的“假”明文至少需要在语法上有效,因此您自己的代码将接受它,并且它还需要具有相同的通用结构和相同的统计属性。你真正的纯文本,以便攻击者不能只使用一些正则表达式或字母频率分析来猜测哪个明文最可能是正确的。
基本上,如果您要加密密码,您的解密方法必须为任何密钥生成看似合理的密码。如果您正在加密JSON数据,则必须生成有效的JSON。如果你正在加密诗歌,它必须产生一首诗。
他们必须是好的诗歌,因为谁会为加剧糟糕的诗歌而烦恼?
显然,没有通用的加密算法可以做到这一点。
那么,可以如何实现你想要的东西?基本上,您有两种选择:
您可以增加密钥的长度,使其无法实际枚举。如果您使用随机十进制数字(实际上是随机选择的,而不是用户选择的!),那么大约25到30位数应该是最小安全长度。
您可以使用key stretching缩短一点长度。例如,如果在使用结果解密数据之前将每个密钥散列100,000次,则可以将密钥空间大小减少100,000倍,即从25位减少到20位。
您还可以通过将其编码为短语来使您的密钥更容易记忆。例如,您可以编译1000个简短的常用英语单词(或use an existing list)的列表,并将密码中的每个三位数组替换为列表中的相应单词。对于大多数人来说,记住一个五个随机单词的序列比一个随机的25位数字要容易得多。
当然,另一个选择是利用您已有的服务器端速率限制。要做到这一点,您需要确保客户端必须先使用服务器检查密钥,然后才能使用服务器执行任何其他操作。
也就是说,您应该在服务器上存储实际的加密密钥(可以是一个随机的128位二进制字符串),并让服务器在客户端成功通过其身份验证后将其发送到客户端拥有“短信”。
您还应确保窃听者无法捕获短密钥和长密钥,例如:使用SRP之类的内容进行身份验证,或者只是通过TLS/SSL进行身份验证。
这些解决方案都不是完美的:第一种解决方案可能需要不方便的长按键,即使使用按键拉伸也是如此,而第二种方法如果客户端处于脱机状态则不起作用,并且灾难性地失败是服务器遭到黑客入侵。但总的来说,这些都是你能做到的最好的。
(是将两种方法结合起来以获得额外安全性的方法,因此攻击者必须两者破坏服务器和猜测客户的密码是为了打破系统。但是你也有两种方法的缺点。)
答案 1 :(得分:1)
格式保留加密,直接回答您的问题。您可以查找库函数,但FPE并不常见。相反,您应该在开始解密/验证之前减少PIN重试计数器,然后在PIN解密并且正确的情况下再次增加它。
请注意,您的随意方案不能替代TLS,并且可能 - 并且可能还有 - 其他漏洞。