認証アプリ(Google 認証システム、Microsoft Authenticator など)の6桁のコードを入れても「コードが間違っています」と出るとき、疑う場所は大きく2つです。スマートフォンの時計と、見ているコードの行(アカウント)です。
認証アプリと同じ計算をPythonで再現し、「時計が何秒ずれると通らなくなるのか」を実際に数えました。結果を見ると、時刻のずれは「ときどき通る」という形で現れることがあり、切り分けの手がかりになります。
先に切り分け:「ときどき通る」か「一度も通らない」か
- 何回か試すと通ったり通らなかったりする:時計が十数秒〜数十秒ずれているか、コードの切り替わり直前に入力している可能性が高い。下の実験の「15/30」の行がこの状態です
- 何度やっても一度も通らない:時計が1分以上ずれている、別のアカウントの行を見ている、サービス側で認証アプリを設定し直して古い登録が無効になっている、のどれかを疑います
- SMSやメールで届いたコードが通らない:時計とは関係ありません。送り直した場合は最後に届いたものだけを使います。届かない・古いものしかない場合はSMSの認証コードが届かないときへ
実験:時計が何秒ずれると通らなくなるか
認証アプリのコードはTOTP(RFC 6238)という方式で作られます。設定時にアプリとサービスが共有した秘密の値と、現在時刻を30秒ごとに区切った「区間の番号」から6桁を計算します。アプリとサービスは通信せず、それぞれが自分の時計で同じ計算をするだけです。
2026年10月19日、macOS上のPython 3.9.7(標準ライブラリのみ)でこの計算を書き、まずRFC 6238の付録Bにあるテスト用の値6件すべてと一致することを確かめました。そのうえで、架空の秘密の値を使い、次の条件をすべて組み合わせて試しています。
- 端末の時計のずれ:−120秒〜+120秒を15秒刻み(+は端末が進んでいる)
- 入力した瞬間:30秒区間の0秒目〜29秒目の30通り
- サービス側の照合の仕方:「同じ区間のコードだけ受け付ける」「1つ前の区間まで受け付ける」「前後1区間ずつ受け付ける」の3通り

結果のうち、−60秒〜+60秒の部分です。数字は「30通りの入力時刻のうち何通りで通ったか」を表します(±75秒より外は、3通りの照合方法すべてで0/30でした)。
RFC 6238 付録B テストベクタ: 6/6 一致
ずれ(秒) | 同じ区間のみ | 過去1区間まで | 前後1区間
-60 | 0/30 | 0/30 | 0/30
-45 | 0/30 | 15/30 | 15/30
-30 | 0/30 | 30/30 | 30/30
-15 | 15/30 | 30/30 | 30/30
+0 | 30/30 | 30/30 | 30/30
+15 | 15/30 | 15/30 | 30/30
+30 | 0/30 | 0/30 | 30/30
+45 | 0/30 | 0/30 | 15/30
+60 | 0/30 | 0/30 | 0/30
28秒目に読んだ 610038 → 31秒目に到着: 同じ区間のみ=通らない, 過去1区間まで=通る, 前後1区間=通る
この表の読み方
- 15秒のずれでも「半分の確率で通らない」照合方法がある:同じ区間しか見ないサービスなら、+15秒・−15秒の行は15/30。何度か試すと通ることがあるので、時計が原因だと気づきにくくなります
- 前後1区間を許すサービスでも、1分ずれるとまったく通らない:±60秒の行はどの方法でも0/30です。±45秒は15/30で、ここが境目です
- 進んでいるか遅れているかで結果が変わる:「1つ前の区間まで」を受け付ける方式では、端末が30秒遅れていても必ず通る一方、15秒進んでいるだけで半分は通りません
- 時計が正確でも、切り替わり直前の入力は落ちることがある:最後の行は、区間の28秒目に読んだコードが3秒後(次の区間の1秒目)に届いた場合です。同じ区間しか見ない方式では通りません。残り時間が数秒なら、次のコードに変わってから入力するほうが確実です
タイムゾーンの違いそのものは関係ない
計算に使うのは世界共通の時刻(UNIX時刻)なので、同じ瞬間なら日本時間で表示していても協定世界時で表示していても、コードは同じでした(実験の出力では両方とも534312)。海外へ移動してタイムゾーンが切り替わっただけなら、認証アプリを設定し直す必要はありません。
問題になるのは、タイムゾーンが間違ったまま、時計の表示だけを手で合わせた場合です。タイムゾーンを協定世界時にしたまま時計を日本の9時に合わせると、実際の時刻とは32,400秒(9時間)ずれ、コードは別物(712210)になりました。時計の見た目が正しくても通らないのはこのパターンです。Googleがコードが通らないときの確認項目に「デバイスの時刻が同期され、現地のタイムゾーンで正しく設定されていること」と、時刻とタイムゾーンを並べているのもこのためです(Google 認証システムで確認コードを取得する)。
この実験で分からないこと
Google、Microsoft、X などの各サービスが、上の3通りのどれで照合しているのか、何区間まで許すのかは、各社のヘルプには書かれていません。実験が示しているのはずれがどう効くかという仕組みで、特定のサービスで何秒まで大丈夫かではありません。どのサービスでも確実なのは、端末の時計を正確にしておくことです。
使ったコード(要点だけ)
import hmac, hashlib, struct
def totp(secret, t, digits=6):
h = hmac.new(secret, struct.pack(">Q", int(t) // 30), hashlib.sha1).digest()
o = h[-1] & 0x0F
n = struct.unpack(">I", h[o:o + 4])[0] & 0x7FFFFFFF
return str(n % 10 ** digits).zfill(digits)
# 端末は drift 秒ずれた時計でコードを作る
code = totp(secret, server_t + drift)
# サービスは自分の時計の区間と、許す前後の区間(offsets)のコードと照合する
ok = code in {totp(secret, server_t + k * 30) for k in offsets} # offsets 例: (-1, 0, 1)
RFC 6238 が決めていること、決めていないこと
この記事の以前の版では「RFC 6238は許すずれの幅を決めていない」と書いていましたが、正確ではありませんでした。原文(RFC 6238: TOTP: Time-Based One-Time Password Algorithm)を読み直すと、次の2段構えになっています(日本語は筆者訳)。
- 5.2節(送信の遅れ):”We RECOMMEND that at most one time step is allowed as the network delay.”(ネットワークの遅れとして許すのは、最大1区間とすることを推奨する)。上の実験の「28秒目→31秒目」がこれに当たります
- 6節(時計のずれの再同期):時計のずれに備えて、何区間まで「同期がずれている」のを認めてから拒否するか、検証側に具体的な上限を設けることを推奨しています。例として、過去2区間まで許せば最大で約89秒のずれまで受け付けられること、照合に成功したときに検出したずれを記録し、次回からそのぶん補正して照合できることも書かれています
つまり、遅延については「1区間まで」という推奨値がある一方、時計のずれをいくつまで許すかは「上限を決めておくこと」を勧めるにとどまり、具体的な数は各サービスが決めます。6節は、長くコードを使っていないとずれが積み重なり、自動の補正が効かなくなる場合があることにも触れています。久しぶりに使うサービスで通らないときは、まず時計を疑う価値があります。
スマートフォンの時刻を自動に戻す
- iPhone:「設定」>「一般」>「日付と時刻」で「自動設定」をオンにする
- Android:「設定」の「日付と時刻」(機種によって「システム」の中)で、ネットワークの時刻を使う設定とタイムゾーンの自動設定をオンにする
自動に戻したら、コードが次に切り替わるのを待ってから入力します。手で時刻を合わせたことがある、海外でSIMを差し替えた、という端末は特に確認してください。
Google 認証システムの「時刻調整」メニューはどこへ行ったか
古い解説記事には、Google 認証システムのメニューから「コードの時刻調整」を開いて「今すぐ同期」を押す、という手順がいまも残っています。現在のアプリでこのメニューを探しても見つからないのは、機能そのものが無くなったためです。Googleのヘルプの文言がいつ変わったかを、Internet Archiveの保存版でたどりました(日本語版・Android向けページ)。
| 保存日 | ヘルプの記載 |
|---|---|
| 2024年1月2日・3月31日 | 「その他メニュー」>[コードの時刻調整]>[今すぐ同期]の手順あり。「同期の影響を受けるのは Google 認証システム アプリ内部の時刻のみ」 |
| 2024年8月6日・8月8日 | ページが改訂され、時刻調整の手順が消える。代わりの説明はまだ無い |
| 2024年10月4日 | 「重要: バージョン 7.0 では、時刻調整の設定は使用できなくなりました。アプリはオペレーティング システムの時刻設定を使用します。」が初めて現れる(英語版は2024年9月17日の保存版で初出) |
| 2026年10月19日(現在のページ) | 同じ文言が残っている |
2024年8月から10月初めまでは、手順が消えたのに理由が書かれていない期間があったことになります。いまの Google 認証システムは端末の時計をそのまま使うので、アプリの中ではなく、上の手順で端末の時刻を直すのが正解です。
一度も通らないとき:別の行・機種変更・設定し直し
- 隣の行のコードを見ている:同じサービスのアカウントが2つある、使わなくなった登録が残っている、という場合です。コードの横のサービス名とアカウント名(メールアドレス)を確かめます
- 機種変更で中身が移っていない:コードを作る元は秘密の値なので、それを移さない限り新しい端末では同じコードは出ません。Google 認証システムでGoogleアカウントにログインして使っている場合は自動で同期されます。アカウントなしで使っている場合は、前の端末で[コードを移行]>[コードをエクスポート]、新しい端末で[コードを移行]>[コードをインポート]からQRコードを読み取ります(2026年10月19日のヘルプの表記)
- サービス側で設定し直した:認証アプリを登録し直すと新しい秘密の値が発行され、古い端末に残った行のコードは通らなくなります。古い行は削除しておきます
前の端末を初期化してしまい、ほかの手段も無い場合は2段階認証の手段を失ったときを見てください。
何度も失敗したときの注意
コードの入力を何度も間違えると、サービスによってはログインが一時的に制限されます。時計を直さないまま入力を繰り返しても、上の表のとおり通る見込みは増えません。先に時刻と行を確かめてから入力してください。制限がかかってしまった場合は「試行回数が上限に達しました」と表示されたときを見てください。
この記事の確かめ方
この記事の調査・計算・撮影・執筆は、運営者の指示のもとでAIエージェント(AnthropicのClaude)が行い、公開するかどうかは運営者が決めています。下に書いた確認は、すべてそのAIエージェントによるものです。
- TOTPの計算をPython標準ライブラリだけで書き、2026年10月19日にmacOS上で実行。RFC 6238付録Bのテスト値6件の一致を確認したうえで、ずれ(15秒刻み)×入力時刻(30通り)×照合方法(3通り)をすべて計算した
- RFC 6238の5.2節と6節は、RFC Editorのテキスト版を同日に取得して原文から訳した
- Google 認証システムのヘルプは、現在のページ(Android・iPhone向けとも)を同日に取得して「バージョン 7.0」の一文を確認し、Internet Archiveの保存版8件(日本語)と3件(英語)で文言の変化した時期を絞り込んだ
- IETF / RFC Editor:RFC 6238: TOTP: Time-Based One-Time Password Algorithm
- Google アカウント ヘルプ:Google 認証システムで確認コードを取得する
コメントを残す