Взаимодействие с Google Authenticator с помощью Cryptonite

Я пытаюсь сгенерировать TOTP, чтобы я мог использовать приложение Google Authenticator. Я использую библиотеку cryptonite, которая обеспечивает функциональность TOTP.

Насколько я понимаю, Google Authenticator требует ключ в Base32. Это также требует удаления заполнения =. Cryptonite предоставляет функцию unpad, но я не очень понимаю, как она работает, и поэтому не могу понять, каким должен быть первый аргумент, все, что я пробовал, возвращает функцию Nothing.

В целях тестирования я выбрал ключ без заполнения, однако коды, сгенерированные моей программой, не совпадают с кодами, сгенерированными Google Authenticator.

Ключ Base32, созданный кодом, выглядит следующим образом:

GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ

Ввод этого в Google Authenticator не дает тех же результатов, что и мой код.

Вот мой код:

{-# 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

Таким образом, я не уверен, как распаковать = байтов из ключа. Во-вторых, при тестировании с ключом без заполнения я все равно не получаю правильного результата.

РЕДАКТИРОВАТЬ: Если это кому-то поможет, мне удалось найти чью-то реализацию Google Authenticator в Haskell без использования cryptonite, однако я все еще не смог понять, почему мой код не работает. Google Authenticator в Haskell


person James Burton    schedule 26.05.2018    source источник
comment
@Карл Хорошо, спасибо за это. Даже без unpad я не получаю правильных кодов. У вас есть идеи, почему это может происходить?   -  person James Burton    schedule 26.05.2018
comment
Я думаю, вы хотите convertFromBase, а не convertToBase.   -  person Carl    schedule 26.05.2018


Ответы (1)


Я нашел ответ на свой вопрос в следующем вопросе, касающемся реализации на Python, здесь.

Я правильно преобразовал secret в base32, прежде чем вводить его в Google Authenticator, но я не знал, что Google Authenticator преобразовал его обратно из base32 в обычный секрет перед созданием кода.

Если я просто позвоню totp secret, введя keyBytes в Google Authenticator, я получу совпадающие коды.

person James Burton    schedule 26.05.2018
comment
Это может помочь думать об этом так: криптография выполняется для произвольных байтов, но отправка произвольных байтов часто затруднена. Таким образом, при передаче байты кодируются в каком-то формате, позволяющем представить их в виде текста — в данном случае Base32. Но формат Base32 — это формат передачи. Используйте необработанные байты для криптографии. - person Carl; 26.05.2018