ホームページ ウェブフロントエンド jsチュートリアル Math.random() を実行するだけで済むのに、なぜ OTP ライブラリを使用するのでしょうか。

Math.random() を実行するだけで済むのに、なぜ OTP ライブラリを使用するのでしょうか。

Aug 17, 2024 pm 08:30 PM

Why do we use OTP libraries when we can just do Math.random()

ワンタイム パスワード (OTP) は、さまざまなアプリケーションやサービスで認証と検証の目的で広く使用されています。通常、サーバーがそれらを生成し、SMS、電子メール、またはその他のチャネル経由でユーザーに送信します。次に、ユーザーは OTP を入力して身元を確認するか、アクションを実行します。

Node JS で OTP ベースの検証を実装する必要があるタスクを受け取りました。このようなものを統合する前に、私たちのほとんどの開発者/エンジニアは、インターネットでベスト プラクティス、チュートリアル、最近の技術トレンド、他の主要なソフトウェア システムが実装中に直面する問題などを調べていると思います。そこで私はそれを実行しましたが、最も注目を集めたのは、OTP を生成することだけが機能する otp-lib や otp-generator のようなライブラリでした。 SMS や電子メールでの送信などの残りのタスクは、引き続き他の手段で行う必要があります。このようなライブラリが存在することを知った後で頭に浮かぶ最初の疑問は、ワンライナーを書くだけで済むのに、なぜわざわざライブラリを使用して OTP を生成する必要があるのか​​ということです。

const otp = Math.ceil(Math.random() * 10000)
ログイン後にコピー

このブログ投稿では、OTP ジェネレーターの小規模な研究中に学んだこと、OTP を生成するために Math.random() を使用するのがなぜ悪い考えなのか、OTP を生成する他の方法は何か、ライブラリを使用する理由について説明します。このようなタスクに使用する必要がありますか?

乱数の種類

乱数には主に 2 種類があります:

  • 擬似乱数 (PRN)
  • 暗号化乱数 (CRN)。

擬似乱数

擬似乱数は、シードと呼ばれる初期値を取得し、ランダムに見える一連の数値を生成するアルゴリズムによって生成されます。ただし、アルゴリズムは決定論的です。つまり、シードとアルゴリズムがわかっていれば、シーケンス内の次の数値を予測できます。 Javascript の Math.random() と Python のrandom.randInt() は、擬似乱数生成器の例です。

暗号乱数

暗号乱数は、予測不可能なプロセスによって生成され、再現したり推測したりすることはできません。これらは通常、大気騒音、熱雑音、量子効果などの物理現象に基づいています。

Math.random() はどのように機能するのでしょうか?

Javascript エンジンが異なると、乱数を生成する際の動作が少し異なりますが、基本的にはすべて単一のアルゴリズム XorShift128+ によって決まります。

XorShift は決定論的アルゴリズムであり、高速な非線形変換ソリューションとして加算を使用します。乗算を使用する他のアルゴリズムと比較して、このアルゴリズムは高速です。また、メルセンヌ ツイスター (Python のランダム モジュールで使用) よりも失敗する可能性が低くなります

アルゴリズムは 2 つの状態変数を受け取り、XOR とシフトを適用して、更新された状態変数の合計を整数で返します。通常、状態はシステム クロックを使用してシードされます。これは、システム クロックが一意の番号の優れたソースであるためです。

JavaScript での XOR シフト プラスの実装は次のようになります:

let state0 = 1;
let state1 = 2;
function xorShiftPlus() {
    let s1 = state0; 
    let s0 = state1; 
    state0 = s0;  
    s1 ^= s1 << 23;
    s1 ^= s1 >> 17;
    s1 ^= s0;
    s1 ^= s0 >> 26;
    state1 = s1;
    return state0 + state1;
}
ログイン後にコピー

返された整数は、定数との OR 演算を使用して double に変換されます。詳細な実装は、Chrome ソース コードで確認できます。

Math.random() で生成された乱数を予測する方法

Math.random() の結果を予測するのは困難ですが、完全に不可能というわけではありません。アルゴリズムを理解していれば、state0 と state1 の値がわかっていれば、同じ乱数を簡単に再生成できます。

XorShift128+ のリバース エンジニアリング Z3 定理証明器を使用すると、サーバーによって生成された 3 つの連続する乱数を提供することで、state0 と state1 の値を見つけることができます。

Z3 ソルバーの実装はここにあります。

ここで問題は、これら 3 つの乱数をサーバーから取得する方法です。それが難しい部分ですが、次のような場合に取得できます:

  1. If an API returns a randomly generated number in its response or headers, it can easily be obtained by sending requests at set intervals.
  2. API documentation like OpenAPI/Swagger in modern applications is generated on the server. Sometimes their responses can contain an example value that uses a random number.
  3. With frameworks like NextJS that use server-side rendering while also being capable of handling backend API integrations, there are high chances of getting randomly generated numbers from the content served by them.

Another approach to exploit a random number is using the fact that Math.random() only returns numbers between 0 and 1 with 16 decimal places. This means that there are only 10^16 possible values that Math.random() can return. This is a very small space compared to the space of possible OTPs. if your OTP has 6 digits, there are 10^6 possible values. This visualizer shows that there is a pattern to the numbers generated. Using it, the possibilities can be reduced by 30%. Therefore, if you can guess or brute-force some of the digits of the OTP, you can reduce the space of possible values and increase your chances of finding the correct OTP.

Generating a Cryptographic Random Number in NodeJS

As mentioned previously, cryptographic random numbers are non-deterministic because they depend on the physical factors of a system. Every programming language can access those factors using low-level OS kernel calls.

NodeJS provides its inbuilt crypto module, which we can use to generate randomBytes and then convert them to a number. These random bytes are cryptographic and purely random in nature. The generated number can easily be truncated to the exact number of digits we want in OTP.

import * as crypto from 'crypto';
const num = parseInt(crypto.randomBytes(3).toString('hex'), 16)
// num.toString().slice(0,4)  // truncate to 4 digits
ログイン後にコピー

NodeJS 14.10+ provides another function from crypto to generate a random number in a given min-max range.

crypto.randomInt(1001, 9999)
ログイン後にコピー

Even after knowing the vulnerability of Math.random() and finding a more secure way to generate a random number cryptographically, we still remain with the same question from the beginning. Why do we have to go to such lengths to use a library to generate OTP when all we have to do is write a one-liner?

Before answering this questions, let's take a look at what is the inconvenience faced while handling and storing an OTP. The problem with using the above method to generate OTPs is that you have to store them in the database in order to verify them later. Storing the OTP in the database is not a good practice for the following reasons:

  1. Storing OTPs in the database creates a lot of garbage data that has to be cleaned up periodically. OTP means a one-time password that can expire after a single use. It can also expire if not used for a specific duration or a new OTP is requested without using the previous one. This mainly adds unnecessary overhead to the database operations for maintaining valid OTPs while also consuming storage space.
  2. Storing OTPs in the database poses a security risk if the database is compromised. An attacker who gains access to the database can read the OTPs and use them to bypass the authentication or verification process. This can lead to account takeover, identity theft, or fraud.
  3. Storing OTPs in the database makes them vulnerable to replay attacks. A replay attack is when an attacker intercepts an incoming valid OTP and uses it again before it expires. This can allow the attacker to perform unauthorised actions or access sensitive information.

What do the OTP libraries do differently?

The OTP libraries use different algorithms and techniques to generate and verify OTPs that behave similarly to a Cryptographic random OTP, while also removing the overhead to store the OTP in a database.

There are mainly two types of OTP implementation techniques.

HOTP

HOTP stands for HMAC-based One-Time Password. It is an algorithm that generates an OTP based on a secret key and a counter. The secret key is a random string that is shared between the server and the user. The counter is an integer that increments every time an OTP is generated or verified.

The algorithm works as follows:

• The server and the user generate the same OTP by applying a cryptographic hash function, such as SHA-1, to the concatenation of the secret key and the counter.
• The server and the user truncate the hash value to obtain a fixed-length OTP, usually 6 or 8 digits.
• The user sends the OTP to the server for verification.
• The server compares the OTP with its own generated OTP and verifies it if they match.
• The server and the user increment their counters by one.

HOTP は、Yubikey などのハードウェア トークン ベースの認証で主に使用されます。 Yubikey は基本的に、コンピュータまたは電話に物理的に接続できるプログラムされたハードウェア キーです。 SMS や電子メールからコードを受け取る代わりに、Yubikey のボタンを押すだけで本人確認と認証を行うことができます。

HOTP の利点は次のとおりです。

• OTP はその場で生成および検証できるため、データベースに保存する必要はありません。
• 予測不可能かつ不可逆的な暗号化ハッシュ関数を使用するため、疑似乱数に依存しません。
• 各 OTP は 1 回だけ有効であるため、リプレイ攻撃に耐性があります。

HOTP の欠点は次のとおりです。

• サーバーとユーザーのカウンター間の同期が必要です。ネットワークの遅延、送信エラー、デバイスの紛失などにより同期が取れていない場合、検証は失敗します。
• 新たに生成された HOTP が使用されない限り有効ですが、脆弱性となる可能性があります。
• 秘密鍵を配布および保管するには安全な方法が必要です。秘密キーが漏洩または盗難された場合、OTP が侵害される可能性があります。

TOTP

TOTP は、タイムベースのワンタイム パスワードの略です。これは、秘密キー、タイムスタンプ、エポックに基づいて OTP を生成するアルゴリズムです。

  • 秘密キーは、サーバーとユーザーの間で共有されるランダムな文字列です。 SHA1( "secretvalue" + user_id ) を生成することで、ユーザーごとに一意に作成できます。
  • タイムスタンプは、現在時刻を秒単位で表す整数です
  • エポックとは、アルゴリズムが同じ結果を生成する期間です。一般に、30 秒から 1 分の間に保持されます。

アルゴリズムは次のように機能します:
• サーバーはユーザーの秘密キーを決定し、Authenticator アプリなどの媒体を介してそれを共有します。
• サーバーは OTP を直接生成し、メールまたは SMS でユーザーに送信することも、オーセンティケーターを使用して共有キーを使用して OTP を生成するようにユーザーに要求することもできます。
• ユーザーは、メールまたは SMS で受信した OTP を直接送信することも、2FA の場合は一定の時間枠で認証アプリで OTP を生成することもできます。
• サーバーは OTP を独自に生成した OTP と比較し、それらがエポック時間範囲内で十分に近いかどうかを検証します。

TOTP の利点は次のとおりです。

• OTP はその場で生成および検証できるため、データベースに保存する必要はありません。
• 予測不可能かつ不可逆的な暗号化ハッシュ関数を使用するため、疑似乱数に依存しません。
• 各 OTP は短期間のみ有効であるため、リプレイ攻撃に対して耐性があります。
• サーバーとユーザーのタイムスタンプ間の同期は必要ありません。適度に正確なクロックを持っている限り、OTP を独立して生成および検証できます。

TOTP の欠点は次のとおりです。

• 秘密鍵を配布および保存するには安全な方法が必要です。秘密キーが漏洩または盗難された場合、OTP が侵害される可能性があります。
• サーバーとユーザーの両方にとって信頼できる時間源が必要です。時計が歪んでいたり改ざんされている場合、検証は失敗します。
• サーバーはリクエストの処理における時間のずれや遅延を考慮する必要があるため、クライアントよりもわずかに長いエポックを維持する必要があります。

結論

OTP に関するちょっとした調査を通じて、Math.random() が予測、悪用、再生できることを知りました。また、OTP をデータベースに保存するのは良い習慣ではないこともわかりました。

TOTP は安全で効率的な OTP を生成し、検証することもできます。オンラインだけでなくオフラインでも OTP を生成でき、同期やストレージを必要とせず、リプレイ攻撃に耐性があります。したがって、ベスト プラクティス、セキュリティ、信頼性に関する懸念のほとんどが解決されます。

以上がMath.random() を実行するだけで済むのに、なぜ OTP ライブラリを使用するのでしょうか。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

独自のJavaScriptライブラリを作成および公開するにはどうすればよいですか? 独自のJavaScriptライブラリを作成および公開するにはどうすればよいですか? Mar 18, 2025 pm 03:12 PM

記事では、JavaScriptライブラリの作成、公開、および維持について説明し、計画、開発、テスト、ドキュメント、およびプロモーション戦略に焦点を当てています。

ブラウザでのパフォーマンスのためにJavaScriptコードを最適化するにはどうすればよいですか? ブラウザでのパフォーマンスのためにJavaScriptコードを最適化するにはどうすればよいですか? Mar 18, 2025 pm 03:14 PM

この記事では、ブラウザでJavaScriptのパフォーマンスを最適化するための戦略について説明し、実行時間の短縮、ページの負荷速度への影響を最小限に抑えることに焦点を当てています。

フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? フロントエンドのサーマルペーパーレシートのために文字化けしたコード印刷に遭遇した場合はどうすればよいですか? Apr 04, 2025 pm 02:42 PM

フロントエンドのサーマルペーパーチケット印刷のためのよくある質問とソリューションフロントエンド開発におけるチケット印刷は、一般的な要件です。しかし、多くの開発者が実装しています...

ブラウザ開発者ツールを使用してJavaScriptコードを効果的にデバッグするにはどうすればよいですか? ブラウザ開発者ツールを使用してJavaScriptコードを効果的にデバッグするにはどうすればよいですか? Mar 18, 2025 pm 03:16 PM

この記事では、ブラウザ開発者ツールを使用した効果的なJavaScriptデバッグについて説明し、ブレークポイントの設定、コンソールの使用、パフォーマンスの分析に焦点を当てています。

ソースマップを使用して、マイナイドJavaScriptコードをデバッグするにはどうすればよいですか? ソースマップを使用して、マイナイドJavaScriptコードをデバッグするにはどうすればよいですか? Mar 18, 2025 pm 03:17 PM

この記事では、ソースマップを使用して、元のコードにマッピングすることにより、Minified JavaScriptをデバッグする方法について説明します。ソースマップの有効化、ブレークポイントの設定、Chrome DevtoolsやWebpackなどのツールの使用について説明します。

Javaのコレクションフレームワークを効果的に使用するにはどうすればよいですか? Javaのコレクションフレームワークを効果的に使用するにはどうすればよいですか? Mar 13, 2025 pm 12:28 PM

この記事では、Javaのコレクションフレームワークの効果的な使用について説明します。 データ構造、パフォーマンスのニーズ、スレッドの安全性に基づいて、適切なコレクション(リスト、セット、マップ、キュー)の選択を強調しています。 コレクションの使用を効率的に最適化します

初心者向けのタイプスクリプト、パート2:基本データ型 初心者向けのタイプスクリプト、パート2:基本データ型 Mar 19, 2025 am 09:10 AM

エントリーレベルのタイプスクリプトチュートリアルをマスターしたら、TypeScriptをサポートするIDEで独自のコードを作成し、JavaScriptにコンパイルできるはずです。このチュートリアルは、TypeScriptのさまざまなデータ型に飛び込みます。 JavaScriptには、NULL、未定義、ブール値、数字、文字列、シンボル(ES6によって導入)とオブジェクトの7つのデータ型があります。 TypeScriptはこれに基づいてより多くのタイプを定義し、このチュートリアルではすべてを詳細に説明します。 ヌルデータ型 JavaScriptのように、Typescriptのnull

chart.js:パイ、ドーナツ、バブルチャートを始めます chart.js:パイ、ドーナツ、バブルチャートを始めます Mar 15, 2025 am 09:19 AM

このチュートリアルでは、chart.jsを使用してパイ、リング、およびバブルチャートを作成する方法について説明します。以前は、4つのチャートタイプのchart.js:ラインチャートとバーチャート(チュートリアル2)、およびレーダーチャートと極地域チャート(チュートリアル3)を学びました。 パイとリングチャートを作成します パイチャートとリングチャートは、さまざまな部分に分かれている全体の割合を示すのに理想的です。たとえば、パイチャートを使用して、サファリの男性ライオン、女性ライオン、若いライオンの割合、または異なる候補者が選挙で受け取る票の割合を示すことができます。 パイチャートは、単一のパラメーターまたはデータセットの比較にのみ適しています。パイチャートのファンの角度はデータポイントの数値サイズに依存するため、パイチャートは値のあるエンティティをゼロ値で描画できないことに注意してください。これは、割合がゼロのエンティティを意味します

See all articles