2016-03-22 6 views
2

Ich habe eine einfache XOR-Funktion in PHP geschrieben. Es funktioniert großartig eigenständig, aber es löst immer eine Ausnahme von "Länge nicht übereinstimmen" aus, wenn ich es in eine Klasse implementiere.PHP XOR-Funktion implementieren "Länge nicht übereinstimmen"

Die XOR-Funktion:

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

Ich habe sogar versucht, eine andere Version, die von Encrypt/decrypt with XOR in PHP, mit Zusatz Länge überprüfen und Variablennamen geändert kopiert.

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

Die Klasse werde ich implementieren:

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

Ich bin sicher, dass die beiden Werte die gleiche Länge haben. Wie kann ich es reparieren? Ich weiß wirklich nicht warum und wie der Fehler auftritt.

Voll Quelle: https://gist.github.com/hartmantam/39857700831591775b1c (nicht funktioniert)

+0

seltsames Problem, könnte es nicht duplizieren ... Könnten Sie eine Geige an http://phpfiddle.org/ schaffen? –

+0

Sie wissen, dass Sie Saiten direkt gegeneinander streamen können, oder? Sie müssen nicht Zeichen für Zeichen gehen. 'function strxor ($ a, $ b) {return $ a^$ b; } ' – duskwuff

+0

@JasonFetterly Ich weiß wirklich nicht, wie man phpfiddle.org benutzt. Also poste ich alle Quelle [hier] (https://gist.github.com/hartmantam/39857700831591775b1c), bitte schauen Sie. – Hartman

Antwort

0

Durch eine Debug-Funktion hinzugefügt, fand ich schließlich, dass das Problem nicht in der XOR-Funktion war es in der openssl_encrypt Funktion ist. Da die AES-Blockgröße 16 ist und ich sie genau richtig eingegeben habe, wird die Funktion einen weiteren Block auf den Klartext auffüllen, wodurch der Ausgang verdoppelt wird, weshalb dieser Fehler auftritt.

Die Lösung ist ziemlich einfach: Ändern Sie OPENSSL_RAW_DATA zu OPENSSL_ZERO_PADDING, und dann die Funktion Padding nicht tun. Obwohl dieses Problem gelöst wurde, müssen wir jetzt die Nachricht manuell auffüllen, und es wird eine Base64 codierte Zeichenfolge ausgeben.

Ändern Sie alle openssl_encrypt wie folgt, und ersetzen Sie die erste Variable, falls erforderlich.

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

Alles, was ich sagen will: seltsame Design

+0

Hallo, ich vermutete, dass sich die Stringgröße nach dem Verschlüsseln änderte, aber mein lokaler Testserver hat eine alte SSL-Lib und es fehlte die 'pkcs7pad'-Funktion, so dass ich letzte Nacht nicht testen konnte. Ich bin froh, dass du es geschafft hast, sorry, dass ich keine Hilfe hatte. –

+0

@JasonFetterly Macht nichts, das ist keine große Sache. – Hartman

Verwandte Themen