2012-06-14 14 views
19

previous discussedとして確認メールには、確認リンクにユニークで(実際には)推測できないコード(本物はone-time password)が含まれている必要があります。UUID.randomUUID()はワンタイムパスワードとして使用するのに適していますか?

The UUID.randomUUID() docsは言う:

UUIDは、暗号強度の高い擬似ランダム 数発生器を使用して生成されます。

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

+2

あなたがより少ない数字でより多くのセキュリティを提供する[別の質問への私の答え](http://stackoverflow.com/a/41156/3474)に興味があるかもしれません。 – erickson

+0

また、ここでの議論を参照してください:https://security.stackexchange.com/questions/890/are-guids-safe-for-one-time-tokens –

答えて

4

: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); 
    } 
} 
+5

UUID仕様!= Java実装です。この仕様ではUUIDを安全にする必要はありませんが、Java実装は実際には122ビットの安全なランダム性を提供します。 http://stackoverflow.com/a/7532965/47528も参照してください。 – Dan

+0

暗号ライブラリを明示的に使用することをお勧めします。 – jchook

+1

はい、間違いなく;-)セキュリティに関しては、慎重で明示的な方がよいでしょう。軍用グレードのシステムではUUID.randomUUID()を使用しません。しかし、問題が「私はトークンにUUID.randomUUID()を使ってセキュリティホールを導入していますか?答えはいいえです。 – Dan

-1

これは、特定の入力ではなくランダムに生成されるので(つまり、ユーザー名などを入力しているわけではないため)、適切であると考えます。このコードを複数回呼び出すと、異なる結果が得られます。それはその128ビットの鍵であることを示しています。

このキーを使用して値を暗号化するか、これを実際のパスワードとして使用する予定ですか?それにかかわらず、キーをキーボードで入力できる形式に再解釈する必要があります。たとえば、Base64またはHex変換を行うか、何らかの方法でアルファ数値に値をマッピングします。そうしないと、ユーザーはキーボードに存在しないバイト値を入力しようとします。

+0

電子メールの受信者がクリックする確認URLに確認コードを埋め込む予定です確認を完了します。ユーザーの入力は必要ありません。 – cqcallaw

-1

私は働いているアプリケーションのために同じものを実装していたとしても、ワンタイムパスワードとしては完璧です。さらに、あなたが共有したリンクは、それをすべて言います。

0

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

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

UUIDも長い文字列(128ビット、通常はBase64(22文字)またはBase16エンコード(32文字))です。システムの使い勝手を考えます。個人的には、8文字の英数字をランダムに選択して返すためにCSRNGを使用します。

+0

RNGの結果を予測できないと思うのは、電子メールの遮断機能を意味しています.RNGが実装されていないことを意味します:)また、長さ、確認を完了するために訪れなければならない確認URLにコードを埋め込むことを期待しているからです。 – cqcallaw

0

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

- アップデート -

あなたが提供暗号的に強い乱数ジェネレータを信用していない場合は、UUIDコードといくつかのより多くの予測不可能なパラメータを入れて、それらをハッシュすることができます。例えば、

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

これは予測することがさらに難しくします。

+2

生成されたビットの数だけでは予測できません。 'java.util.Random'は128ビットのデータを取得するために使用できますが、それは安全なものではありません。 –

+2

今日、人々はお金を稼ぐための攻撃をしており、予算は限られています。何も破壊できません。どのように安全なはずですか?安全保障のポイントは、それを壊すのにどれくらいの費用がかかり、彼らが得られる利益はどれくらいですか?共通のウェブサイトの確認リンクのコードであれば、十分安全です。これが核兵器のコードであれば、私はそう言わないだろう。私のために、安全の定義は - それを打破するためのコスト>>収益の期待。それを壊すにはあまりにも多くの費用がかかり、あなたがそれを壊すことによって得られる収入がほとんどない場合、それは安全です。 –

+0

@LouisWasserman 'java.util.Random'と' UUID.randomUUID() 'を比較することはできません –

13

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

はい、それは「安全な」ジェネレータからの122ビットの乱数と同様に機能します。 でもより短い値には十分な量のランダム性が含まれている可能性があります(おそらく、端末でメールを読む唯一の古風な人ですが、行を横切る確認URLは面倒です... )。

+0

他にも同様の回答がありましたが、これは最も完全で有益なようでした。ありがとう。 – cqcallaw

+7

実際には、RFCはセキュリティトークンとしてUUIDを使用することに対して明示的に注意しています。「UUIDを推測するのは難しいとは考えておらず、セキュリティ機能(単なる所有権がアクセスを許可する識別子)として使用しないでください。安全なRNG **を使用して**生成されたUUID4は、ほとんど推測が不可能ですが、標準では安全でないRNG(!)が明示的に許可されています。 http://tools.ietf.org/html/rfc4122#section-6(非常に古いコメントを復活させる謝罪ですが、セキュリティは誰もが心配しています) –

4

はい、java.util.UUIDを使用しても問題ありません。それ以上のことは言えません。ここで

は私の提案です:

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

これはいくつかの作業を必要としますが、堅牢で安全なシステムを作成することに本当に気を付ける必要があります。 UUID specによると

+1

あなたの提案は私がまもなくUUIDを無効にすることを除いて、私のまさに意図です確認URLが訪問され、確認が完了すると、 – cqcallaw

関連する問題