Partie II:Comment faire de Ruby AES-256-CBC et PHP MCRYPT_RIJNDAEL_128 de bien jouer ensemble

StackOverflow https://stackoverflow.com/questions/1864700

Question

Cette question est la suite de mon dernier sujet Comment faire de Ruby AES-256-CBC et PHP MCRYPT_RIJNDAEL_128 de bien jouer ensemble.J'ai que le travail maintenant, mais j'ai encore des difficultés à aller dans l'autre direction.Le PHP généré le cryptogramme semble avoir toutes les informations qui ont été fournies, mais je ne peux pas obtenir le code Ruby pour le décrypter sans erreur.

Voici le code PHP que j'utilise pour générer le cryptogramme:

$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='

Alors voici la tentative de déchiffrer en Ruby:

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

Ce qui est vraiment frustrant, c'est qu'il est possible d'obtenir l'ensemble du texte clair de cette chaîne cryptée.Répétition de ce qui précède, mais l'ajout d'un non-sens pad le cryptogramme:

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

Dans mon cas d'utilisation, le texte en clair est structuré (une chaîne JSON, puisque vous le demandez), donc je me sens à l'aise a ce point que je pourrais dire d'utiliser ce système et de détecter mal chiffrées entrée sans effectuer de la cipher.final.Cependant, je ne peux pas tolérer ce genre de bidouille dans mon code, donc j'aimerais comprendre comment faire le code ruby gérer le dernier bloc gracieusement.

Était-ce utile?

La solution

Le problème est que mcrypt n'est-ce pas rembourrage le dernier bloc, alors que Ruby OpenSSL de liaison utilise la valeur par défaut OpenSSL rembourrage méthode, qui est PKCS rembourrage.Je ne peux pas vraiment améliorer la description de la OpenSSL documentation:

PKCS rembourrage fonctionne par ajout de n rembourrage octets de la valeur de n pour faire le total longueur des données d'un multiple de la taille de bloc.Le rembourrage est toujours ajouté donc, si les données sont déjà un multiple de la taille de bloc n égale à la taille de bloc.Par exemple, si la taille de bloc est de 8 et de 11 octets sont pour être cryptées puis 5 octets de remplissage de valeur 5 sera ajouté.

Vous aurez besoin d'ajouter manuellement des protections appropriées à la fin du texte clair en PHP avant de les crypter.Pour ce faire, passez votre $cleartext par le biais de ce pkcs5_pad fonction sur le PHP côté avant de le chiffrer (en passant 16 comme la taille des blocs).

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

Si vous aussi vous aller dans l'autre sens (chiffrer en Ruby et décrypter avec mcrypt), vous devrez enlever les octets de remplissage après décryptage.

Note de côté: La raison pour laquelle vous devez ajouter rembourrage, même si le texte en clair est déjà un multiple de la taille des blocs (un bloc entier de remplissage), est de sorte que lorsque vous êtes décryptage vous savez que le dernier octet du dernier bloc est toujours la quantité de remplissage ajouté.Sinon, vous ne pouviez pas faire la différence entre texte en clair avec un seul remplissage d'octets et d'un texte clair et sans rembourrage octets qui vient de se passer à la fin de la valeur 0x01.

Autres conseils

Il semble PHP \0 plaquettes au clair avant de les crypter.Vous pouvez définir Ruby pour désactiver le remplissage.

http://www.ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/Cipher.html#method-i-padding-3D

Cela va fonctionner, mais vous devez dépouiller le rembourrage éteint manuellement.

1.9.3p125 :008 > cipher = OpenSSL::Cipher::Cipher.new('aes-128-cbc')
 => #<OpenSSL::Cipher::Cipher:0x0000000561ee78>
1.9.3p125 :009 > cipher.decrypt
 => #<OpenSSL::Cipher::Cipher:0x0000000561ee78>
1.9.3p125 :010 > cipher.padding = 0
 => 0
1.9.3p125 :011 > cipher.key = Base64.decode64("6sEwMG/aKdBk5Fa2rR6vVw==\n")
 => "\xEA\xC100o\xDA)\xD0d\xE4V\xB6\xAD\x1E\xAFW"
1.9.3p125 :012 > cipher.iv = Base64.decode64("vCkaypm5tPmtP3TF7aWrug==")
 => "\xBC)\x1A\xCA\x99\xB9\xB4\xF9\xAD?t\xC5\xED\xA5\xAB\xBA"
1.9.3p125 :013 > cryptogram =  Base64.decode64('JM0OxMINPTnF1vwXdI3XdI2j8NJ8kr+Du0fnkxorNl0=')
 => "$\xCD\x0E\xC4\xC2\r=9\xC5\xD6\xFC\x17t\x8D\xD7t\x8D\xA3\xF0\xD2|\x92\xBF\x83\xBBG\xE7\x93\x1A+6]"
1.9.3p125 :014 > cleartext = cipher.update(cryptogram)
 => "Who's the clever girl?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
1.9.3p125 :015 > cleartext << cipher.final
 => "Who's the clever girl?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"



1.9.3p125 :042 > cleartext.strip
 => "Who's the clever girl?"
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top