私は現在 MD5 ハッシュを使用していますが、[a-z][A-Z][0-9]
. 長さは 5 ~ 10 文字程度で十分です。
すでにこれを行っているものはありますか?
更新 1:
私はCRC32ハッシュが好きです。.NETでそれを計算するクリーンな方法はありますか?
更新 2:
Joeが提供したリンクからCRC32関数を使用しています。uInt を上で定義した文字に変換するにはどうすればよいですか?
.NET文字列オブジェクトにはGetHashCode()関数があります。整数を返します。それを16進数に変換してから、8文字の長さの文字列に変換します。
そのようです:
string hashCode = String.Format("{0:X}", sourceString.GetHashCode());
詳細: http: //msdn.microsoft.com/en-us/library/system.string.gethashcode.aspx
更新:上記のリンクからこの回答にコメントを追加しました:
GetHashCodeの動作はその実装に依存しており、共通言語ランタイムのバージョンごとに変更される可能性があります。これが発生する理由は、GetHashCodeのパフォーマンスを向上させるためです。
2つの文字列オブジェクトが等しい場合、GetHashCodeメソッドは同じ値を返します。ただし、一意の文字列値ごとに一意のハッシュコード値はありません。異なる文字列が同じハッシュコードを返す可能性があります。
発信者へのメモ
GetHashCodeによって返される値は、プラットフォームに依存します。.NETFrameworkの32ビットバージョンと64ビットバージョンでは異なります。
URL短縮サービスを作成することを目標としていますか、それともハッシュ関数を作成することを目標としていますか?
URL短縮サービスを作成することが目標の場合は、ハッシュ関数は必要ありません。その場合は、暗号的に安全な乱数のシーケンスを事前に生成してから、各URLにシーケンスから一意の番号をエンコードするように割り当てます。
次のようなコードを使用してこれを行うことができます。
using System.Security.Cryptography;
const int numberOfNumbersNeeded = 100;
const int numberOfBytesNeeded = 8;
var randomGen = RandomNumberGenerator.Create();
for (int i = 0; i < numberOfNumbersNeeded; ++i)
{
var bytes = new Byte[numberOfBytesNeeded];
randomGen.GetBytes(bytes);
}
暗号化番号ジェネレータを使用すると、生成する文字列を予測することが非常に困難になります。これは、あなたにとって重要だと思います。
次に、アルファベットの文字を使用して、8バイトの乱数を文字列に変換できます。これは基本的にベース計算の変更です(ベース256からベース62へ)。
エントリの ID の Base36 (大文字と小文字を区別しない) または Base64 を取るだけです。
つまり、Base36 を使用したいとします。
(ID - Base36)
1 - 1
2 - 2
3 - 3
10 - A
11 - B
12 - C
...
10000 - 7PS
22000 - GZ4
34000 - Q8C
...
1000000 - LFLS
2345000 - 1E9EW
6000000 - 3KLMO
base64 を使用した場合はこれらをさらに短くすることもできますが、URL は大文字と小文字が区別されます。素敵できちんとした英数字キーを取得でき、衝突がないことが保証されていることがわかります。
短いバージョンから実際の値への 1 対 1 のマッピングが必要なため、短いハッシュは使用できません。短いハッシュの場合、衝突の可能性は非常に高くなります。通常の長いハッシュは、あまりユーザーフレンドリーではありません (衝突の可能性はおそらく十分に小さいですが、それでも私には「正しい」とは感じられません)。
TinyURL.com では、 Base 36 (0 ~ 9、AZ) に変換されるインクリメントされた数値を使用しているようです。
最初に、ランダムな個別の番号のリストを取得します。次にchar
、ベース文字列からそれぞれを選択し、追加して結果を返します。私は 5 文字を選択しています。これは、base 62 から 6471002 の順列になります。2 番目の部分は、短い URL を保存しない場合は、存在するかどうかを確認するために db に対してチェックすることです。
const string BaseUrlChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private static string ShortUrl
{
get
{
const int numberOfCharsToSelect = 5;
int maxNumber = BaseUrlChars.Length;
var rnd = new Random();
var numList = new List<int>();
for (int i = 0; i < numberOfCharsToSelect; i++)
numList.Add(rnd.Next(maxNumber));
return numList.Aggregate(string.Empty, (current, num) => current + BaseUrlChars.Substring(num, 1));
}
}
MD5 ハッシュを英数字としてエンコードすることで、文字数を減らすことができます。各 MD5 文字は通常 16 進数で表されるため、16 の可能な値になります。[a-zA-Z0-9] には 62 の可能な値が含まれているため、4 つの MD5 値を取得して各値をエンコードできます。
編集:
これは、数値 (4 桁の 16 進数) を受け取り、[0-9a-zA-Z] を返す関数です。これにより、それを実装する方法のアイデアが得られるはずです。タイプにはいくつかの問題がある可能性があることに注意してください。このコードはテストしていません。
char num2char( unsigned int x ){
if( x < 26 ) return (char)('a' + (int)x);
if( x < 52 ) return (char)('A' + (int)x - 26);
if( x < 62 ) return (char)('0' + (int)x - 52);
if( x == 62 ) return '0';
if( x == 63 ) return '1';
}
CRC32 を使用できます。これは長さが 8 バイトで、MD5 に似ています。実際の値にタイムスタンプを追加することで、一意の値がサポートされます。
したがって、http://foo.bar/abcdefg12のようになります。
inters から小さな一意のハッシュを生成するライブラリを探している場合は、http://hashids.org/net/を強くお勧めします。私は多くのプロジェクトでそれを使用していますが、素晴らしく機能します。カスタム ハッシュに独自の文字セットを指定することもできます。
md5ハッシュコードを16進数ではなくbase64でエンコードできます。これにより、正確に文字[az][AZ][0-9]を使用して短いURLを取得できます。
暗号化の強度を気にしない場合は、CRC 関数のいずれかで十分です。
ウィキペディアには、出力の長さを含むさまざまなハッシュ関数が一覧表示されています。出力を [az][AZ][0-9] に変換するのは簡単です。
btoa
大文字と小文字、数字、および 2 つの追加文字を使用してバイナリを ASCII に変換する、素晴らしいが古いプログラムがあります。MIME base64 エンコーディングもあります。ほとんどの Linux システムには、おそらくbase64
orと呼ばれるプログラムがありbase64encode
ます。どちらも、32 ビット CRC から短い読み取り可能な文字列を提供します。
MD5 ハッシュの最初の 5 ~ 10 文字の英数字を取ることができます。