3

いくつかのものをスケジュールし、識別子をスケジュールされたタスクにいくつかの異物に返すシステムがあります。推測できないユニークなトークンの生成

identifier = MyLib.Schedule(something) 
# Nah, let's unschedule it. 
MyLib.Unschedule(identifier) 

私は、パターンのこの種の内部コードで大量に使用し、私はいつも識別子として普通の整数を使用します。ユーザーは、基本的にこれを行うだろう。しかし、信頼できないコードによって識別子が使用されている場合、悪意のあるユーザーが単一のUnschedule(randint())を実行することによってシステム全体を破壊する可能性があります。

実際にスケジュールした識別子のスケジュールを解除できるようにするには、コードのユーザーが必要です。

私が考えることができる唯一の解決策は、識別子として64ビットの乱数を生成し、どちらの識別子が現在配布されているかを追跡して、恐ろしく重複しないようにすることです。または128ビット? 「これは十分にランダムで、重複は起こらない」と言えるのはいつですか?

さらに、これを行うより賢明な方法がありますか?ジェネレータが容易に追跡できる(重複を避ける)識別子トークンを生成する方法はありますか?しかし、受信者に乱数と区別できませんか?

EDIT - 受け入れ答えに基づくソリューション:

from Crypto.Cipher import AES 
import struct, os, itertools 

class AES_UniqueIdentifier(object): 
    def __init__(self): 
     self.salt = os.urandom(8) 
     self.count = itertools.count(0) 
     self.cipher = AES.new(os.urandom(16), AES.MODE_ECB) 
    def Generate(self): 
     return self.cipher.encrypt(self.salt + 
            struct.pack("Q", next(self.count))) 
    def Verify(self, identifier): 
     "Return true if identifier was generated by this object." 
     return self.cipher.decrypt(identifier)[0:8] == self.salt 
+0

ほとんどの(擬似)乱数ゲラータは、常に同じ種子でジェネレータを初期化することによって、生成されたものを追跡することができます。それは、あなたが同じマシンでそれを使用している場合、正確に同じ番号のシーケンスを生成します。したがって、定数でなければならないシードと生成された識別子の数を計算することにより、以前に生成された数があるかどうかを確認することができます。これは簡単な方法です。識別子をリセットすることができれば(すべてがスケジュールされていなかった場合など)大量の番号を追跡する必要がある場合は非常に遅くなります。 – Trinidad

+0

安全なシステムでUnschedule()を実装するコードはありますか?クライアントが検査できないものは?そうしないと、クライアントが発見できない秘密の値を維持することは期待できません。 –

+0

@GregS:はい、基本的に。クライアントコードはサンドボックス化されています。 @トリニダード:システムは、大きな数の数を処理できる必要があります。少なくとも私は毎秒10000の数字を言うだろう。 (Unscheduleはまれなイベントですが)。 – porgarmingduod

答えて

3

アクティブIDの数によっては、64ビットが少なすぎることがあります。 birthday paradoxによって、32ビットの識別子から期待される保護のレベルが本質的に上がります。

さらに、これらを作成する最も良い方法は、SHA-1やMD5などの塩漬けされたハッシュ関数を使用したり、フレームワークが既に持っているものをランダムに選択した塩(秘密にしておく)とにかく上記の理由で正確に128ビット。より長いハッシュ値を作成するものを使用する場合、実際には切り捨てる理由はありません。

識別子を作成するには、保存しないでチェックすることができます。同じ64ビットパターンを2回(合計128ビット)検出するなど、検出が簡単なものを使用し、一定の秘密鍵でAESなどを使用して暗号化しますブロックサイズが128ビット(またはあなたが選んだもの)の他の暗号。ユーザーが何らかの主張されたキーを送信した場合、解読して簡単にパターンを確認します。

+1

ああ、それはとても賢いです。私は生成された識別子に簡単に署名する方法を強く疑っていましたが、それを自分で考えるには十分ではないことを強く証明するのに十分な暗号を知っていました。実際には、私の質問は本当に "一意に生成された識別子に署名する"です。 – porgarmingduod

0

これは、通常のWebアプリケーションでセッション識別子を扱うと同じ問題です。予測可能なセッションIDは、簡単にセッションハイジャックにつながる可能性があります。

セッションIDの生成方法を見てみましょう。ここでは代表的なPHPSESSIDクッキーの内容は:あなたは何のブルートフォース攻撃が可能ではない死んだことを確認したい場合は

bf597801be237aa8531058dab94a08a9 

、後方計算を行う:クラッカーが毎秒どのように多くの試みを行うことができますか?ランダムな時点でいくつの異なる一意のIDが使用されていますか?合計でいくつのIDがありますか?クラッカーが蓋をするのにどれくらいの時間がかかりますか、つまりidsの総容量の1%と言いますか?それに応じてビット数を調整します。

0

あなたは識別子を十分に長くしているので、推測できません。さらに、トークンが使用されていない場合は、Unscheduleが1秒間待機するようにして、ブルートフォース攻撃を実行できなくなります。他の答えと同じように、WebアプリケーションのセッションIDはまったく同じ問題であり、セッションIDは64のランダムな文字が長いことが分かりました。

0

分散型またはローカル環境でこのパターンが必要ですか?

ローカルの場合、ほとんどのオブジェクト指向言語はオブジェクトIDの概念をサポートする必要があるため、不透明なハンドルを作成する場合は新しいオブジェクトを作成してください。

handle = new Object(); // in Java 

他のクライアントはこれを偽造できません。

配布環境でこれを使用する必要がある場合は、セッションごとにハンドルをプールして、外部セッションで盗まれたハンドルを使用することはできません。

1

あなたはこの問題を考えすぎるかもしれないように私に聞こえます。これは、GUID/UUIDのアプリケーションのように100%発音します。 Pythonもa built in way to generate themです。 GUID/UUIDの全体のポイントは、衝突の確率が天文学的であることです。暗号化されたトークンの代わりに文字列を使用することで、検証ステップで解読操作をスキップできます。私はこれにより、キーマネージメントに関して遭遇する可能性のある問題も完全に排除され、プロセス全体のスピードが向上すると考えています。

EDIT:UUIDで

、あなたの検証方法は、ただ与えられたUUIDと格納されている1つの間の比較になります。 2つのUUIDの間の衝突の確率は非常に低いので、誤認について心配する必要はありません。あなたの例では、同じオブジェクトが、第三者が格納されたデータを読み取ることなく、暗号化と復号の両方を行っているようです。この場合、暗号化されたデータを渡すことで何も得られませんが、渡すビットが推測しにくいという点が異なります。私は、UUIDは暗号化操作のオーバーヘッドなしで同じ利点を与えると思います。

+0

Uuidについて知ることは有益であり、私は将来それを必ず使用します。ありがとう。しかし、私は「検証ステップで復号化操作をスキップする」ことができないと思っています。最初にUUIDを検証することはできません。 2つのソリューションは同じではなく、さまざまなニーズに対応しています。私は両方のアプローチを知ってうれしいです。 – porgarmingduod

+0

まあ、もちろん、duhは、UUIDを格納して確認することができます。これらが異なる特性を持つ2つの異なるソリューションであるという事実は変わりません。 – porgarmingduod

関連する問題