web-dev-qa-db-ja.com

Java UUID.randomUUID()またはSecureRandom for id id segment?

Java URLベースの一意の識別子を必要とするシステムを構築する場合、UUID.randomUUID()またはSecureRandomの方が適していますか?

より具体的には、POST /itemsを呼び出すと、新しく作成された201 Createdへの場所とともに/items/{id}が返されます。ここで、{id}はランダムな文字列であり、URLは期間限定の匿名HTTPリクエスト。

このコードは、128ビットのランダム性を持つ22文字の文字列(例:B-KEPLFdWNZ4JTUnnEq3Og)を返します。

SecureRandom random = new SecureRandom();
byte bytes[] = new byte[16];
random.nextBytes(bytes);
Encoder encoder = Base64.getUrlEncoder().withoutPadding();
String token = encoder.encodeToString(bytes);
System.out.println(token);

ID.randomUUID() は、「タイプ4(疑似ランダムに生成された)UUIDを取得する静的ファクトリーです。UUIDは、暗号学的に強力な疑似乱数ジェネレーターを使用して生成されます。」このコードは、122ビットのランダム性を持つ36文字の文字列(例:f0803ce7-8e3d-421a-8126-e5a0bd0a865f)を返します。

UUID randomUUID = UUID.randomUUID();
System.out.println(randomUUID);

これらの識別子は、固定長のCHARタイプとしてリレーショナルデータベースにも保持されます。

7
Kevin Hakanson

ランダムビットの生の量に関しては、はい。

JavaのランダムUUIDのソース 生成を見ると、実際にSecureRandomクラスを使用して生のバイトを生成していることがわかります。したがって、ランダム性の「品質」が変わることはありません。

あと6ビットあるという事実は、技術的には、ブルートフォースによる複製をより困難にします。 IDに関するWikipediaの記事 は、その背後にある数学についての適切な説明があります。それを引用するには:

次の100年間、毎秒10億のUUIDを生成する[A] fterの場合、複製が1つだけ作成される確率は約50%になります。

これらのリンクがたとえば24時間で期限切れになる場合、これは心配する必要がある非常に小さな問題であり、それは122ビットでのみ発生します。

さて、より多くのビットは攻撃者が衝突をブルートフォースすることをより困難にするでしょうか?承知しました!その価値はありますか?多分...しかし多分そうではない。あなただけが本当にあなたのユースケースに何が正しいかを決めることができます。

ブルートフォーシングによる衝突が、平均して、宇宙の熱による死の推定時間よりも長くかかる点に達したとき、それは少し船外にあるかもしれません。これは、ハッカーがブルートフォースよりもストレージのセキュリティを危険にさらすことについて心配する必要があるという領域に達しています(そして、正直なところ、UUIDを使用しても、問題が発生します)。結局のところ、総当たり攻撃の難しさは、彼らが別の方法を見つけることができるかどうかには関係ありません。本当に心配なら、ストレージは安価です-SecureRandomで生成した256ビットの文字列を格納し、それを良いと呼びます。しかし、他のすべてのものが適切にセキュリティ保護されていることを確認してください。そうしないと役に立たなくなります。

9
childofsoong

まあ、原則として、UUIDと暗号化RNGは2つの異なることを約束します。

  1. UUIDは重複の可能性が低いことを約束します;
  2. 暗号化RNGは、悪意のある敵に予測不可能性を約束します。

#2が問題になる場合は、暗号化RNGを使用するようにします。たとえば、悪意のある攻撃者が短期間に多くのUUIDを要求できる場合、他のユーザーの要求に与えられるUUIDを予測するのに十分な情報を取得することが懸念される場合。

偶然にも、JavaのUUID.randomUUID()メソッドは暗号化RNGを使用するため、その点で安全である必要があります。しかし、そのリスクは、後でコードを見る開発者が、あなたのintentに、一意性だけでなく安全な暗号ランダム選択が含まれていることを理解できない可能性があることです。たとえば、誰かが他の言語または暗号化RNGを使用しないUUIDライブラリを使用してその特定のモジュールを書き換え、除外するつもりの予測ベースの攻撃にさらされる可能性があります。したがって、暗号化セキュリティが本当に重要な要素である場合、SecureRandomを明示的に使用することで、それを明白にする方法でコードを記述しようとします。 (セキュリティ上重要なコードは非常に明確である必要があります!)

私が注意したのは、セキュリティではなく一意性である場合は、先に進んでUUID.randomUUID()を使用します。

7
Luis Casillas