PHPには、文字列から一意のハッシュを与える方法がありますが、ハッシュは数字のみで構成されていますか?
例:
return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6
しかし、私は必要です
return numhash(234); // returns 00978902923102372190
(20 numbers only)
ここでの問題は、ハッシュを短くすることです。
edit:OKここでバックストーリーを説明させてください。登録したすべての人のIDを持つサイトがあり、その人が使用および交換するためのIDも必要です(そのため、長すぎることはできません)。 ..
ポイント1と2を修正するには、番号を一意に保ちながら「非表示」にする必要があります。
https://stackoverflow.com/a/23679870/175071 によるコードに基づく数値ハッシュ関数
/**
* Return a number only hash
* https://stackoverflow.com/a/23679870/175071
* @param $str
* @param null $len
* @return number
*/
public function numHash($str, $len=null)
{
$binhash = md5($str, true);
$numhash = unpack('N2', $binhash);
$hash = $numhash[1] . $numhash[2];
if($len && is_int($len)) {
$hash = substr($hash, 0, $len);
}
return $hash;
}
// Usage
numHash(234, 20); // always returns 6814430791721596451
いくつかの良い答えがありますが、私にとってアプローチはばかげているようです。
最初にphpに16進数を作成するように強制し、次にこれをBigIntegerに変換して(hexdec
)戻し、それをいくつかの文字に切り詰めます...これは大変な作業です!
代わりに
ハッシュをバイナリとして読み取ります。
$binhash = md5('[input value]', true);
を使用して
$numhash = unpack('N2', $binhash); //- or 'V2' for little endian
これを2つのINT
s($numhash
は2つの要素の配列です)。 AND
操作を使用するだけで、数値のビット数を減らすことができます。例えば:
$result = $numhash[1] & 0x000FFFFF; //- to get numbers between 0 and 1048575
しかし衝突に注意してください!数を減らすことは同じ出力で2つの異なる[入力値]の確率を増やすことを意味します。
もっと良い方法は、Bijectiv関数で「ID暗号化」を使用することだと思います。したがって、衝突は発生しませんでした!最も単純な種類の場合は、 Affine_cipher を使用します
最大入力値の範囲が0〜25の例:
function numcrypt($a)
{
return ($a * 15) % 26;
}
function unnumcrypt($a)
{
return ($a * 7) % 26;
}
出力:
numcrypt(1) : 15
numcrypt(2) : 4
numcrypt(3) : 19
unnumcrypt(15) : 1
unnumcrypt(4) : 2
unnumcrypt(19) : 3
例えば.
$id = unnumcrypt($_GET('userid'));
... do something with the ID ...
echo '<a href="do.php?userid='. numcrypt($id) . '"> go </a>';
もちろんこれは安全ではありませんが、暗号化に使用される方法を誰も知らない場合、セキュリティ上の理由はありません。この方法はより速く、衝突に対して安全です。
PHP=のMD5またはSHA1ハッシュは16進数を返します。そのため、ベースを変換するだけです。PHPはこれを行うことができる関数を持っています:
$bignum = hexdec( md5("test") );
または
$bignum = hexdec( sha1("test") );
限られたサイズの番号が必要なため、モジュラー分割を使用して、必要な範囲に配置できます。
$smallnum = $bignum % [put your upper bound here]
[〜#〜] edit [〜#〜]
Artefactoのコメントに記載されているように、このアプローチを使用すると、PHPの整数の最大サイズを超える数が発生し、モジュラー除算後の結果は常に0になります。ただし、最初の16キャラクターにはこの問題はありません。初期の大きな数を計算するための改訂版:
$bignum = hexdec( substr(sha1("test"), 0, 15) );
crc32()
を試すことができます。次のドキュメントを参照してください。 http://php.net/manual/en/function.crc32.php
$checksum = crc32("The quick brown fox jumped over the lazy dog.");
printf("%u\n", $checksum); // prints 2191738434
そうは言っても、crc
はonlyを使用してvalidate the integrity of data
。
ハッシュをカットする問題は衝突であり、それを避けるために試してください:
_return hexdec(crc32("Hello World"));
_
crc32()
:
Strの32ビット長の巡回冗長チェックサム多項式を生成します。これは通常、送信されるデータの整合性を検証するために使用されます。
これにより、32ビットの整数、32ビットインストールでは負、64ビットでは正になります。この整数は、データベースのIDのように格納できます。 hexdec()
関数で10進数に変換すると、32ビット変数に収まるため、これには衝突の問題はありません。
まず、md5は基本的に危険にさらされているので、重要ではないハッシュ以外には使用しないでください。 PHP5にはhash()
関数があります。 http://www.php.net/manual/en/function.hash.php を参照してください。
最後のパラメーターをtrueに設定すると、バイナリデータの文字列が得られます。あるいは、結果の16進数のハッシュを2文字の断片に分割し、それらを個別に整数に変換することもできますが、それははるかに遅いと予想されます。
以下の手動のハッシュ方式を使用してください:
数値(6桁など)を素数3,5,7で割ります。
そして、使用するIDとして小数点以下の最初の6つの値を取得します。 IDが実際に作成される前に一意性のチェックを行い、衝突が存在する場合は、衝突しないまで最後の桁を+1増やします。
例えば。 123456は771428を与えます123457は780952を与えます123458は790476を与えます。
hashid を試してください。
数値をハッシュして、定義可能な形式にします。形式には、文字数と含まれている文字が含まれます。
例:
$ hashids-> encode(1);
フォーマットによって「28630」が返されますが、