バックグラウンド
現在、ユーザーがスマートフォンを使用して認証できる二要素認証システムに取り組んでいます。ユーザーが自分のデバイスを使用する前に、まずデバイスを確認する必要があります。そのためには、私が提供した QR コードをスキャンし、続いて表示されるコードを入力する必要があります。
問題
QR コードのスキャンは正常に機能し、Google 認証アプリによって正しく読み取られます。ただし、生成されたコードは、サーバー上で生成しているコードと一致しません。
私は何を試しましたか
私の問題を見つけることを期待して、いくつかのことを試しました。
'thiswasmysecretkeyused'
デフォルトの secret:とbase64.b32encode()
エンコードされたバージョンの secret: の両方を Google Authenticator アプリに直接挿入しようとし'ORUGS43XMFZW26LTMVRXEZLUNNSXS5LTMVSA===='
ましたが、これらは両方ともサーバーとは異なるコードを生成しました。====
キーの末尾が原因で機能しない可能性があると読んだので、それらも含めずに追加してみました。それでも良い結果は得られません (同じコードが生成されます)TOTP コードを生成するために別のアルゴリズムを使用してみました。これは、使用しているアルゴリズム ( django-otp ) が正しくない場合に備えてです。私が使用した別のアルゴリズムは、この回答から取られました。どちらのアルゴリズムも、同じキーを使用すると同じコードを生成しました。
システムの時刻を確認しました。オペレーティング システムが
15:03
スマートフォンと同じように表示されていることがわかりました。time.time()
両方でPythonで時間をダンプした後datetime.datetime.now()
、返された時間がオペレーティングシステムの時間より1時間遅れていることがわかりました。を示してい14:03
ます。3600
コード生成に使用されるタイムスタンプに秒を追加しようとしましたが、役に立ちませんでした。他にもいくつか試してみましたが、それらがすべて何であったかを思い出せません。
Google Authenticator でキーを受け入れるコードを調べたところ、base32 文字列が必要であることを確認しました。したがって、私の知る限り、キーのエンコードは正しいです。コードから ( EnterKeyActivity.java、78行目):
入力フィールドに有効な base32 文字列が含まれていることを確認します
コード
秘密鍵の生成;
def generate_shared_key(self):
# create hash etc.
return base64.b32encode(hasher.hexdigest())
QRコードの生成;
key = authenticator.generate_shared_key()
qrcode = pyqrcode.create('otpauth://totp/someurl.nl?secret=' + key)
TOTP コードの生成;
def generate_code(self, drift_steps=0, creation_interval=30, digits=6, t0=0):
code = str(totp(self.generate_shared_key(), creation_interval, timestamp, digits, drift_steps))
return code.zfill(digits)
django-otp 実際の totp 生成コードなど、さらにコードが必要な場合はお知らせください。
エラー
エラーなし。
予感
私の推測では、鍵の生成または Google Authenticator への鍵の受け渡しのどこかで間違っているに違いありません。キーを手動で Google Authenticator に入れても、正しいコードを生成できないためです。ユーザーの追加など、キーが保存されると、Google Authenticator はそれ以上の処理を行いますか?
私が使用した他のアルゴリズムでも、そこにある秘密が最初にデコードされることに気付きました。
key = base64.b32decode(secret, True)
元のキー (SHA512 ハッシュ) は間違っていますか? でエンコードする必要がありbase64.b32encode()
ますか? ハッシュをエンコードせずに生成された QR コードをスキャンしようとすると、Google Authenticator はそれを (有効な) キーとして認識しないと言います。