1

データベース ID を短い形式にエンコードする方法を見つけようとしていますURL。たとえば、1 は「Ys47R」になるはずです。次に、値を使用してデータベース検索を実行できるように、「Ys47R」から 1 にデコードしたいと思いINTます。データベースを使用して一意である必要がありますID。1=「Ys47R」、2=「Ys47S」のように、簡単に推測できない配列にしてください。YouTube や bitly のURL's. md5base32base64および `bcpowを使用して何百もの異なるソースを読みましたが、空っぽになりました。

このブログ投稿は有望に見えましたが、パディングとパスキーを追加すると、1 が SDDDG になり、2 が「SDDDH」になり、3 が「SDDDI」になりました。あまりランダムではありません。

base32ab 0-9 のみ base64が使用され、末尾に == などの文字がありました。

次に、これを試しました:

function getRandomString($db, $length = 7) {

    $validCharacters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $validCharNumber = strlen($validCharacters);
    $result = "";

    for ($i = 0; $i < $length; $i++) {
        $index = mt_rand(0, $validCharNumber - 1);
        $result .= $validCharacters[$index];
    }

これはうまくいきましたが、衝突がなく、データベースに存在しないことを確認するために毎回データベースクエリを実行する必要がありました。

各数値が一意であるデータベースで一意のインクリメントを使用して、エンコードおよびデコードできるID's文字セットで最小 4 文字のショートを作成する方法はありますか。またはを使用した高度なテクニックについて理解できません。[a-z][A-Z][0-9]IDbase32base64

それとも、これを調べすぎていて、もっと簡単な方法がありますか? 上記のランダム文字列関数を実行し、データベースにクエリを実行して常に一意性を確認するのが最善でしょうか?

4

2 に答える 2

1

コメントから関数を使用できます: http://php.net/manual/en/function.base-convert.php#106546

$initial = '11111111';
$dic = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
var_dump($converted = convBase($initial, '0123456789', $dic)); 
// string(4) "KCvt"
var_dump(convBase($converted, $dic, '0123456789')); 
// string(8) "11111111"

function convBase($numberInput, $fromBaseInput, $toBaseInput)
{
    if ($fromBaseInput==$toBaseInput) return $numberInput;
    $fromBase = str_split($fromBaseInput,1);
    $toBase = str_split($toBaseInput,1);
    $number = str_split($numberInput,1);
    $fromLen=strlen($fromBaseInput);
    $toLen=strlen($toBaseInput);
    $numberLen=strlen($numberInput);
    $retval='';
    if ($toBaseInput == '0123456789')
    {
        $retval=0;
        for ($i = 1;$i <= $numberLen; $i++)
            $retval = bcadd($retval, bcmul(array_search($number[$i-1], $fromBase),bcpow($fromLen,$numberLen-$i)));
        return $retval;
    }
    if ($fromBaseInput != '0123456789')
        $base10=convBase($numberInput, $fromBaseInput, '0123456789');
    else
        $base10 = $numberInput;
    if ($base10<strlen($toBaseInput))
        return $toBase[$base10];
    while($base10 != '0')
    {
        $retval = $toBase[bcmod($base10,$toLen)].$retval;
        $base10 = bcdiv($base10,$toLen,0);
    }
    return $retval;
}
于 2014-07-28T02:02:55.510 に答える
0

対称的な難読化が必要な場合base_convert()は、多くの場合、これで十分です。

base_convert($id, 10, 36);

のような文字列を返し1i0g、それらを元に変換します。

その基本変換の前後に、次を追加できます。

  • 文字列の最小長を取得するには70000$id. そして、受信側でそれをもう一度減算します。

  • マイナー乗算$id *= 3は、生成された英数字 ID 範囲にいくつかの「穴」を追加しますが、使用可能な文字列スペースを使い果たすことはありません。

  • 恣意性のいくつかの外観については、少しニブル移動:

    $id = ($id & 0xF0F0F0F) << 4    
        | ($id & 0x0F0F0F0) >> 4;
    

    これは、難読化された ID 文字列を生成し、元の ID 文字列を取り戻すために機能します。

    はっきりさせておくと、これはいかなる種類の暗号化でもありません。連続した数字の間で数字のジャンプをシフトするだけで、少し恣意的に見えます

それでも答えが気に入らないかもしれませんが、ID の推測を本当に妨げる唯一の方法は、データベースでランダムな ID を生成することです。

于 2014-07-28T03:51:13.387 に答える