web-dev-qa-db-ja.com

UUID.randomUUID()はワンタイムパスワードとしての使用に適していますか?

前に説明した のように、確認メールには、確認リンクに一意の(実際には)推測できないコード(基本的には ワンタイムパスワード -)が含まれている必要があります。

ID.randomUUID()docs 言う:

UUIDは、暗号的に強力な疑似乱数ジェネレーターを使用して生成されます。

これは、適切に実装されたJVMのUUIDランダムジェネレーターが、一意の(実際には)推測できないOTPとしての使用に適していることを意味しますか?

24
cqcallaw

番号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);
    }
}
8
jchook

uUIDを定義し、APIドキュメントからリンクされている [〜#〜] rfc [〜#〜] を読むと、UUIDのすべてのビットが実際にランダムであるとは限らないことがわかります。 (「バリアント」と「バージョン」はランダムではありません)。したがって、タイプ4 UUID(使用する予定の種類)が正しく実装されている場合、合計サイズ128ビットのうち、122ビット(この実装では安全)のランダム情報が含まれている必要があります。

そうです、「安全な」ジェネレーターからの122ビットの乱数と同様に機能します。 しかし短い値には十分な量のランダム性が含まれている可能性があり、ユーザーにとっては簡単かもしれません(おそらく私はまだ電子メールを読んでいる唯一の昔ながらの人ですターミナルではありますが、行をまたがる確認URLは煩わしいです....)。

14
andrew cooke

はい、Java.util.UUIDを使用することは問題ありません、randomUUIDメソッドは暗号的に secure ソースから生成します。言う必要のあることはこれ以上ありません。

これが私の提案です:

  1. URL引数として巨大なパスワードを含むリンクをユーザーに送信します。
  2. ユーザーがリンクをクリックしたときに、引数が正しいかどうか、およびユーザーがログインしているかどうかを判断するようにバックエンドを記述します。
  3. 発行されてから24時間後にUUIDを無効にします。

これには多少の作業が必要ですが、堅牢で安全なシステムを作成することに本当に関心がある場合は必要です。

5
Alex Lockwood

確認リンクのランダムコードのポイントは、攻撃者が値を推測または予測できないようにする必要があるということです。ご覧のとおり、確認リンクへの正しいコードを見つけるために、128ビット長のUUIDは、2 ^ 128の異なる可能なコード、つまり、340,282,366,920,938,463,463,374,607,431,768,211,456の可能なコードを生成します。あなたの確認リンクは核兵器を発射するためのものではないと思いますよね?これは、攻撃者が推測するのに十分なほど困難です。安全です。

-更新-

提供されている暗号的に強い乱数ジェネレーターを信頼できない場合は、UUIDコードを使用してさらに予測不可能なパラメーターを配置し、それらをハッシュすることができます。例えば、

コード= SHA1(UUID、プロセスPID、スレッドID、ローカル接続ポート番号、CPU温度)

これにより、予測がさらに困難になります。

0
Fang-Pen Lin

CSRNGによって生成された場合、それは予測不可能であるため、使用できます。

しかし、暗号化されていない確認メールを送信すると、問題が無駄になります。攻撃者がシステムからRNGの結果を予測する手段を持っている場合、攻撃者もメールを傍受できる可能性があります。

UUIDも長い文字列です(128ビットの場合は通常Base64(22文字)またはBase16エンコード(32文字))-システムがどれほどユーザーフレンドリーになるかを考えてください。個人的には、CSRNGを使用して8文字の英数字をランダムに選択し、それらを返します。

0
Dai