Question

J'ai passé quelques heures maintenant essayer de comprendre cela, mais je ne peux pas le faire au travail. J'ai une routine de cryptage C # que je dois correspondre en php. Je ne peux pas changer la version C #, ce n'est pas une option (3ème partie est ferme à ce sujet).

Voici le code C #:

//In C#
// Console.WriteLine(ApiEncode("testing", "56dsfkj3kj23asdf83kseegflkj43458afdl"));
// Results in: 
//     XvHbR/CsLTo=
public static string ApiEncode(string data, string secret)
{
  byte[] clear;

  var encoding = new UTF8Encoding();
  var md5 = new MD5CryptoServiceProvider();

  byte[] key = md5.ComputeHash(encoding.GetBytes(secret));

  TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
  des.Key = key;
  des.Mode = CipherMode.ECB;
  des.Padding = PaddingMode.PKCS7;

  byte[] input = encoding.GetBytes(data);
  try { clear = des.CreateEncryptor().TransformFinalBlock(input, 0, input.Length); }
  finally
  {
    des.Clear();
    md5.Clear();
  }

  return Convert.ToBase64String(clear);
}

Voici le meilleur de ce que je suis venu avec en PHP:

//In PHP
// echo apiEncode("testing", "56dsfkj3kj23asdf83kseegflkj43458afdl");
// Results in: 
//    5aqvY6q1T54=
function apiEncode($data, $secret)
{    
  //Generate a key from a hash
  $key = md5(utf8_encode($secret), true);
  //Create init vector  
  $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_3DES, MCRYPT_MODE_ecb), MCRYPT_RAND); 

  //Pad for PKCS7
  $blockSize = mcrypt_get_block_size('tripledes', 'ecb');
  $len = strlen($data);
  $pad = $blockSize - ($len % $blockSize);
  $data .= str_repeat(chr($pad), $pad);

  //Encrypt data
  $encData = mcrypt_encrypt('tripledes', $key, $data, 'ecb'); //, $iv);
  return base64_encode($encData);
}

Au meilleur de ma connaissance, je me occupe le rembourrage PKCS7 correctement sur le côté PHP. Je ne sais pas quoi d'autre pour essayer.

Une chose à noter, le C # se passe sur les fenêtres et le PHP sous Linux, pas sûr que doit faire une différence.

Était-ce utile?

La solution

La longueur de remplissage dans votre version PHP est basée sur la longueur du mot de passe. Ceci est une erreur. Il doit être basé sur la longueur de votre message à la place.

Essayez de remplacer strlen($password) avec strlen($data).


Le deuxième problème est que la bibliothèque mcrypt requiert des clés de 24 octets. Triple DES applique DES trois fois réguliers, de sorte que vous pouvez appeler la clé de 8 octets utilisé dans chaque tour de DES K 1 , K 2 et K 3 . Il existe différentes façons de choisir ces clés. Le plus sûr est de choisir trois clés distinctes. Une autre façon consiste à fixer K 3 égal à K 1 . La méthode la moins sécurisé (équivalent à DES) est de faire K 1 = K 2 = K 3 .

La plupart des bibliothèques sont assez "intelligents" pour interpréter une clé 3DES 16 octets comme la deuxième option ci-dessus: K 3 = K 1 . La mise en œuvre .NET fait pour vous, mais la bibliothèque de mcrypt n'est pas; à la place, il est la mise en K 3 = 0. Vous aurez besoin de fixer vous-même, et passer mcrypt une clé de 24 octets.

Après le calcul du hachage MD5, prendre les 8 premiers octets du $key, et de les ajouter à la fin de $key, de sorte que vous avez une valeur de 24 octets à transmettre à mcrypt_encrypt().

Autres conseils

J'ai trouvé une solution, vérifier ce lien, peut vous aider. http://sanity-free.com/131/triple_des_between_php_and_csharp.html

Et voici la fonction Décrypter juste au cas où:

    public static string Decrypt(string cypherString)
    {

        byte[] key = Encoding.ASCII.GetBytes("icatalogDR0wSS@P6660juht");
        byte[] iv = Encoding.ASCII.GetBytes("iCatalog");
        byte[] data = Convert.FromBase64String(cypherString);
        byte[] enc = new byte[0];
        TripleDES tdes = TripleDES.Create();
        tdes.IV = iv;
        tdes.Key = key;
        tdes.Mode = CipherMode.CBC;
        tdes.Padding = PaddingMode.Zeros;
        ICryptoTransform ict = tdes.CreateDecryptor();
        enc = ict.TransformFinalBlock(data, 0, data.Length);
        return UTF8Encoding.UTF8.GetString(enc, 0, enc.Length);
    }

Jetez un oeil à encoding.getBytes, vous avez besoin des clés secrètes Octets de UTF8 ...

Il semble que la version C # ne définit pas le IV . Cela pourrait être un problème si vous ne savez pas ce qu'il est parce que msdn dit:

  

La propriété IV est automatiquement réglé sur une nouvelle valeur aléatoire à chaque fois que vous créez une nouvelle instance de l'une des classes SymmetricAlgorithm ou lorsque vous appelez manuellement la méthode GenerateIV.

Il ressemble à la version PHP, vous utilisez un IV . Vous pouvez essayer de ne pas fournir l'IV et espère que la version C # utilise également des zéros.

Edit:. On dirait que pour la BCE, la IV est ignorée

Vous pourriez aussi avoir besoin de coder la clé comme dans la version C # en utilisant utf8- encoder

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top