8

Oauth では、10 進形式の ASCII 文字列としてエンコードされたランダムな 64 ビットの符号なし数値が必要です。PHPでこれを達成するのを手伝ってもらえますか?ありがとう

4

3 に答える 3

28

これは非常に興味深い問題でした (PHP で任意の長さの乱数の 10 進数表現を、オプションの拡張機能を使用せずに作成する方法)。解決策は次のとおりです。

ステップ 1: 任意長の乱数

// Counts how many bits are needed to represent $value
function count_bits($value) {
    for($count = 0; $value != 0; $value >>= 1) {
        ++$count;
    }
    return $count;
}

// Returns a base16 random string of at least $bits bits
// Actual bits returned will be a multiple of 4 (1 hex digit)
function random_bits($bits) {
    $result = '';
    $accumulated_bits = 0;
    $total_bits = count_bits(mt_getrandmax());
    $usable_bits = intval($total_bits / 8) * 8;

    while ($accumulated_bits < $bits) {
        $bits_to_add = min($total_bits - $usable_bits, $bits - $accumulated_bits);
        if ($bits_to_add % 4 != 0) {
            // add bits in whole increments of 4
            $bits_to_add += 4 - $bits_to_add % 4;
        }

        // isolate leftmost $bits_to_add from mt_rand() result
        $more_bits = mt_rand() & ((1 << $bits_to_add) - 1);

        // format as hex (this will be safe)
        $format_string = '%0'.($bits_to_add / 4).'x';
        $result .= sprintf($format_string, $more_bits);
        $accumulated_bits += $bits_to_add;
    }

    return $result;
}

この時点で、呼び出すrandom_bits(2048)と、16 進数でエンコードされた文字列として 2048 のランダム ビットが返されますが、問題ありません。

ステップ 2: 任意精度の基数変換

数学は難しいので、コードは次のとおりです。

function base_convert_arbitrary($number, $fromBase, $toBase) {
    $digits = '0123456789abcdefghijklmnopqrstuvwxyz';
    $length = strlen($number);
    $result = '';

    $nibbles = array();
    for ($i = 0; $i < $length; ++$i) {
        $nibbles[$i] = strpos($digits, $number[$i]);
    }

    do {
        $value = 0;
        $newlen = 0;
        for ($i = 0; $i < $length; ++$i) {
            $value = $value * $fromBase + $nibbles[$i];
            if ($value >= $toBase) {
                $nibbles[$newlen++] = (int)($value / $toBase);
                $value %= $toBase;
            }
            else if ($newlen > 0) {
                $nibbles[$newlen++] = 0;
            }
        }
        $length = $newlen;
        $result = $digits[$value].$result;
    }
    while ($newlen != 0);
    return $result;
}

この関数は、たとえば trybase_convert_arbitrary('ffffffffffffffff', 16, 10) == '18446744073709551615'や など、宣伝どおりに機能しbase_convert_arbitrary('10000000000000000', 16, 10) == '18446744073709551616'ます。

それを一緒に入れて

echo base_convert_arbitrary(random_bits(64), 16, 10);
于 2011-03-14T18:07:03.683 に答える
4

2 つの 32 ビット数値、4 つの 16 ビット数値などを使用できます。

PHP にはrand()mt_rand()がありますが、それらが提供するランダムなビット数は標準では指定されていません (ただし、それぞれgetrandmax ()mt_getrandmax( ) を使用して照会できます)。

したがって、最も安全で簡単な方法は、64 個のランダム ビットを生成し、それらを 1 つずつ設定することです。

64 ビット整数の操作に関しては、GMPライブラリを使用することをお勧めします。これには、さまざまな機能が用意されているためです。

数値を作成し、連続する位置で64 個のgmp_setbit()を呼び出してから、gmp_strval() を使用して文字列に変換できます。

于 2011-03-14T16:12:57.217 に答える
2

自分で OAuth アダプターを作成していますか? もしそうなら、あなたは再考したいと思うかもしれません。PECLもの、PEARもの、Zend Frameworkのもの、Google Code でホストされているものなど、優れた OAuth ライブラリがたくさんあります。私は最初の 3 人と仕事をしましたが、どれもかなりまともです。

本当にこれを自分でやりたい場合は、問題に直面する可能性があります。PHP は、64 ビット プラットフォームでコンパイルされていないか、高度な数学拡張機能がインストールされていない限り、64 ビットの数値で考えることができません。これにより、64 ビットの数値を 10 進数として表示することが非常に難しくなります。上記でリンクしたライブラリの多くは、フォーマット要件を完全に無視し、生の MD5 ハッシュで動作するようです。ZF のアダプターのコードは次のとおりです。

/**
 * Generate nonce
 * 
 * @return string
 */
public function generateNonce()
{
    return md5(uniqid(rand(), true));
}

彼らは、相互運用性の問題なしにこれを回避しているように見えます.

于 2011-03-14T16:23:09.503 に答える