Domanda

ho passato un paio d'ore ora cercando di capire questo, ma non riesco proprio a farlo funzionare. Ho un C # crittografia di routine che ho bisogno di corrispondere in php. Non posso cambiare la versione C #, che non è un'opzione (3a parte è ferma su questo).

Ecco il codice 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);
}

Ecco il meglio di quello che mi è venuta in mente in 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);
}

Per quanto a mia conoscenza, mi sto occupando l'imbottitura PKCS7 correttamente sul lato PHP. Non sono sicuro che altro per provare.

Una cosa da notare, il C # sta accadendo su finestre, e il PHP su Linux, non sono sicuro che dovrebbe fare la differenza.

È stato utile?

Soluzione

La lunghezza imbottitura nella vostra versione di PHP si basa sulla lunghezza della password. Questo non è corretto. Dovrebbe essere basata sulla lunghezza del messaggio, invece.

Provare a sostituire strlen($password) con strlen($data).


Il secondo problema è che la biblioteca mcrypt richiede chiavi di 24 byte. Triple DES applica regolari DES tre volte, in modo da poter chiamare la chiave di 8 byte utilizzata in ogni turno di DES K 1 , K 2 , e K 3 . Ci sono diversi modi per scegliere questi tasti. Il più sicuro è quello di scegliere tre chiavi distinte. Un altro modo è quello di impostare K 3 pari a k ?? 1 . Il metodo meno sicuro (equivalente a DES) è di rendere K 1 = K 2 = K 3 .

La maggior parte delle librerie sono "intelligenti" abbastanza per interpretare una chiave 3DES 16 byte, come la seconda opzione di cui sopra: K 3 = K 1 . L'implementazione .NET sta facendo questo per voi, ma la biblioteca mcrypt non lo è; K 3 , invece, è l'impostazione = 0. Si avrà bisogno di risolvere il problema da soli, e passare mcrypt una chiave 24 byte.

Dopo aver calcolato l'hash MD5, prendere i primi 8 byte di $key, e li aggiunge alla fine del $key, in modo da avere un valore di 24 byte da passare al mcrypt_encrypt().

Altri suggerimenti

Ho trovato una soluzione, controllare questo link, può aiutare. http://sanity-free.com/131/triple_des_between_php_and_csharp.html

E qui è la funzione di decifrare solo nel caso in cui:

    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);
    }

Date un'occhiata a encoding.getBytes, è necessario byte chiave segreta da UTF8 ...

Sembra la versione C # non imposta il IV . Questo potrebbe essere un problema se non sai quello che è perché MSDN dice:

La struttura IV viene impostata automaticamente un nuovo valore casuale quando si crea una nuova istanza di una delle classi SymmetricAlgorithm oppure quando si chiama manualmente il metodo GenerateIV.

Sembra che nella versione di PHP, si utilizza un IV . Si potrebbe cercare di non alimentare il IV e la speranza la versione C # utilizza anche zeri.

Modifica:. Assomiglia per BCE, la IV viene ignorato

Potrebbe anche essere necessario per la codifica la chiave come nel C # versione utilizzando utf8- encode

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top