Blog de ILINFO

Trucs et astuces

Blog ILINFO Active DIrectory MIIS LDAP ADAM PCA PRA BCP DRP

Log in

Compatibilité TripleDes entre DOTNET et PHP

by Emmanuel Dreux octobre 26, 2010 23:38

Petit travaux pratiques:

Un développeur m'a récemment confié une application DOTNET utilisant un chiffrement TripleDES.

Le but de la manoeuvre était de pouvoir échanger des données chiffrées entre cette application DOTNET et une application php hébergée sur un serveur Ubuntu.

Retour d'exérience.

Pour commencer, le codeTripleDES provenant d'Internet a été facilement retrouvé.

http://nguyendoanhoa.googlecode.com/svn-history/r59/trunk/QuanLyTruongHoc_App/MyControls/CryptorEngine.cs

Les lignes essentielles sont les suivantes:

            byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

            keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
            tdes.Key = keyArray;
            tdes.Mode = CipherMode.ECB;
            tdes.Padding = PaddingMode.PKCS7

 

Ce choix d'initialisation peu judicieux implique plusieurs problèmes de compatibilité:

1. la clé de chiffrement est une clé courte de 128 bit (hash MD5) et non pas 192 bit.

Hors PHP ne sait pas utiliser des clés de 128 bit.

2. Vous noterez qu'il n'y a pas de vecteur d'initialisation.

Hors PHP en veut un de longueur 8.

3. Le mode de Padding est PKC7.

Hors PHP fait du padding avec des octets NULL.

Pour terminer, on peut s'interroger sur la pertinence d'utiliser ECB, mais passons...

A noter également que le code c# convertit les entrées en UTF8

Solution:

Pour assurer la compatibilité PHP, il faut tout d'abord régler le problème de la longueur de clé.

Triple DES fonctionne de la façon suivante: 

La clé de 192 bit est divisée en 3 clés, puis le chiffrement s'effectue de la façon suivante en mode EDE par défaut (Encrypt Decrypt Encrypt):

Encrypt(K1) -> Decrypt(K2) -> Encrypt(K3).

Avec une clé de 128 bit, le chiffrement devient 

Encrypt(K1) -> Decrypt(K2) -> Encrypt(K1)

En PHP, il suffit donc de couper la clé de 128bit en 2 et de rajouter à la suite de la clé les 64 premiers bits.

La clé doit ensuite être convertie en binaire.

        $key = md5($initialkey);
        $td = mcrypt_module_open('tripledes', '', 'ecb', '');
        $key .= substr($key, 0, mcrypt_enc_get_key_size($td));
        $key = utf8_encode($key);

        // Convert to bin
        $key_bin = pack('H*', $key);

Ensuite, il faut passer un IV null et désactiver les warnings sinon PHP vous remonte un warning sur l'utilisation d'un IV invalide.

Pour le  problème de padding PKCS7, un petit bout de code à conserver dans les tablettes:

DES chiffre des blocs de 8 octets. Il faut rajouter au dernier bloc des octets pour compléter les blocs à 8 caractères.

Par défaut PHP rajoute des NULL. En PKCS7, le caractère rajouté est le code ascii du nombre d'octets manquants.

S'il manque 3 caractères, il rajoute 3x le code asci de 3 en fin de chaine.

        $block = mcrypt_get_block_size('tripledes', 'ecb');
        $len = strlen($buffer);
        $padding = $block - ($len % $block);
        $buffer .= str_repeat(chr($padding),$padding);

Il ne reste plus qu'à mettre ensemble ces éléments:

<?php
    error_reporting(0);
    $buffer ="manu";
    $initialkey = "abcd1234efgh5678";

    // Calcule le hash MD5 et génère 128 bits

    $key = md5($initialkey);
   
    $td = mcrypt_module_open('tripledes', '', 'ecb', '');

    // Transforme en clé 192 bit.

    $key .= substr($key, 0, mcrypt_enc_get_key_size($td));

    $key = utf8_encode($key);

    // Convert to bin
    $key_bin = pack('H*', $key);
    $iv = NULL;

    $block = mcrypt_get_block_size('tripledes', 'ecb');
    $len = strlen($buffer);
    $padding = $block - ($len % $block);
    $buffer .= str_repeat(chr($padding),$padding);
    // Encode en UTF8

    $buffer = utf8_encode($buffer); 

    /* Initialise le module de chiffrement */
    if (mcrypt_generic_init($td, $key_bin, $iv) != -1)
    {
        /* Chiffre les données */
        $Result = mcrypt_generic($td, $buffer);
        mcrypt_generic_deinit($td);
   
        /* Nettoye */
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
    }
    // hex encode the return value
    echo bin2hex($Result);
    echo "<br/>";
    echo base64_encode($Result);
?>

 

Soyez le premier à noter ce billet

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , , ,

Partenaires
Assurez votre plan de continuit� d'activit� avec BCPAnywhere
Votre poste de travail partout dans le monde.

Mig6 votre solution de migration de vos postes de travail vers Windows 7
Migrez de XP vers Windows 7 avec Mig6.

Auteur

Freelance, Indépendant, expert Active Directory, Domaine et Sécurité.

Expert MIIS, ILM, FIM 2010,Kerberos, NTLM, SSL, PKI et chiffrement.