C#和PHP中的TripleDES加密不一样(PKCS7,ECB)?

Red*_*dth 3 php c# encryption cryptography tripledes

我花了几个小时试图解决这个问题,但我无法让它发挥作用.我有一个C#加密例程,我需要在php中匹配.我无法改变C#版本,这不是一个选项(第三方对此很坚定).

这是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);
}
Run Code Online (Sandbox Code Playgroud)

这是我在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);
}
Run Code Online (Sandbox Code Playgroud)

据我所知,我正在PHP端正确处理PKCS7填充.我不知道还有什么可以尝试的.

有一点需要注意,C#发生在Windows上,而Linux上发生的PHP,并不确定它是否应该有所作为.

eri*_*son 10

PHP版本中的填充长度基于密码的长度.这是不正确的.它应该基于您的消息的长度而不是.

尝试更换strlen($password)用strlen($data).


第二个问题是mcrypt库需要24字节密钥.三重DES应用常规DES三次,因此您可以调用每轮DES K 1,K 2和K 3中使用的8字节密钥.有不同的方法来选择这些键.最安全的是选择三个不同的键.另一种方法是将K 3设置为等于K 1.最不安全的方法(相当于DES)是使K 1 = K 2 = K 3.

大多数库都"足够智能",足以将16字节的3DES键解释为上面的第二个选项:K 3 = K 1..NET实现正在为您执行此操作,但mcrypt库不是; 相反,它设置K 3 = 0.你需要自己解决这个问题,并传递mcrypt一个24字节的密钥.

计算MD5哈希值后,取前8个字节$key,并将它们追加到末尾$key,这样就可以传递24个字节的值mcrypt_encrypt().