2016-03-22 59 views
2

我已經在PHP中編寫了一個簡單的XOR函數。它非常獨立,但是當我將它實現爲一個類時,它總是拋出「長度不匹配」的異常。PHP XOR函數實現「長度不匹配」

XOR函數:

private static function strxor($dataA, $dataB) { 
    if (($dataLen = strlen($dataA)) != strlen($dataB)) { 
     throw new Exception("Length Not Match in strxor"); 
    } 
    $result = ''; 
    for ($i = 0; $i < $dataLen; $i++) { 
     $result .= $dataA[$i]^$dataB[$i]; 
    } 
    return $result; 
} 

我甚至嘗試從Encrypt/decrypt with XOR in PHP複製,添加了長度校驗和變量名改爲另一個版本。

private static function xor_this($dataA, $dataB) { 
    if (($dataLen = strlen($dataA)) !== strlen($dataB)) { 
     die("Length Not Match in xor_this"); 
    } 
    $result = ''; 
    for($i=0;$i<$dataLen;) { 
     for($j=0;($j<$dataLen && $i<$dataLen);$j++,$i++) { 
      $result .= $dataA{$i}^$dataB{$j}; 
     } 
    } 
    return $result; 
} 

類我要去實現:

public static function encrypt($key, $data) { 
    $iv = parent::genSafeRandomBytes(16); 
    $nonce = parent::genSafeRandomBytes(16); 
    $firstBlock = self::xor_this($nonce, $iv); 
    $salt = parent::genSafeRandomBytes(16); 
    $hmac = parent::signText($data, $key); 
    $subkey = parent::genSubKey($key, $salt); 
    $data = self::pkcs7pad($data); 
    $data = str_split($data, 16); 
    $tmp_r = openssl_encrypt($firstBlock, self::CIPHER, $subkey, OPENSSL_RAW_DATA); 
    $result = ''; 
    for ($i = 0; $i < count($data); $i++) { 
     $tmp_n = parent::ivAdd($nonce, $i+1); 
     $tmp_n = self::xor_this($tmp_n, $tmp_r); 
     $tmp_x = openssl_encrypt($tmp_n, self::CIPHER, $subkey, OPENSSL_RAW_DATA); 
     $result .= $tmp_r = self::xor_this($tmp_x, $data[$i]); 
    } 
    return Base62::encode($iv.$nonce.$salt.$hmac.$result); 
} 

我敢肯定,這兩個值具有相同的長度。我該如何解決它?我真的不知道錯誤發生的原因和方式。

全部來源:https://gist.github.com/hartmantam/39857700831591775b1c(不工作)

+0

奇怪的問題,無法複製它......你可以創建在http://phpfiddle.org/一個小提琴? –

+0

你知道你可以直接對XOR字符串進行對吧?你不必一個字符一個字。 '函數strxor($ a,$ b){return $ a^$ b; }' – duskwuff

+0

@JasonFetterly我真的不知道如何使用phpfiddle.org。所以我張貼所有來源[這裏](https://gist.github.com/hartmantam/39857700831591775b1c),請看看。 – Hartman

回答

0

通過添加調試功能,我終於發現,問題並不在XOR功能,它是在openssl_encrypt功能。由於AES塊的大小是16,我輸入它恰到好處,該功能將再填充一個塊到明文,導致輸出翻倍,所以這就是發生這種錯誤的原因。

解決方案非常簡單:將OPENSSL_RAW_DATA更改爲OPENSSL_ZERO_PADDING,然後該函數不會執行填充。雖然解決了這個問題,但現在需要我們手動填充消息,並且它會輸出一個Base64編碼的字符串。

如下更改所有openssl_encrypt,並根據需要替換第一個變量。

openssl_encrypt($firstBlock, self::CIPHER, $subkey, OPENSSL_ZERO_PADDING); 

所有我想說:奇怪的設計

+0

嗨,我懷疑加密後字符串的大小發生了變化,但是我的本地測試服務器有一箇舊的SSL lib,缺少'pkcs7pad'功能,所以我昨晚無法測試。很高興你釘了它,對不起,我沒有任何幫助。 –

+0

@JasonFetterly不要緊,這不是什麼大不了的事情。 – Hartman