2012-04-03 10 views
14

Derzeit haben wir eine Mcrypt-Implementierung auf unseren Systemen, um einige sensible Daten in unserer PHP-Anwendung zu verschlüsseln. Jetzt haben wir eine neue Anforderung, dass wir das Crypt-Modul zu openssl ändern müssen. Eine weitere Sache, die wichtig ist, ist, dass wir den Chiffrier-Blowfish und den Modus ecb verwenden. Also begann ich zu testen, was Unterschiede sind und wie ich verschlüsselte mcrypt-Strings mit openssl entschlüsseln kann.Ersetzen Mcrypt mit OpenSSL

verwendete ich die Standard-PHP-Funktion:

  • mcrypt_encrypt gegen openssl_encrypt
  • mcrypt_decrypt gegen openssl_decrypt

Beide Methoden liefern unterschiedliche Ergebnisse. Die zweite Sache ist, dass in der gegebenen Chiffre (Blowfish) und Mode (ecb) in beiden Typen unterschiedliche IV-Längen benötigt werden (openssl = 0 und mcrypt = 56).

Weiß jemand, wie ich die Module ohne großen Migrationsaufwand leicht ändern kann?

Vielen Dank im Voraus!

UPDATE:

Hier ist der Code, den ich es getestet:

<?php 

function say($message){ 
    if(!is_string($message)){ 
     if(!isset($_SERVER["HTTP_USER_AGENT"])) echo "<pre>"; 
     echo var_export($message, true) . ((!isset($_SERVER["HTTP_USER_AGENT"]) ? "\n" : "<br />")); 
     if(!isset($_SERVER["HTTP_USER_AGENT"])) echo "</pre>"; 
    }else{ 
     echo $message . ((!isset($_SERVER["HTTP_USER_AGENT"]) ? "\n" : "<br />")); 
    } 
} 

say("= Begin raw encryption"); 
$key = "anotherpass"; 
$str = "does it work"; 

say(" Params:"); 
say(" - String to encrypt '".$str."'"); 
say(" - Key: ".$key); 
say(""); 


$params = array(
    "openssl" => array(
     "cipher" => "BF", 
     "mode"  => "ECB", 
    ), 
    "mcrypt" => array(
     "cipher" => "blowfish", 
     "mode"  => "ecb", 
    ), 
); 

say("= Mcrypt"); 
$handler = mcrypt_module_open($params['mcrypt']['cipher'], '', $params['mcrypt']['mode'], ''); 
$iv  = mcrypt_create_iv (mcrypt_enc_get_iv_size($handler), MCRYPT_RAND); 
$keysize = mcrypt_enc_get_key_size($handler); 
mcrypt_generic_init($handler,$key,"\0\0\0\0\0\0\0\0"); 
say(" Params:"); 
say(" - InitVector ".bin2hex($iv)." (bin2hex)"); 
say(" - Max keysize ".$keysize); 
say(" - Cipher  ".$params['mcrypt']['cipher']); 
say(" - Mode   ".$params['mcrypt']['mode']); 
say(""); 
say(" Encryption:"); 
$m_encrypted = mcrypt_generic($handler, $str); 
$m_decrypted = mdecrypt_generic($handler, $m_encrypted); 
say(" - Encrypted ".bin2hex($m_encrypted)." (bin2hex)"); 
say(" - Descrypted ".$m_decrypted); 
say(""); 


say("= Openssl"); 
say(" Params:"); 
say(" - InitVector not needed"); 
say(" - Max keysize ".openssl_cipher_iv_length($params['openssl']['cipher']."-".$params['openssl']['mode'])); 
say(" - Cipher  ".$params['openssl']['cipher']); 
say(" - Mode   ".$params['openssl']['mode']); 
say(""); 
say(" Encryption:"); 
$o_encrypted = openssl_encrypt($str,$params['openssl']['cipher']."-".$params['openssl']['mode'],$key,true); 
$o_decrypted = openssl_decrypt($o_encrypted,$params['openssl']['cipher']."-".$params['openssl']['mode'],$key,true); 
say(" - Encrypted ".bin2hex($o_encrypted)." (bin2hex)"); 
say(" - Descrypted ".$o_decrypted); 

Und das ist mein Ergebnis:

= Begin raw encryption 
    Params: 
    - String to encrypt 'does it work' 
    - Key: anotherpass 

= Mcrypt 
    Params: 
    - InitVector 06a184909d7bf863 (bin2hex) 
    - Max keysize 56 
    - Cipher  blowfish 
    - Mode   ecb 

    Encryption: 
    - Encrypted 0e93dce9a6a88e343fe5f90d1307684c (bin2hex) 
    - Descrypted does it work 

= Openssl 
    Params: 
    - InitVector not needed 
    - Max keysize 0 
    - Cipher  BF 
    - Mode   ECB 

    Encryption: 
    - Encrypted 213460aade8f9c14d8d51947b8231439 (bin2hex) 
    - Descrypted does it work 

Vielleicht jetzt irgendwelche Ideen?

Danke!

+7

werden Sie entweder einen Migrationsskript ausführen, die die aktuellen Daten mit mcrypt entschlüsselt und dann verschlüsselt ihn wieder openssl verwenden, oder Sie sonst‘ Sie müssen eine Methode implementieren, mit der Sie wissen, welche Verschlüsselungs-/Entschlüsselungsfunktionen für jedes Datenelement zu verwenden sind, und diese bei Bedarf beim Zugriff auf einige mit mcrypt verschlüsselte Daten von mcrypt in openssl ändern. – Jon

+1

Wie ich es verstehe, verwenden Mcrypt und Open_ssl verschiedene Schlüsselableitungsmethoden und damit Jon Recht hat, müssen Sie entweder durch Entschlüsseln migrieren, dann verschlüsseln oder Daten markieren, so dass es beim nächsten Zugriff migriert wird. –

+0

Ich frage mich, warum IB im ECB-Modus benötigt wird. Siehe die Beschreibung des ECB-Modus unter http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation. – doptimusprime

Antwort

8

Blowfish ist die Blockchiffre. Es erfordert, dass die Daten vor der Verschlüsselung aufgefüllt werden. OpenSSL verwendet PKCS # 7 und mcrypt verwendet PKCS # 5. Verschiedene Füllalgorithmen für Daten. Minimale PKCS # 5-Fülllänge ist 0, für PKCS # 7 ist es 1 (wikipedia). Werfen Sie einen Blick auf dieses Beispiel (i Eingangsdaten für mcrypt_encrypt() in PKCS # 7-Stil manuell gepolstert haben):

<?php 

$key = "anotherpassword1"; 
$str = "does it work 12"; 

$enc = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $str."\1", MCRYPT_MODE_ECB); 
$dec = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $enc, MCRYPT_MODE_ECB); 
echo(bin2hex($enc).PHP_EOL); 
var_dump($dec); 

$enc = openssl_encrypt($str, 'bf-ecb', $key, true); 
$dec = openssl_decrypt($enc, 'bf-ecb', $key, true); 
echo(bin2hex($enc).PHP_EOL); 
var_dump($dec); 

?> 

es unmöglich ist, openssl_decrypt() Daten verschlüsselt mit mcrypt_encrypt(), es sei denn, die manuelle Daten Polsterung mit gemacht PKCS # 7 vor mcrypt_encrypt() wurde aufgerufen.

Es gibt nur einen Weg in Ihrem Fall - recrypt die Daten.

PS: Es ist ein Fehler in der Quelle - ECB-Modus nicht verwendet nicht IV bei allen (wikipedia)

+1

Danke, dieser Hinweis hat mir geholfen, Rijndael-128/AES-128 kompatibel zwischen MCrypt und OpenSSL zu machen. Leider funktioniert es nicht für Blowfish - – Narf

+0

Es stellt sich heraus, es funktioniert für Blowfish, aber die Schlüsselgröße muss mindestens 16 Bytes sein (Wikipedia-Artikel für Blowfish sagt, dass es weniger unterstützt). – Narf

+0

Es ist wegen Padding in PKCS # 7 – clover

-1

@clover richtig ist, dass die Standard-Polsterung für Blowfish unterscheidet zwischen mcrypt und OpenSSL, ist aber falsch, dass es nicht getan werden kann.Wenn Sie die OPENSSL_ZERO_PADDING Option für die Entschlüsselung verwenden die beiden sind wirklich kompatibel:

openssl_decrypt($data, 'bf-ecb', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING); 
+0

'OPENSSL_ZERO_PADDING' fügt keine Auffüllung hinzu, es müssen alle nicht standardmäßigen Auffüllungen manuell hinzugefügt werden Verschlüsselung und entfernt bei der Entschlüsselung. In der Dokumentation [openssl_encrypt] (https://secure.php.net/manual/en/function.openssl-encrypt.php) verwenden Sie möglicherweise eine andere Version. Aus den Kommentaren der Dokumentation: OPENSSL_ZERO_PADDING deaktiviert das Padding für den Kontext, was bedeutet, dass Sie Ihr eigenes Padding manuell auf die Blockgröße anwenden müssen. Ohne OPENSSL_ZERO_PADDING erhalten Sie automatisch PKCS # 7 Padding. – zaph