web-dev-qa-db-ja.com

php:数字のみのハッシュ?

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

例:

return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6

しかし、私は必要です

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

ここでの問題は、ハッシュを短くすることです。

edit:OKここでバックストーリーを説明させてください。登録したすべての人のIDを持つサイトがあり、その人が使用および交換するためのIDも必要です(そのため、長すぎることはできません)。 ..

  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
36
Timo Huovinen

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

代わりに

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

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

を使用して

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

これを2つのINTs($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>';

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

11
Thomas

PHP=のMD5またはSHA1ハッシュは16進数を返します。そのため、ベースを変換するだけです。PHPはこれを行うことができる関数を持っています:

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

または

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

hexdecのPHPマニュアル

限られたサイズの番号が必要なため、モジュラー分割を使用して、必要な範囲に配置できます。

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

[〜#〜] edit [〜#〜]

Artefactoのコメントに記載されているように、このアプローチを使用すると、PHPの整数の最大サイズを超える数が発生し、モジュラー除算後の結果は常に0になります。ただし、最初の16キャラクターにはこの問題はありません。初期の大きな数を計算するための改訂版:

$bignum = hexdec( substr(sha1("test"), 0, 15) );
62
derekerdmann

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 

そうは言っても、crconlyを使用してvalidate the integrity of data

15
David Titarenco

ハッシュをカットする問題は衝突であり、それを避けるために試してください:

_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文字の断片に分割し、それらを個別に整数に変換することもできますが、それははるかに遅いと予想されます。

1
tdammers

以下の手動のハッシュ方式を使用してください:

数値(6桁など)を素数3,5,7で割ります。

そして、使用するIDとして小数点以下の最初の6つの値を取得します。 IDが実際に作成される前に一意性のチェックを行い、衝突が存在する場合は、衝突しないまで最後の桁を+1増やします。
例えば。 123456は771428を与えます123457は780952を与えます123458は790476を与えます。

0
Ben

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

0