Frage

Diese Frage ist eine Fortsetzung meines letzten, in Bezug auf Wie Ruby-AES-256-CBC und PHP MCRYPT_RIJNDAEL_128 spielen gut zusammen zu machen. Ich habe, dass die Arbeit jetzt, aber ich bin immer noch kämpfen, in die andere Richtung zu gehen. Die PHP erzeugte Krypto erscheint alle Informationen zu haben, die zur Verfügung gestellt wurde, aber ich kann den Ruby-Code nicht erhalten, ohne Fehler zu entschlüsseln.

Hier ist der PHP-Code Ich bin mit dem Krypto zu generieren:

$cleartext = "Who's the clever boy?";
$key = base64_decode("6sEwMG/aKdBk5Fa2rR6vVw==\n");
$iv = base64_decode("vCkaypm5tPmtP3TF7aWrug==");
$cryptogram = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $cleartext, MCRYPT_MODE_CBC, $iv);
$result = base64_encode($cryptogram);
print "\n'$result'\n";

RESULT
'JM0OxMINPTnF1vwXdI3XdKI0KlVx210CvpJllFja+GM='

Dann ist hier der Versuch, in Ruby zu entschlüsseln:

>> cipher = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
>> cipher.key = Base64.decode64("6sEwMG/aKdBk5Fa2rR6vVw==\n")
>> cipher.iv = Base64.decode64("vCkaypm5tPmtP3TF7aWrug==")
>> cryptogram = Base64.decode64('JM0OxMINPTnF1vwXdI3XdKI0KlVx210CvpJllFja+GM=')
>> cleartext = cipher.update(cryptogram)
=> "Who's the clever"
>> cleartext << cipher.final
OpenSSL::Cipher::CipherError: bad decrypt
 from (irb):100:in `final'
 from (irb):100

Was ist das wirklich frustrierend ist, dass es möglich ist, die gesamte unverschlüsselt aus diesem verschlüsselten String zu erhalten. Durch Wiederholen der oben, aber das Hinzufügen eines Nonsense-Pad zum Kryptogramm:

  >> cleartext = cipher.update(cryptogram + 'pad')
  => "Who's the clever boy?\000\000\000\000\000\000\000\000\000\000\000"
  >> cleartext << cipher.final
  OpenSSL::Cipher::CipherError: bad decrypt
   from (irb):119:in `final'
   from (irb):119

In meinem konkreten Anwendungsfall die unverschlüsselt strukturiert ist (ein JSON-String, da Sie fragen), so fühle ich mich ein, diesen Punkt komfortabel, dass ich dieses Schema sagen könnte, verwenden und erkennen schlecht verschlüsselte Eingabe ohne den cipher.final auszuführen. Allerdings kann ich nicht diese Art von Flickschusterei in meinem Code tolerieren, so würde ich zu verstehen, wie der Ruby-Code machen anmutig den letzten Block behandeln.

War es hilfreich?

Lösung

Das Problem ist, dass mcrypt ist der letzte Block nicht Klotzen, während Ruby OpenSSL Bindung des Auffüllverfahrens Standard OpenSSL verwendet, die PKCS padding ist. Ich kann auf die Beschreibung von der OpenSSL Dokumentation nicht wirklich verbessern:

  

PKCS padding Arbeiten von n padding Hinzufügen   Bytes des Wertes n um die Gesamt   Länge der Daten eines   Vielfaches der Blockgröße. Polsterung   immer hinzugefügt, so, wenn die Daten bereits   ein Vielfaches der Blockgrße n wird   gleich der Blockgrße. Zum Beispiel, wenn   die Blockgröße 8 und 11 Bytes   verschlüsselt dann 5 Füllbytes werden   der Wert wird 5 hinzugefügt.

Sie müssen manuell die richtige Polsterung zum Ende des unverschlüsselt in PHP hinzufügen, bevor die Verschlüsselung. Um das zu tun, übergeben Sie Ihre $cleartext durch diese pkcs5_pad Funktion auf der PHP-Seite, bevor Sie es (vorbei 16 als Blockgröße) zu verschlüsseln.

function pkcs5_pad ($text, $blocksize)
{
    $pad = $blocksize - (strlen($text) % $blocksize);
    return $text . str_repeat(chr($pad), $pad);
}

Wenn Sie auch in die andere Richtung gehen (verschlüsselt in Ruby und Entschlüsseln mit mcrypt), werden Sie den Paddingbytes nach dem Entschlüsselung abstreifen müssen.

Side Hinweis: Der Grund, warum Sie padding hinzuzufügen, auch wenn die unverschlüsselt ist bereits ein Vielfaches der Blockgröße (ein ganzer Block von padding), ist so, dass, wenn Sie Entschlüsseln Sie wissen, dass die letzte Byte des letzten Blocks ist immer die Menge der Polsterung hinzugefügt. Andernfalls könnten Sie nicht den Unterschied zwischen unverschlüsselt mit einem einzigen Füllbyte erzählen und eine Klartext ohne Füllbytes, die gerade im Wert 0x01 geschah zu beenden.

Andere Tipps

Es scheint PHP \0 Pads den unverschlüsselt, bevor sie verschlüsselt werden. Sie können Ruby-Set die Polsterung zu deaktivieren.

scroll top