TOTPジェネレーター - ワンタイムパスワード生成・検証 オンライン
2FAテスト用のTOTPコードを生成・検証。シークレット、QRコード、otpauth:// URIを作成。RFC 6238準拠 — 100%クライアントサイド処理。
TOTPコードを生成するにはシークレットキーを入力してください
よくある質問
TOTPジェネレーターとは何ですか?
TOTP(時間ベースのワンタイムパスワード)ジェネレーターは、RFC 6238標準に従って時間制限付きの認証コードを作成するオンラインツールです。TOTPは、Google Authenticator、Authy、Microsoft Authenticatorなどの人気のある認証アプリの背後にあるアルゴリズムです。共有秘密鍵と現在のUnixタイムスタンプをHMAC(ハッシュベースのメッセージ認証コード)関数を使用して組み合わせ、結果を切り詰めて短い数字コード(通常6桁または8桁)を生成します。コードはデフォルトで30秒ごとに変更され、二要素認証(2FA)の第二要素として有用です。このツールにより、開発者は認証アプリをインストールすることなく、ブラウザで直接TOTPコードの生成、検証、テストが可能です。
このツールはどのように使用しますか?
1. Base32エンコードされた秘密鍵を入力するか、「シークレット生成」をクリックしてランダムな鍵を作成します。2. TOTPパラメータを設定します:アルゴリズム(SHA-1がほとんどのサービスで使用されるデフォルト)、桁数(6または8)、時間周期(30秒が標準)。3. ツールは即座に現在のTOTPコードと、更新までの残り時間を示すカウントダウンタイマーを表示します。4. オプションで、発行者とラベルフィールドを入力して完全なotpauth:// URIを生成します。5. 生成されたQRコードを認証アプリでスキャンして、コードが一致することを確認します。6. 検証タブでコードを貼り付けて、設定されたシークレットと時間ウィンドウに対して有効かどうかを確認します。7. コードまたはURIの横にあるコピーボタンをクリックして、クリップボードにコピーします。
秘密鍵は安全ですか?サーバーに送信されますか?
秘密鍵は100%安全で、ブラウザの外に出ることはありません。HMAC計算、コード生成、検証、QRコードレンダリングなど、すべてのTOTP計算はJavaScriptを使用してクライアントサイドで完全に実行されます。このツールはRFC 6238計算にotpauthライブラリを使用し、暗号化操作にブラウザのネイティブWeb Crypto APIを使用します。データはサーバーに一切送信されず、アナリティクスが秘密鍵の内容を追跡することもなく、ブラウザタブのメモリ以外にデータが保存されることもありません。これにより、開発やQA中に実際のTOTPシークレットを使用したテストにも安全です。
otpauth:// URI形式とは何ですか?
otpauth:// URIは、認証アプリにTOTP(およびHOTP)シークレットをプロビジョニングするための標準化された形式です。QRコードにエンコードすると、スキャン時に認証アプリが必要なすべてのパラメータで自動的に設定されます。形式は次の通りです:otpauth://totp/{label}?secret={secret}&issuer={issuer}&algorithm={algorithm}&digits={digits}&period={period}。ラベルは通常issuer:accountの形式(例:MyApp:user@example.com)で、シークレットはBase32でエンコードされた共有鍵、オプションパラメータにはアルゴリズム(SHA1、SHA256、SHA512)、桁数(6または8)、周期(デフォルト30秒)が含まれます。この形式はGoogle Authenticator、Microsoft Authenticator、Authy、FreeOTP、およびほぼすべての標準準拠の認証アプリでサポートされています。
TOTPとHOTPの違いは何ですか?
TOTP(時間ベースのワンタイムパスワード、RFC 6238)は現在の時刻に基づいてコードを生成します。コードはN秒ごと(デフォルト30秒)に自動的に変更され、サーバーとクライアントの両方が現在のUnixタイムスタンプをカウンターとして使用するため、時計が合理的に正確である限り同期が維持されます。HOTP(HMACベースのワンタイムパスワード、RFC 4226)は増分カウンターに基づいてコードを生成します。コードが生成されるたびにカウンターが1つ進み、サーバーとクライアントは独立してカウンターを追跡する必要があります。コードが生成されても使用されない場合、非同期が発生する可能性があります。TOTPは技術的には「カウンター」が現在の時刻を周期で割った値であるHOTPの拡張です。このツールは、現代の2FA実装の主流標準であるTOTPに焦点を当てています。
TOTPコードが認証アプリと異なるのはなぜですか?
このツールで生成されたコードが認証アプリと一致しない場合、次の一般的な原因を確認してください:(1) 秘密鍵の誤り -- Base32シークレットが正確に入力されていることを確認してください。1文字でも間違うと完全に異なるコードが生成されます。(2) アルゴリズムの不一致 -- ほとんどのサービスはSHA-1(デフォルト)を使用しています。サービスがSHA-256またはSHA-512を使用している場合、ツールとアプリの両方が同一に設定されていることを確認してください。(3) 桁数の不一致 -- ほとんどのサービスは6桁を使用しますが、一部のエンタープライズツールは8桁を使用します。(4) 周期の不一致 -- 標準周期は30秒ですが、一部のサービスは60秒または90秒を使用します。(5) クロックスキュー -- TOTPは時間に敏感なため、デバイスの時計が大きくずれている(30秒以上)場合、コードは一致しません。NTPでシステム時計が同期されていることを確認してください。
二要素認証としてTOTPはどのくらい安全ですか?
TOTPは正しく実装されれば、認証のための強力な第二要素を提供します。各コードは1つの時間周期(通常30秒)のみ有効で、傍受攻撃のウィンドウを制限します。HMACを介して暗号化ハッシュ関数(SHA-1、SHA-256、またはSHA-512)を使用して秘密鍵からコードを導出するため、観察されたコードからシークレットをリバースエンジニアリングすることは計算上不可能です。共有シークレットは登録時に一度確立され、通常の認証中に再度送信されることはありません。ただし、TOTPはすべての攻撃に対して免疫があるわけではありません。フィッシング攻撃はリアルタイムでコードをキャプチャして再生でき、サーバーのシークレットストレージが侵害されると共有シークレットが漏洩する可能性があります。最高レベルのセキュリティには、TOTPをWebAuthn/FIDO2のようなフィッシング耐性のある方法と組み合わせてください。
コード例
// TOTP Generator using Web Crypto API (RFC 6238)
function base32Decode(base32) {
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
const cleaned = base32.toUpperCase().replace(/[^A-Z2-7]/g, '');
let bits = '';
for (const char of cleaned) {
const val = alphabet.indexOf(char);
if (val === -1) throw new Error(`Invalid Base32 character: ${char}`);
bits += val.toString(2).padStart(5, '0');
}
const bytes = new Uint8Array(Math.floor(bits.length / 8));
for (let i = 0; i < bytes.length; i++) {
bytes[i] = parseInt(bits.substr(i * 8, 8), 2);
}
return bytes;
}
async function generateTOTP(secret, options = {}) {
const {
algorithm = 'SHA-1',
digits = 6,
period = 30,
timestamp = Date.now(),
} = options;
const counter = Math.floor(timestamp / 1000 / period);
const counterBuffer = new ArrayBuffer(8);
const counterView = new DataView(counterBuffer);
counterView.setUint32(4, counter, false);
const keyBytes = base32Decode(secret);
const cryptoKey = await crypto.subtle.importKey(
'raw', keyBytes,
{ name: 'HMAC', hash: algorithm },
false, ['sign']
);
const hmacBuffer = await crypto.subtle.sign('HMAC', cryptoKey, counterBuffer);
const hmac = new Uint8Array(hmacBuffer);
const offset = hmac[hmac.length - 1] & 0x0f;
const code =
((hmac[offset] & 0x7f) << 24) |
((hmac[offset + 1] & 0xff) << 16) |
((hmac[offset + 2] & 0xff) << 8) |
(hmac[offset + 3] & 0xff);
const otp = code % Math.pow(10, digits);
return otp.toString().padStart(digits, '0');
}
function generateSecret(bits = 160) {
const bytes = new Uint8Array(bits / 8);
crypto.getRandomValues(bytes);
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
let result = '', buffer = 0, bufferLength = 0;
for (const byte of bytes) {
buffer = (buffer << 8) | byte;
bufferLength += 8;
while (bufferLength >= 5) {
bufferLength -= 5;
result += alphabet[(buffer >> bufferLength) & 0x1f];
}
}
if (bufferLength > 0) {
result += alphabet[(buffer << (5 - bufferLength)) & 0x1f];
}
return result;
}
// Usage:
// const secret = generateSecret();
// const code = await generateTOTP(secret);
// console.log('TOTP:', code);