我怎样才能解密C#加密MCRYPT_RIJNDAEL_256值,即由mcrypt的PHP中加密? [英] How can I decrypt an encrypted MCRYPT_RIJNDAEL_256 value in C#, that was encrypted by mcrypt in PHP?

查看:334
本文介绍了我怎样才能解密C#加密MCRYPT_RIJNDAEL_256值,即由mcrypt的PHP中加密?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图从数据库表在Linux中成功地读取Base64编码的值。在这种
表有一个名为FIRST_NAME列。

  $数据= mcrypt_decrypt(MCRYPT_RIJNDAEL_256,patient_fn_salt:在Linux方面我可以在PHP中使用下面的命令轻松解密此,
BASE64_DECODE(H6XmkH + VWvdD88THCliKJjLisGZIBk3CTNvyQMLnhpo =),
MCRYPT_MODE_ECB);



不过,我试着尽我所能复制C#的一面这样的逻辑,所有我得到的是。胡言乱语



我的C#代码如下,我希望你有一些建议,因为我跑出来的想法:(

 字节[] =密文
Convert.FromBase64String(H6XmkH + VWvdD88THCliKJjLisGZIBk3CTNvyQMLnhpo =);
的byte []键= Encoding.UTF8.GetBytes(patient_fn_salt );
Array.Resize(REF键,32);
的byte [] IV =新的字节[32];

串FNAME = Utilities.Decrypt(密文,钥匙, IV);


公共静态字符串解密(字节[]的密文,字节[]键,字节[] IV)
{
//检查参数
如果(密文== NULL || cipherText.Length< = 0)
抛出新的ArgumentNullException(密文);
如果(主要== NULL || Key.Length< = 0)
抛出新的ArgumentNullException(钥匙);
如果(IV == NULL || IV.Length< = 0)
抛出新的ArgumentNullException(钥匙);

// TDeclare使用
//流解密到内存中
//的字节数组。
MemoryStream的msDecrypt = NULL;
的CryptoStream csDecrypt = NULL;
StreamReader的srDecrypt = NULL;

//声明AesManaged对象
//用于解密数据。
RijndaelManaged的RJ =新RijndaelManaged的();

//声明用来保存
//解密的文本字符串。
字符串明文= NULL;


{
//创建一个AesManaged对象
//使用指定的密钥和IV。

rj.Mode = CipherMode.ECB;
rj.BlockSize = 256;
rj.KeySize = 256;
rj.Padding = PaddingMode.Zeros;

rj.Key =键;
rj.GenerateIV();
//rj.IV = IV;


//创建一个decrytor执行流转换。
ICryptoTransform的解密= rj.CreateDecryptor(rj.Key,rj.IV);

//创建用于解密的流。
msDecrypt =新的MemoryStream(密文);
csDecrypt =新的CryptoStream(msDecrypt,解密,CryptoStreamMode.Read);
srDecrypt =新的StreamReader(csDecrypt);

//读取从解密流
//解密的字节,并将其放置在一个字符串。
明文= srDecrypt.ReadToEnd();
}
终于
{
//干净的东西了。

//关闭流。
如果(srDecrypt!= NULL)
srDecrypt.Close();
如果(csDecrypt!= NULL)
csDecrypt.Close();
如果(msDecrypt!= NULL)
msDecrypt.Close();

//清除AesManaged对象。
如果(RJ!= NULL)
rj.Clear();
}
返回明文;
}
}


解决方案

由于保罗说,ECB模式不使用IV。如果C#在一个坚持,然后使用全零字节。



关键patient_fn_salt为15个字符,120位。您解密函数需要的关键256位。你需要的非常确保额外的位在两个系统中相同的,在这两个系统在同一个地方正在增加。即使是一个有点不对,将导致垃圾解密。仔细阅读PHP文档,以确定究竟是如何patient_fn_salt被扩展到256位的密钥。特别是检查是否实际的关键是 SHA256(patient_fn_salt)



顺便说一句,ECB模式不安全的。优先使用两种CTR模式或CBC模式。 CTR模式不需要填充这样可能意味着更少的密文存储



ETA:另一个通读我注意到C#一边是用0填充。用什么填充PHP的一面呢?零填充是不是一个好主意,因为它不能识别故障解密。 PKCS7填充有识别错误的输出的一个更好的机会。最好明确指定填充的两端,而不是依赖于默认值。


I am trying to read a Base64-Encoded value from a Database table managed on the Linux side. In that table there is a column called first_name. On the Linux side I can decrypt this easily by using the following command in PHP:

$data = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, "patient_fn_salt",
                       base64_decode("H6XmkH+VWvdD88THCliKJjLisGZIBk3CTNvyQMLnhpo="),
                       MCRYPT_MODE_ECB);

However I try as much as I can to duplicate this logic on the C# side and all I get is gibberish.

My C# code is below, i hope you have some suggestions because I ran out of ideas :(

byte [] cipherText =
         Convert.FromBase64String("H6XmkH+VWvdD88THCliKJjLisGZIBk3CTNvyQMLnhpo=");
byte [] key = Encoding.UTF8.GetBytes("patient_fn_salt");
Array.Resize(ref key, 32);
byte [] iv = new byte[32];

string fname = Utilities.Decrypt(cipherText, key, iv);


public static string Decrypt(byte[] cipherText, byte[] Key, byte[] IV)
  {
   // Check arguments.
   if (cipherText == null || cipherText.Length <= 0)
    throw new ArgumentNullException("cipherText");
   if (Key == null || Key.Length <= 0)
    throw new ArgumentNullException("Key");
   if (IV == null || IV.Length <= 0)
    throw new ArgumentNullException("Key");

   // TDeclare the streams used
   // to decrypt to an in memory
   // array of bytes.
   MemoryStream msDecrypt = null;
   CryptoStream csDecrypt = null;
   StreamReader srDecrypt = null;

   // Declare the AesManaged object
   // used to decrypt the data.
   RijndaelManaged rj = new RijndaelManaged();

   // Declare the string used to hold
   // the decrypted text.
   string plaintext = null;

   try
   {
    // Create an AesManaged object
    // with the specified key and IV.

    rj.Mode = CipherMode.ECB;
    rj.BlockSize = 256;
    rj.KeySize = 256;
    rj.Padding = PaddingMode.Zeros;

    rj.Key = Key;
    rj.GenerateIV();
    //rj.IV = IV;


    // Create a decrytor to perform the stream transform.
    ICryptoTransform decryptor = rj.CreateDecryptor(rj.Key, rj.IV);

    // Create the streams used for decryption.
    msDecrypt = new MemoryStream(cipherText);
    csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
    srDecrypt = new StreamReader(csDecrypt);

    // Read the decrypted bytes from the decrypting stream
    // and place them in a string.
    plaintext = srDecrypt.ReadToEnd();
   }
   finally
   {
    // Clean things up.

    // Close the streams.
    if (srDecrypt != null)
     srDecrypt.Close();
    if (csDecrypt != null)
     csDecrypt.Close();
    if (msDecrypt != null)
     msDecrypt.Close();

    // Clear the AesManaged object.
    if (rj != null)
     rj.Clear();
   }
   return plaintext;
  }
 }

解决方案

As Paŭlo says, ECB mode does not use an IV. If C# insists on one then use all zero bytes.

The key "patient_fn_salt" is 15 characters, 120 bits. Your decryption function is expecting 256 bits of key. You need to be very sure that the extra bits are identical in both systems and are being added in the same place in both systems. Even a single bit wrong will result in garbage decryption. Read the PHP documentation very carefully to determine exactly how "patient_fn_salt" is expanded to a 256 bit key. In particular check if the actual key is SHA256("patient_fn_salt").

As an aside, ECB mode is insecure. Use either CTR mode or CBC mode in preference. CTR mode does not require padding so will probably mean less cyphertext to store.

ETA: on another read through I notice that the C# side is padding with zeros. What padding is the PHP side using? Zero padding is not a good idea, as it cannot recognise a faulty decryption. PKCS7 padding has a much better chance of recognising a faulty output. Best to explicitly specify the padding on both ends rather than rely on defaults.

这篇关于我怎样才能解密C#加密MCRYPT_RIJNDAEL_256值,即由mcrypt的PHP中加密?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆