Nodejs:使用speakeasy包生成一次密码

时间:2017-05-11 07:01:42

标签: node.js express

我在使用Speakeasy OTP验证时遇到了一个奇怪的问题,OTP应在2分钟后过期。

生成令牌

var secret = speakeasy.generateSecret({length: 20}).base32;

        var token = speakeasy.totp({
            secret: secret.base32,
            encoding: 'base32',
            time:120
        });

验证令牌

 var verified = speakeasy.totp.verify({
            secret:req.params.secret,
            encoding: 'base32',
            token: req.params.token,
            time:120
        });
console.log(verified);

案例1固定密钥

当我将secret密钥更改为固定密钥(即secret='676FGFG!@$#')时,OTP永远不会过期console.log(已验证);始终返回false

case-2使用base32生成密钥

当我使用base32生成secret时(即secret = secret.base32)OTP未经验证

的console.log(认证);始终返回true

2 个答案:

答案 0 :(得分:2)

一个问题是您的秘密实际设置为undefined

var secret = speakeasy.generateSecret({length: 20}).base32;
                                                   ^^^^^^^ notice this

var token = speakeasy.totp({
              secret: secret.base32,
                            ^^^^^^^ and again here

后者应该是secret : secret,因为secret变量已经包含了秘密的Base-32字符串。

其次,time并非用于设置到期/期限,而是step的用途。

由于TOTP在特定时间窗口中有效,因此您不能(AFAIK)将它们设置为有效,直到"从现在开始到5未来几分钟" 。你可以做的是调整window值,以便在验证期间允许宽容,在那里你可以说出属于"属于的标记。到5分钟前到5分钟之间的时间戳也是有效的:

// creating the token
let token = speakeasy.totp({
  ...
  window : 10
});

// verifying the token:
let verified = speakeasy.verify({
  ...
  window : 10
});

默认step值为30秒,这意味着每30秒生成一个新令牌。如果您希望该令牌仍然验证为"有效"在30秒的时间段之外,您可以指定一个窗口。一个窗口" 10"表示5分钟前和未来5分钟之间(10 * 30秒=)之间的所有令牌都有效。

您还可以将步骤设置为5分钟,但如果用户在5分钟有效期结束时收到令牌,则他们可能只剩下10秒钟,直到令牌失效。这就是为什么使用更宽的窗口而不是更大的步骤更好。

确保必须对stepwindow进行speakeasy.totp()和/或speakeasy.verify()的任何更改。

答案 1 :(得分:1)

浪费4个小时后,这对我有用,请复制整个代码并尝试一次。整理之后,您可以对其进行修改。

var secret = Speakeasy.generateSecret({length:6}); res.send({“ secret”:secret.base32});

        async totpgenerate(request,response) { 
          response.send({
              "token": Speakeasy.time({
                  secret: request.body.secret,
                  encoding: "base32",
                  step:600,//10 mins
                  window:0
              })
          })
        }
        ,
        async totpvalidate(request,response) { 
          response.send({
              "valid": Speakeasy.time.verify({
                secret:request.body.secret,
                encoding: 'base32',
                token: request.body.token,
                step:600,//10 mins
                  window:0
              })
          })
        }