開発者が「ユーザー」オブジェクトの ID をおしゃべりにするのはなぜですか。たとえば、Twitterがメッセージ ID にSnowflakeを使用するのはなぜですか? 言い換えれば、連続した ID がブラウザーで明らかであることはなぜ悪いのでしょうか? それはセキュリティ上の欠陥ですか、それとも単にプライバシーの問題ですか? セキュリティ上の欠陥である場合、シーケンシャル ID はどのような脆弱性を露呈しますか? プライバシーの問題である場合、エンド ユーザーが連続する ID を識別できる場合、どのようにプライバシーが侵害されるのでしょうか?
1 に答える
一意の ID を作成するための 3 つの一般的な方法は次のとおりです。
- それらを順次にする
- 適度に大きな乱数を選ぶ
- UUID の選択。これは、番号を「パーソナライズ」して、2 度目に作成されないようにすることです。
セキュリティ面
セッションなどを ID に関連付ける場合、これは確かにセキュリティ上の問題です。その場合、悪意のあるユーザーがそのような ID を予測できないようにする必要があります。シーケンシャル ID は簡単に予測できます。UUID にはもう少し手間がかかりますが、乱数が残るため、良い考えではありません。また、それらの場合でも、暗号的に安全な乱数ジェネレーターを使用する必要があります。そうしないと、予測可能性の余地がまだあります。
これが深刻な理由の例として、古き良き「jsessionid」または URL に含まれるその他の典型的なセッション ID を考えてみましょう。攻撃者はログインして通常のユーザーのように振る舞い、自分に割り当てられたセッション ID を書き留めてから、さらに ID を予測し始め、それらをアドレス バーに入力することで、他のユーザーのセッションを効果的にハイジャックします。
並行性/スケーリングの問題
しかし、スノーフレークがその説明で述べていることから判断すると、それに関連する固有のセキュリティ上の懸念はないように思われ、このアプローチは 3 番目の UUID カテゴリに分類されるようです。本文では、MySQL から Cassandra に移行しており、過去には MySQL のシーケンシャル ID を使用していたと書かれています。しかし、考えてみれば、システムをスケーリングしようとすると、これがすぐにボトルネックになります。競合状態を防ぐために、すべての ID 生成を同期する必要があります。
このプロセスを同期しない場合、このような競合状態の例として、2 つの独立したインスタンスが同時に ID を増やし、実際には 2 増加するはずのカウンターが 1 だけ増加することがあります。通常、データベース インスタンスが 1 つしかない場合は、データベースが同期を実行します。しかし、明らかにこれは拡張できません。データベースの負荷が高い間、あまりにも多くのクライアントがアイドル状態で待機することになります。複数のデータベースはオプションですが、ID を複製すると同じ状況に戻る可能性があります。
ロックフリーのユニークID
したがって、同期を必要とせずに (ロックフリーで) ID を生成したい場合は、一意でない ID を使用する方法を学ぶか (これは多かれ少なかれ矛盾に満ちたものであり、実際には解決策ではありません)、または排除するために何かを考え出さなければなりません。ボトルネック。以前行ったことと、いくつかのデータベース インスタンスでうまく機能すること:
- 2 つのインスタンスの場合、1 つの DB は奇数の ID のみを生成し、もう 1 つの DB は偶数の ID のみを生成します。
- n インスタンスの場合、互いに素な n 個の数を選択し、特定のインスタンスの ID にこれらの互いに素な数の 1 つだけを掛けます。3 つのデータベースの場合は、たとえば 2、3、および 5 を選択します。基本的な数論により、重複がないことが保証されます。
しかし、多くの場合、これは実数論的な問題になるため、別の解決策を講じる必要があります。解決策の 1 つは、UUID ルートを使用することです。これは通常は問題ありませんが、時間の経過とともに変化する可能性のある外部要因に完全に依存するという欠点があります。私が見てきたことから、これがSnowflakeが目指しているものだと思います。
完全を期すために、美しくスケーリングし、それ自体がIMO美しい別のソリューションについて言及したいと思います。また、最初は直感に反するものでしたが、外的要因の影響を受けず、どこでも機能します。アイデアは、十分に大きな (20 バイトとしましょう) 暗号的に安全な乱数を選択することです。非暗号化乱数ジェネレーターは通常、一定量の数値が生成された後に繰り返されますが、もちろんそれは望ましくありません。それ以外は、それだけです。
最初は、これは絶対にうまくいかないだろうと思っていました。しかし、計算してみると、確率がどのくらいかがわかります。誕生日のパラドックスは、n が乱数のビット数である O(2^(n/2)) の順序で時間の衝突を見つけることを教えてくれます。したがって、20 バイト = 160 ビットであり、衝突は 2^80 時間で検出されるはずです。これは SHA-1 と同じセキュリティ マージンであり、これまでのところ誰も衝突を発見していません。問題は、幸運に恵まれて、たとえば 2^30 の衝突を「偶然」またはそのようなもので見つける可能性はほとんどないということです。確率はあなたに逆らっています。同じ日に大統領になりながら、同時に複数の宝くじに当選するのとほぼ同じです。