前に説明したように、確認メールの確認リンクには、一意で (事実上) 推測不可能なコード (基本的にはワンタイム パスワード) が含まれている必要があります。
UUID.randomUUID() ドキュメントには次のように書かれています。
UUID は、暗号的に強力な疑似乱数ジェネレーターを使用して生成されます。
これは、適切に実装された JVM の UUID 乱数発生器が、一意で (実際には) 推測不可能な OTP として使用するのに適していることを意味しますか?
前に説明したように、確認メールの確認リンクには、一意で (事実上) 推測不可能なコード (基本的にはワンタイム パスワード) が含まれている必要があります。
UUID.randomUUID() ドキュメントには次のように書かれています。
UUID は、暗号的に強力な疑似乱数ジェネレーターを使用して生成されます。
これは、適切に実装された JVM の UUID 乱数発生器が、一意で (実際には) 推測不可能な OTP として使用するのに適していることを意味しますか?
UUID を定義し、API ドキュメントからリンクされているRFCを読むと、UUID のすべてのビットが実際にはランダムではないことがわかります (「バリアント」と「バージョン」はランダムではありません)。したがって、タイプ 4 UUID (使用する予定の種類) は、正しく実装されている場合、128 ビットの合計サイズのうち、122 ビットの (この実装では安全な) ランダム情報を持つ必要があります。
はい、「安全な」ジェネレーターからの122ビットの乱数と同様に機能します。 しかし、より短い値には十分な量のランダム性が含まれている可能性があり、ユーザーにとってより簡単になる可能性があります (端末で電子メールを読んでいる昔ながらの人間は私だけかもしれませんが、確認 URL が複数の行にまたがってラップするのは面倒です....) .
いいえ。UUID仕様によると:
UUID を推測するのは難しいと思い込まないでください。たとえば、セキュリティ機能 (単に所有するだけでアクセスが許可される識別子) として使用しないでください。予測可能な乱数ソースは、状況を悪化させます。
また、UUID には 16 文字 (0 から F) しかありません。SecureRandom
(@erickson に感謝) を使用して、はるかにコンパクトで明示的に安全なランダム パスワードを生成できます。
import java.security.SecureRandom;
import java.math.BigInteger;
public final class PasswordGenerator {
private SecureRandom random = new SecureRandom();
public String nextPassword() {
return new BigInteger(130, random).toString(32);
}
}
PS
UUID をセキュリティ トークンとして使用すると問題が発生する可能性があることの明確な例を挙げたいと思います。
uuid-randomでは 、ランダムなバイトを巧妙な方法で内部的に再利用し、予測可能な UUID に導くことで、大幅な速度向上を発見しました。私たちは変更をリリースしませんでしたが、RFC はそれを許可しており、そのような最適化は気づかれずに UUID ライブラリに忍び込む可能性があります。
はい、aを使用してjava.util.UUID
も問題ありません。randomUUID
メソッドは、暗号的に安全なソースから生成されます。言う必要のあることはこれ以上ありません。
これが私の提案です:
これには多少の作業が必要ですが、堅牢で安全なシステムを作成することに本当に関心がある場合は必要です。
確認リンクのランダム コードのポイントは、攻撃者が値を推測または予測できないことです。ご覧のとおり、確認リンクへの正しいコードを見つけるために、128 ビット長の UUID は 2^128 の異なるコードを生成します。あなたの確認リンクは核兵器を発射するためのものではないと思いますよね? これは、攻撃者が推測するのが非常に困難です。安全です。
- アップデート -
提供されている暗号的に強力な乱数ジェネレーターを信頼できない場合は、UUID コードにさらに予測不可能なパラメーターを追加して、それらをハッシュすることができます。例えば、
code = SHA1(UUID、プロセスPID、スレッドID、ローカル接続ポート番号、CPU温度)
これにより、予測がさらに難しくなります。
特定の入力からではなくランダムに生成されるため(つまり、ユーザー名などを入力していないため)、これは適切であると思います。したがって、このコードを複数回呼び出すと、異なる結果が得られます。それは128ビットの鍵であると述べているため、解読するのに十分な長さです.
次に、このキーを使用して値を暗号化しますか?それとも、これを実際のパスワードとして使用する予定ですか? とにかく、キーをキーボードで入力できる形式に再解釈する必要があります。たとえば、Base64 または Hex 変換を行うか、何らかの方法で値を英数字にマップします。そうしないと、ユーザーはキーボードに存在しないバイト値を入力しようとします。
作業中のアプリケーションにも同じものを実装していたので、ワンタイムパスワードとしては完璧です。さらに、あなたが共有したリンクがすべてを物語っています。
java.util.UUID は問題ないと思います。詳細については、次の記事を参照してください。