猫の写真を作成できるサイトを運営しているとしましょう。私はすべての猫の写真に一意の識別子を付け、http://catpictures.com/base62Identifier
を使用してソーシャルメディアで共有できるようにします。
猫の写真に1、2、3などの連続した識別子を与えることもできますが、ユーザーが1日に作成する新しい猫の写真の数を(毎日HTTP 200を返す最大の識別子によって)簡単に見つけることができます。これにより、競合他社に月に1回製品を注文し、請求書番号を書き留めるという一般的な戦略がわかります。ウェブサイトのトラフィックの数値はビジネスの収益とよく相関しているので、この情報を秘密にしたいと思います。
私がしようと考えていること:
これはハッシュアルゴリズムの仕事のように聞こえますよね?問題は、ハッシュを観察することで、どのアルゴリズムがそれを作成したか(md5、crc32など)を判別するのが非常に簡単です。レインボーテーブルを持っている人は、そのアイデアを簡単に解決するでしょう。識別子[hash( "salt" +1)、hash( "salt" +2)、...]をソルトすることもできますが、その場合、ソルトに関連するセキュリティについて心配する必要があります。そして衝突チェック。
もう1つのアイデアは、ランダムな文字列を生成し、それをデータベース内の猫の画像の主キーとして使用することでした(または、猫の画像データの最初のnビットをハッシュすることもできました)。この方法では、衝突をチェックするだけで済みます。
一意の識別子のURLを介してトラフィック量を公開しないようにするための標準的なベストプラクティスの方法はありますか?
編集:データベースの主キーまたはインデックス可能な列としてのセキュリティと適合性の良い組み合わせであるソリューションを具体的に探しています。
この種の問題に対する標準的なアプローチは、各画像に対して ID(Universally Unique Identifier) を作成することです。これは通常、ランダムな128ビットの識別子であり、名前空間に対するブルートフォース攻撃を介して画像を列挙することが可能であるという特定の懸念なしに、各画像に割り当てることができます。
たとえば.NETでは、このような目的で [〜#〜] guid [〜#〜] 構造を使用できます。 Windows 2000以降 ( ソース )、Guid.NewGuid
はランダムな(バージョン4)UUIDを生成します。 (古いバージョンでは バージョン1 UUID が生成されましたが、これは生成された日付を示し、「請求書番号」の問題からユーザーを保護するために何もしていません。)
単純に画像ハッシュを使用します。あなたが使ったハッシュを誰かが理解していることの何が問題になっていますか? 「URLのこの部分がsha1のように見える」と思った場合、ファイルをダウンロードするとthat sha1が含まれています。しかし、それでも私はあなたの"猫のセキュリティ"を破ることはできません。ハッシュを解読して画像を理解することができたとしても、単にダウンロードするのではなく、それを試みても意味がありません。
画像データの暗号で保護されたハッシュを生成し、それを識別子として使用するだけです。
これには2つの副作用があります。
これらの影響はどちらも本質的に悪いものではありません。彼らも便利になるかもしれません。しかし、それらを避けたい場合は、安全な乱数ジェネレータからの疑似乱数で各画像ハッシュをソルトすることができます。
ちなみに、衝突は心配する必要はありません。 SHA256のようなハッシュ関数を使用すると、 ランダムな衝突が発生する可能性は天文学的に非常に小さいため、1つが見つかると不思議です 。
標準的な方法は、暗号で保護された疑似乱数ジェネレータ(CSPRNG)を使用して、ランダムにURLを生成することです。
ハッシュなどは必要ありません-単純な古い乱数を使用してください。それらはGUIDである必要もありません(データベースが何らかの理由で単純な数値よりもGUIDをよりよく処理する場合を除きます)。おそらく、あなたのサイトは各URLでアクセス可能な画像をすでに記憶しているので、連続したURLではなくランダムなURLを処理するように変更するだけです。
128ビットの乱数は十分な長さにする必要があります。
新しい画像を処理するときは、URLの重複を必ず確認してください。
質問、コメント、その他の回答で読んだことから、すべてのものが写真ごとに一意の識別子を見つけることに変わり、これは推測できず、写真の数に関する情報も提供されず、データベースで簡単に処理できます。
次に、挿入のタイムスタンプ(1970年からのミリ秒数)を使用しないのはなぜですか。 2人が非常に同じミリ秒で猫の写真を挿入する可能性がある場合は、そのミリ秒の挿入数に対応する連番と連結できます。
そうすれば、誰かが最後の写真を積極的に検索することで見つけられる唯一のことは、誰かが写真を追加した最後の日であり、そのようなジャークに毎日のDOS攻撃のように見せることです。
その間、衝突やデータベースのサポートについて心配する必要はありません。
代替ソリューション:
画像識別子にメタデータを追加します。例:
philipp_20151213_00002.jpg
-ユーザーPhilippが2015年12月13日に投稿した2番目の画像。
私はそのメタデータをリークしますが、それはユーザーがそのリンクをクリックしたときにとにかく見ることができるデータだけです(私は推測します)。
これはオブザーバーに、サービスに投稿された画像の合計数を通知するのではなく、その日の特定のユーザーのアクティビティについてのみ通知します。これも隠したい場合は、連番の代わりに疑似乱数を使用できます。 1人のユーザーが1日に非常に大量の画像をアップロードした場合でも衝突が発生する可能性がありますが、実際には、ランダムな数がなくなるまで新しい乱数を生成するだけで処理できるほどまれです。
これが1つの方法です。サーバー全体で8バイトのCSPRNGを保持します。次に、新しい画像ごとに、別の8バイトのCSPRNGを生成します。このCSPRNGをサーバー全体のCSPRNGでハッシュします(md5は問題ありません)。次に、XOR画像IDを含むハッシュの最後の8バイト(データベースで0から自動インクリメントされます)。クライアントは、画像の一意の8バイトCSPRNGのBase64エンコーディングを受け取ります。 8バイトXOR結果。これは公開イメージIDになります。
サーバーが公開イメージIDを受信すると、サーバー全体の8バイトのCSPRNGとともに、公開IDの最初の8バイトをハッシュします。次に、ハッシュの最後の8バイトを取得し、XORパブリックIDの最後の8バイトを使用します。結果は、データベースからインデックスを作成できるプライベート内部IDになります。
更新(説明):
まず、すべてのID計算に使用されるランダムなグローバルCSPRNGを事前定義します(8バイトまたは64ビット、18,446,744,073,709,551,616の可能な組み合わせ)。
serverCSPRNG = CSPRNG(8)
PrivateID(8バイト)から新しいパブリックID(16バイト)を作成するには、次のようにします。
newCSPRNG = CSPRNG(8)
hashEnding = last8Bytes(md5(newCSPRNG + serverCSPRNG))
publicID = newCSPRNG + XOR(hashEnding, privateID)
PublicIDからprivateIDを派生させる場合:
hashEnding = last8Bytes(md5(first8Bytes(publicID) + serverCSPRNG))
privateID = XOR(hashEnding, last8Bytes(publicID))
セキュリティを強化するために、ブルートフォース攻撃から完全に保護するために、publicIDの最後の8バイトでセカンダリグローバル(静的サーバーのみ)CSPRNGをXORすることができます(1つに固有のセキュリティモデルを実装しているため)。タイムパッド)。
前述のように here :ハッシュ、UUIDなどには、これらのハッシュ/ uuidがPKであり、PKがクラスター化されているDBへのレコードの挿入は非常に高価である(定義が高価)という「欠点」があります。 。)それらは通常順次ではないので( NEWSEQUENTIALID
のような特定の関数が使用されている場合を除きますが、そのページの「重要な」ブロックに注意してください:「プライバシーが懸念される場合は、この関数を使用しないでください。次に生成されるGUIDの値を推測できます... ")。
ここでの提案とは別に、Twitterの( 廃止 ) snowflake のようなものを検討します。私は同様の.Netライブラリ( IdGen );を作成しました。 Readmeには、正確に機能する方法に関する情報が記載されています。利点は、生成されたIDが(ほとんど)シーケンシャルであり、スペースをあまり消費しない(64ビットv.s. 128ビットUUID /ハッシュ)ものであり、衝突を引き起こすことなくIDを生成する複数のホスト/プロセスがある(調整されていない)分散環境で使用できることです。そして、それらは連続的ですが、一定期間の猫の写真の数(または、より一般的には、「使用されたID」の数)に関する多くの情報を提供しません。
これは、ハッシュアルゴリズムの仕事のように聞こえますよね?
いいえ、あなたが観察するようにあなたは衝突を心配する必要があるので。私にとっては、順列、つまりブロック暗号の仕事のように思えます。これにはマイナス面であるキーの管理が必要ですが、データベースの自動インクリメント機能を使用でき、衝突を心配する必要がありません。
トリッキーな部分はIVについて何をするかを決めることであり、ここにはオプションがあります。 URLを作成するたびに新しいURLを生成できるので、たとえば、猫の写真ごとに2 ^ 128個の異なるURL。 IVをユーザーごとまたはセッションごとに作成し、ユーザープロファイル/セッション状態の一部としてサーバー側に保存することができます。ユーザーごとに作成することもできますが、URLに含めることで、写真が口コミで広まった人物を追跡できます。
問題:
したがって:
nextCat
は、Webサイトfirstの起動時に0に設定されます。64ビットである必要があります。nextCat
は、猫が追加されるたびにincremented
であり、newCat
はtrue
に設定されます。nextCat
はランダムなタイマーによるincremented
であり、猫が追加されると予想するよりも速い速度で起動します。ただし、newCat
がtrue
の場合、このタイマーの起動に対してインクリメントは行われず、newCat
はfalse
に設定されます。(タイマーはランダムな時間で行われるため、タイマーの起動の間に2匹の猫が追加されたかどうかを判断するのは困難です。)
1つのアプローチは hashids を使用することです。
Hashidsは、小さなオープンソースライブラリで、数字から短く一意の非シーケンシャルIDを生成します。
347のような数値を「yr8」のような文字列に、または[27、986]のような数値の配列を「3kTMd」に変換します。
これらのIDをデコードして戻すこともできます。これは、いくつかのパラメーターを1つにバンドルする場合、または単にそれらを短いUIDとして使用する場合に役立ちます。
内部で連続した数値のIDを引き続き使用できるため、DBのパフォーマンスは低下しません。一方、外部キーは不透明です。
この問題に対するローテクな解決策があります。 URL短縮サービスを使用するか、独自のサービスを作成してください。
以下を提供します。
http://catpic.to/i34dhY
対http://catpictures.com/some-guid-string
。サードパーティのサービスに依存したくない場合は、お好みの言語で 全単射関数 を実装することにより、独自のサービスを簡単に導入できます。