是否可以利用Math.random()生成密码重置密钥?

时间:2018-02-18 07:54:29

标签: javascript node.js authentication cryptography authorization

我有一个非常基本的想法,一个简单的算法,允许用户通过请求发送到他们的电子邮件的随机代码重置他们的密码。

如果用户忘记了他们的PW,他们可以请求服务器生成重置代码并将其作为电子邮件发送给他们。然后将此代码附加到DB中的用户条目。确认输入表单将要求用户在前端键入重置代码 - 如果它们失败,代码将被标记并失效。如果成功,他们将被发送到新的PW重置表单,在那里他们可以更新他们的凭据,通过PUT请求替换到后端。

这是我的基本想法 -

function generate7KeyPasswordResetConfirmationCode() {

    const arrayOfSeven = [1, 2, 3, 4, 5, 6, 7]

    const alphabet = [Array of 26 Lowercase Chars and 26 Uppercase Chars]

    const letterOrNumber = arrayOfSeven.map(currentPos => {
        // return pseudorandom number between 0-100
        const oneToOneHundred = Math.floor(Math.random() * Math.floor(101))
            if (oneToOneHundred < 50) { return "char" }
            else if (oneToOneHundred >= 50) { return "num" }        
    })

    const resetKey = letterOrNumber.map(numOrChar => {
        // return pseudorandom number between 0-51 and return a-z-A-Z
        if (numOrChar === "char") {
            const index = Math.floor(Math.random() * Math.floor(52))                
              return alphabet[index]
        }
        // return pseudorandom number 0-9
        if(numOrChar === "num") { 
            return Math.floor(Math.random() * Math.floor(10)) 
        }
    })

        return resetKey
}

但是,我的方法涉及Math.random(),我注意到MDN上的这个东西:

Math.random() does not provide cryptographically secure random numbers. Do not use them for anything related to security. Use the Web Crypto API instead, and more precisely the window.crypto.getRandomValues() method

我意识到我可以使用uuid4,但我想创建自己的解决方案 - 这究竟是如何被破解的?如果我在第一次尝试失败时使代码无效,还有什么可能出错?

1 个答案:

答案 0 :(得分:3)

不,使用非安全随机数生成器从不是个好主意。随机生成的密码应具有与随机生成的密钥类似的属性。无法保证随机数生成器不受其他脚本的影响。在最坏的情况下,其他脚本可以找出随机数生成器的状态并直接计算您的密码。

因此,请使用tmpfile生成密码。可以找到从安全随机数生成器检索密码的无偏见实现window.crypto.getRandomValues(array)

如果您无法访问随机数生成器,则:

  1. 从服务器获取安全随机数;
  2. 从客户端添加随机熵(鼠标移动,系统时间,一些不安全的随机值等),并将它们从服务器连接到随机;
  3. 对结果数组执行安全计算,例如散列或PRNG实现,以创建随机数;
  4. 使用(3)创建密码。
  5. 您绝对应该只通过安全连接执行此操作,并牢记网络钓鱼攻击。