type の ID 値から一意のハッシュを生成する必要がありますLong
。私の懸念は、2 つの異なるLong/long
値から同じハッシュをグローバルに生成してはならないということです。
MD5 ハッシュは良い解決策に見えますが、ハッシュ文字列は非常に長いです。文字だけ欲しい
0-9
a-z and A-Z
j4qwO7 のような 6 文字だけです。
最も簡単な解決策は何ですか?
16 進数表現を使用する必要はありません。関数からの実際のハッシュ バイトを使用して、独自のハッシュ表現を構築します。ハッシュ出力を切り捨ててハッシュ表現を単純化することもできますが、衝突の可能性が高くなります。
編集:
可能な値の数に基づいて、あなたが尋ねることは不可能であると述べている他の回答は、実際に範囲全体が必要な場合long
、理論的には真実です。
ID がゼロから自動的にインクリメントされる場合、ニーズによっては、値だけ 62^6 = 56800235584
で十分な場合があります。
ステップ 1. long の代わりに int を使用するように切り替えるか、より長い「ハッシュ」を許可します。long を処理するのに 6 文字では不十分な理由については、他のすべての回答を参照してください。
ステップ 2. パディングを使用しないアルゴリズムを使用して番号を暗号化します。個人的には、skip32 エンコーディングをお勧めします。これがセキュリティ上十分に強力であるとは約束しませんが、「ランダムに見える ID を作成する」ことが目的であれば、うまく機能します。
ステップ 3. 番号を base_62 番号としてエンコードします (base_10 ではなく、base64 エンコードではありません)。
更新:
Hashid を使用する必要はありません。ベース36で十分です。
long id = 12345;
String hash = Integer.toString(Math.abs((int)id), 36);
Hashids を使用した元の回答:
long id = 12345;
Hashids hashids = new Hashids("this is my salt");
String hash = hashids.encrypt(id); // "ryBo"
"ryBo"
あなたのロングに戻すことができるので、ユニークになります。Hashids
変換するだけで、それ以上ハッシュしません。
long[] numbers = hashids.decrypt("ryBo");
// numbers[0] == 12345
本当に 64 ビットの値を持っている場合、ハッシュ文字列はかなり長くなります (アルファベットによっては約 16 文字) が、2^16 を超えるものを使用する予定がない場合は、問題なく実行できます。 64 ビット ハッシュを 32 ビット (int) に切り捨てます。
long id = 12345;
String hash = hashids.encrypt(Math.abs((int)id));
ハッシュと同じように長い値自体を使用できます(インデックス作成/検索の目的で)。
long 値を難読化/非表示にする必要がある場合は、ECB モードの DES や AES など、64 ビット ブロックの任意の対称暗号化アルゴリズムを使用できます。