46

PHP には、文字列から一意のハッシュを与える方法がありますが、そのハッシュは数値のみから構成されていますか?

例:

return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6

しかし、私は必要です

return numhash(234); // returns 00978902923102372190 
(20 numbers only)

ここでの問題は、ハッシュを短くしたいということです。

編集: ここでバックストーリーを説明しましょう。私はすべての登録者の ID を持つサイトを持っています。また、その人が使用して交換するための ID が必要です (したがって、長すぎることはありません)。これまでのところ、ID 番号は 00001、00002、00003 などです。 ..

  1. これにより、一部の人々がより重要に見えるようになります
  2. これにより、公開したくないアプリケーション情報が公開されます。

ポイント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
4

7 に答える 7

66

PHP の MD5 または SHA1 ハッシュは 16 進数を返すため、基数を変換するだけで済みます。PHP には、これを実行できる関数があります。

$bignum = hexdec( md5("test") );

また

$bignum = hexdec( sha1("test") );

hexdec の PHP マニュアル

限られたサイズの数値が必要なため、剰余除算を使用して、必要な範囲に入れることができます。

$smallnum = $bignum % [put your upper bound here]

編集

コメントでArtefactoが指摘したように、このアプローチを使用すると、PHPの整数の最大サイズを超える数値になり、剰余除算後の結果は常に0になります。ただし、最初の16を含むハッシュの部分文字列を取得します文字にはこの問題はありません。最初の大きな数を計算するための改訂版:

$bignum = hexdec( substr(sha1("test"), 0, 15) );
于 2010-07-31T19:21:59.467 に答える
19

試すことができ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必要があります。validate the integrity of data

于 2010-07-31T19:25:46.457 に答える
15

いくつかの良い答えがありますが、私にとってはアプローチがばかげているようです。
彼らは最初に php に 16 進数を作成させ、次にこれを変換して ( hexdec) BigInteger に戻し、それを文字数に切り詰めます... これは大変な作業です!

代わりに

ハッシュをバイナリとして読み取ります。

$binhash = md5('[input value]', true);

次に使用

$numhash = unpack('N2', $binhash); //- or 'V2' for little endian

INTこれを 2 つの s ($numhashは 2 つの要素の配列)としてキャストします。これで、演算を使用して単純に数値のビット数を減らすことができますAND。例えば:

$result = $numhash[1] & 0x000FFFFF; //- to get numbers between 0 and 1048575

ただし、衝突には注意してください。数を減らすということは、同じ出力を持つ 2 つの異なる [入力値] の確率を増やすことを意味します。

Bijectiv機能を備えた「ID-Crypting」を使用する方がはるかに良い方法だと思います。したがって、衝突は発生しませんでした。最も単純な種類の場合は、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>';

もちろん、これは安全ではありませんが、暗号化に使用された方法を誰も知らない場合、セキュリティ上の理由はありません。この方法はより高速で衝突安全です。

于 2014-05-15T13:34:57.547 に答える
8

ハッシュを切り離す問題は衝突です。回避するには、次のことを試してください。

return  hexdec(crc32("Hello World"));

crc32():_

str の 32 ビット長の巡回冗長チェックサム多項式を生成します。これは通常、送信されるデータの整合性を検証するために使用されます。

これにより、32 ビットの整数、32 ビットのインストールでは負、64 ビットでは正の整数が得られます。この整数は、ID のようにデータベースに格納できます。関数で10進数に変換すると、32ビット変数に収まるため、これには衝突の問題はありませんhexdec()

于 2015-08-19T16:06:28.110 に答える
1

まず第一に、md5 は基本的に侵害されているため、重要でないハッシュ以外には使用しないでください。PHP5 にはhash()関数があります。 http://www.php.net/manual/en/function.hash.phpを参照してください。

最後のパラメーターを true に設定すると、バイナリ データの文字列が得られます。または、結果の 16 進数のハッシュを 2 文字の断片に分割し、それらを個別に整数に変換することもできますが、それははるかに遅くなると思います。

于 2010-07-31T19:20:12.497 に答える
0

hashidを試してください。
数値を定義可能な形式にハッシュします。形式には、文字数と含まれる文字が含まれます。
例:
$hashids->encode(1);
「28630」はフォーマットによって異なりますが、

于 2016-04-05T10:08:06.583 に答える