cifrado - c# triple des encrypt string
¿El cifrado TripleDES en C#y PHP no son iguales(PKCS7, ECB)? (4)
Eche un vistazo a codificando.getBytes, necesita la clave secreta Bytes de UTF8 ...
He pasado un par de horas tratando de resolver esto, pero no puedo hacer que funcione. Tengo una rutina de cifrado de C # que necesito para combinar en php. No puedo cambiar la versión de C #, esa no es una opción (la tercera parte es firme en esto).
Aquí está el código 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);
}
Aquí está lo mejor de lo que he encontrado 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);
}
Que yo sepa, estoy manejando el relleno PKCS7 correctamente en el lado de PHP. No estoy seguro de qué más probar.
Una cosa a tener en cuenta, el C # está sucediendo en Windows, y el PHP en Linux, no estoy seguro de que eso haga la diferencia.
La longitud del relleno en su versión de PHP se basa en la longitud de la contraseña. Esto es incorrecto. Debería basarse en la longitud de su mensaje en su lugar.
Intente reemplazar strlen($password)
con strlen($data)
.
El segundo problema es que la biblioteca mcrypt
requiere claves de 24 bytes. Triple DES aplica tres DES regulares, por lo que puede llamar a la clave de 8 bytes utilizada en cada ronda de DES K 1 , K 2 y K 3 . Hay diferentes formas de elegir estas teclas. Lo más seguro es elegir tres claves distintas. Otra forma es establecer K 3 igual a K 1 . El método menos seguro (equivalente a DES) es hacer que K 1 = K 2 = K 3 .
La mayoría de las bibliotecas son lo suficientemente "inteligentes" como para interpretar una clave 3DES de 16 bytes como la segunda opción anterior: K 3 = K 1 . La implementación .NET hace esto por usted, pero la biblioteca mcrypt
no lo está haciendo; en su lugar, establece K 3 = 0. Tendrá que arreglar esto usted mismo, y pasar mcrypt
una clave de 24 bytes.
Después de calcular el hash MD5, tome los primeros 8 bytes de la $key
y añádalos al final de $key
, de modo que tenga un valor de 24 bytes para pasar a mcrypt_encrypt()
.
Parece que la versión de C # no configura el IV . Esto podría ser un problema si no sabes de qué se trata porque msdn dice:
La propiedad IV se establece automáticamente en un nuevo valor aleatorio cada vez que crea una nueva instancia de una de las clases SymmetricAlgorithm o cuando llama manualmente al método GenerateIV.
Parece que en la versión de PHP, estás usando un IV . Podría intentar no suministrar el IV y esperar que la versión C # también use ceros.
Editar: parece que para ECB, el IV se ignora.
Es posible que también necesite codificar la clave como en la versión C # usando utf8-encode
Encontré una solución, revisa este enlace, puede ayudarte. http://sanity-free.com/131/triple_des_between_php_and_csharp.html
Y aquí está la función de descifrado por si acaso:
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);
}