使用 Cryptonite 与 Google 身份验证器交互

Interacting with Google Authenticator Using Cryptonite

我正在尝试生成 TOTP,以便我可以使用 Google Authenticator 应用程序。我正在使用提供 TOTP 功能的 cryptonite 库。

据我了解,Google Authenticator 需要 Base32 密钥。它还需要删除 = 填充。 Cryptonite 提供了一个 unpad 函数,但我真的不明白它是如何工作的,因此无法弄清楚第一个参数应该是什么,我尝试过的一切都使函数 return Nothing.

出于测试目的,我选择了一个没有填充的密钥,但是,我的程序生成的代码与 Google Authenticator 生成的代码不匹配。

代码生成的Base32密钥如下:

GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ

将此输入 Google 验证器不会产生与我的代码产生的结果相同的结果。

这是我的代码:

{-# LANGUAGE OverloadedStrings #-}

module TOTP
    ( genTOTP
    ) where

import qualified Basement.Imports        as Base (String)
import           Crypto.Data.Padding
import           Crypto.OTP              (defaultTOTPParams, totp)
import           Data.ByteArray
import           Data.ByteArray.Encoding
import           Data.Time.Clock.POSIX

genTOTP :: IO ()
genTOTP = do
    time <- getPOSIXTime
    let secret = "12345678901234567890" :: Base.String
        keyBytes = convertToBase Base32 secret :: Bytes
        key = keyBytes -- unpad (PKCS7 6) keyBytes -- I don't know what the first argument to unpad should be
        code = totp defaultTOTPParams key (round time)
    print code

总而言之,我不确定如何从密钥中取消填充 = 字节。其次,当使用没有填充的键进行测试时,我仍然没有得到正确的结果。

编辑:如果它对任何人有帮助,我确实设法在 Haskell 中找到了某人对 Google Authenticator 的实现而不使用 cryptonite 但是,我仍然无法弄清楚为什么我的代码不起作用。 Google Authenticator in Haskell

我在以下与 Python、.

中的实施相关的问题中找到了问题的答案

在输入 Google Authenticator 之前,我将 secret 转换为 base32 是正确的,但我不知道 Google Authenticator 将其从 base32 转换回常规生成代码之前的秘密。

如果我在 secret 上简单地调用 totp 并将 keyBytes 输入到 Google 验证器,我会得到匹配的代码。