2016-03-22 16 views
2

PHP'de basit bir XOR işlevi yazdım. Tek başına çok iyi çalışır, ancak bunu bir sınıfa uygularken her zaman "Uzunluk Eşleşmiyor" özel bir istisna atar.PHP XOR fonksiyonu "Uzunluk Eşleşmiyor" uyarısı

XOR Fonksiyonu:

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; 
} 

Hatta değişti eklendi Uzunluğu kontrol edin ve değişken adıyla Encrypt/decrypt with XOR in PHP kopyalanmış başka versiyonunu denedik.

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; 
} 

sınıf

Ben uygulamak için gidiyorum:

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); 
} 

Ben iki değer aynı uzunlukta olduğundan emin değilim. Bunu nasıl düzeltebilirim? Gerçekten neden ve nasıl bir hata oluştuğunu bilmiyorum.

Tam kaynak: (çalışmıyor) https://gist.github.com/hartmantam/39857700831591775b1c

+0

Garip sorunu, bunu çoğaltmak olamazdı ... Eğer http://phpfiddle.org/ bir keman oluşturmak olabilir mi? –

+0

Doğrudan birbirinize karşı XOR dizeleri yapabileceğinizi biliyorsunuz, değil mi? Karaktere gitmek zorunda değilsin. 'strxor işlevi ($ a, $ b) {return $ a^$ b; } ' – duskwuff

+0

@JasonFetterly phpfiddle.org'u nasıl kullanacağımı gerçekten bilmiyorum. Bu yüzden tüm kaynakları [buraya yazarım] (https://gist.github.com/hartmantam/39857700831591775b1c), lütfen bir göz atın. – Hartman

cevap

0

bir hata ayıklama fonksiyonunu ekleyerek, nihayet onu openssl_encrypt fonksiyonunda olduğu, sorunun XOR işlevinde olmadığını gördük. AES blok boyutu 16 ve ben onu doğru olarak girdiğimde, fonksiyon bir düz metin bloğuna daha fazla blok koyacaktır, bu da çıktının iki katına çıkmasına neden olacaktır, bu yüzden bu hata oluşur.

Çözüm oldukça basit: OPENSSL_RAW_DATA'u OPENSSL_ZERO_PADDING olarak değiştirin ve sonra işlev dolgu yapmayacaktır. Bu sorun çözülmesine rağmen, şimdi mesajın manuel olarak doldurulmasını gerektiriyor ve bir Base64 kodlu dizgi çıkacak.

Aşağıdaki gibi tüm openssl_encrypt değiştirin ve gerekirse ilk değişkeni değiştirin.

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

söylemek istediğim: garip tasarım

+0

Merhaba, şifreden sonra dize boyutu değiştiğinden şüphelendim, ancak yerel test sunucumun eski bir SSL libresi var ve 'pkcs7pad' fonksiyonuna sahip olmadığından, dün gece test edemedim. Başardığına sevindim, üzgünüm, hiç yardımcı olmadım. –

+0

@JasonFetterly Unutmayın, bu büyük bir sorun değil. – Hartman