2011-11-30 87 views
1

我試圖在C中用PHP編寫以下函數。問題是,用PHP編寫的函數返回的結果與C中返回的結果不同。將嵌入式C函數轉換爲PHP函數

我認爲問題來自PHP中的整數溢出,它無法將變量當作無符號32位整數。

我試圖用0xFFFFFFFF沒有成功,並掩蓋所有操作。你有其他解決方案可以工作嗎?

C函數:

void 
decipher(const uint32_t num_rounds, uint32_t v[2], const uint32_t key[4]) 
{ 
    uint32_t idx; 
    uint32_t v0 = v[0]; 
    uint32_t v1 = v[1]; 
    uint32_t delta = 0x9E3779B9; 
    uint32_t sum = delta * num_rounds; 

    for (idx = 0; idx < num_rounds; ++idx) 
    { 
     v1 -= (((v0 << 4)^(v0 >> 5)) + v0)^(sum + key[(sum >> 11) & 3]); 
     sum -= delta; 
     v0 -= (((v1 << 4)^(v1 >> 5)) + v1)^(sum + key[sum & 3]); 
    } 

    v[0] = v0; 
    v[1] = v1; 
} 

PHP函數:

function decipher($num_rounds, &$v, $key) 
{ 
    $v0 = $v[0]; 
    $v1 = $v[1]; 
    $delta = 0x9E3779B9; 
    $sum = ($delta * $num_rounds) & 0xFFFFFFFF; 

    for ($idx = 0; $idx < $num_rounds; ++$idx) 
    { 
     $v1 -= (((($v0 << 4)^($v0 >> 5)) + $v0)^($sum + $key[($sum >> 11) & 3])) & 0xFFFFFFFF; 
     $v1 &= 0xFFFFFFFF; 
     $sum -= $delta; 
     $sum &= 0xFFFFFFFF; 
     $v0 -= ((($v1 << 4)^($v1 >> 5) + $v1)^($sum + $key[$sum & 3])) & 0xFFFFFFFF; 
     $v0 &= 0xFFFFFFFF; 
    } 

    $v[0] = $v0; 
    $v[1] = $v1; 
} 

謝謝。

SOLUTION:

我發現一種解決方案:下面的代碼使用的功能,其允許做無符號的32位整數移位操作和加法。

function decipher($num_rounds, &$v, $key) 
{ 
    $v0 = $v[0]; 
    $v1 = $v[1]; 
    $delta = 0x9E3779B9; 
    $sum = ($delta * $num_rounds) & 0xFFFFFFFF; 

    for ($idx = 0; $idx < $num_rounds; ++$idx) 
    { 
     $v1 = _add($v1, -(_add($v0 << 4^_rshift($v0, 5), $v0)^_add($sum, $key[_rshift($sum, 11) & 3]))); 
     $sum = _add($sum, -$delta); 
     $v0 = _add($v0, -(_add($v1 << 4^_rshift($v1, 5), $v1)^_add($sum, $key[$sum & 3]))); 
    } 

    $v[0] = $v0; 
    $v[1] = $v1; 
} 

function _rshift($integer, $n) 
{ 
    // convert to 32 bits 
    if (0xffffffff < $integer || -0xffffffff > $integer) 
    { 
     $integer = fmod($integer, 0xffffffff + 1); 
    } 

    // convert to unsigned integer 
    if (0x7fffffff < $integer) { 
     $integer -= 0xffffffff + 1.0; 
    } 
    else if (-0x80000000 > $integer) 
    { 
     $integer += 0xffffffff + 1.0; 
    } 

    // do right shift 
    if (0 > $integer) 
    { 
     // remove sign bit before shift 
     $integer &= 0x7fffffff; 
     // right shift 
     $integer >>= $n; 
     // set shifted sign bit 
     $integer |= 1 << (31 - $n); 
    } 
    else 
    { 
     // use normal right shift 
     $integer >>= $n; 
    } 

    return $integer; 
} 


function _add($i1, $i2) 
{ 
    $result = 0.0; 

    foreach (func_get_args() as $value) 
    { 
     // remove sign if necessary 
     if (0.0 > $value) 
     { 
      $value -= 1.0 + 0xffffffff; 
     } 

     $result += $value; 
    } 

    // convert to 32 bits 
    if (0xffffffff < $result || -0xffffffff > $result) 
    { 
     $result = fmod($result, 0xffffffff + 1); 
    } 

    // convert to signed integer 
    if (0x7fffffff < $result) 
    { 
     $result -= 0xffffffff + 1.0; 
    } 
    else if (-0x80000000 > $result) 
    { 
     $result += 0xffffffff + 1.0; 
    } 

    return $result; 
} 

謝謝你的回答。

+4

發佈您的PHP代碼到目前爲止 –

+0

如果它是一個已知的密碼,可能您可以在PHP的[密碼擴展]中找到它(http://es2.php.net/manual/en/refs.crypto.php ) –

回答

1

如果你需要做數學與PHP非常大的整數,你的選擇基本上是使用字符串和您所選擇的任意精度庫:

在這種情況下,GMP是您唯一的選擇,因爲其他庫不支持按位運算。

+0

所有整數必須限制爲32位。 「非常大的整數」是什麼意思? – johsey

+0

「非常大」意味着「它可以放大」。例如,2147483648.有關適合的詳細信息,請參閱'PHP_INT_MAX'和'PHP_INT_SIZE'常量。 –