donglu9825
donglu9825
2014-12-14 23:27

将AES解密从php转换为c#

已采纳

I'm attempting to convert some working php code to c# in order to do aes decryption.

Working PHP code:

function convert_from_hex($h) {
    $r="";
    for ($i=0; $i<strlen($h); $i+=2) 
        if ((isset($h[$i])) && (isset($h[$i+1]))) 
            $r.=chr(hexdec($h[$i].$h[$i+1]));

    return $r;
}

function decryptAES($crypt_text, $key) {

    $crypt_text=convert_from_hex($crypt_text);                                              // convert from hex

    $iv = substr($crypt_text, 0, 16);                                                       // extract iv
    $crypt_text = substr($crypt_text, 16);                                                  // extract iv

    $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');                 // decrypt
    @mcrypt_generic_init($td, $key, $iv);
    $package = @mdecrypt_generic($td, $crypt_text);

    mcrypt_generic_deinit($td);                                                             // close encryption
    mcrypt_module_close($td);

    $padqty=ord($package[strlen($package)-1]);                                              // remove padding

    return substr($package, 0, strlen($package)-$padqty);
}

Broken C# Code:

public string test()
        {
            string data = ConvertHex("149B56B7240DCFBE75B7B8B9452121B0E202A18286D4E8108C52DBB2149D820B980FFC7157470B9573AA660B2FAAB158E321023922191BCEA5D6E1376ABE6474");

            string iv = data.Substring(0, 16);
            string toDecrypt = data.Substring(16);

            return AESEncryption.DecryptString(Encoding.Default.GetBytes(toDecrypt), Encoding.ASCII.GetBytes("C728DF944B666652"), Encoding.Default.GetBytes(iv));
        }

static public string DecryptString(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");

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

            byte[] binaryDecryptedData;

            // Create an Aes object 
            // with the specified key and IV. 
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Mode = CipherMode.CBC;
                aesAlg.Padding = PaddingMode.PKCS7;
                aesAlg.KeySize = 128;
                aesAlg.BlockSize = 128;
                aesAlg.Key = Key;
                aesAlg.IV = IV;

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


                // Create the streams used for decryption. 
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (MemoryStream srDecrypt = new MemoryStream())
                        {
                            var buffer = new byte[1024];
                            var read = csDecrypt.Read(buffer, 0, buffer.Length);
                            while (read > 0)
                            {
                                srDecrypt.Write(buffer, 0, read);
                                read = csDecrypt.Read(buffer, 0, buffer.Length);
                            }
                            csDecrypt.Flush();
                            binaryDecryptedData = srDecrypt.ToArray();
                        }
                    }
                }

            }

            StringBuilder sb = new StringBuilder();
            foreach (byte b in binaryDecryptedData)
                sb.Append((char)b);
            plaintext = sb.ToString();

            return plaintext;
        }

        public string ConvertHex(String hexString)
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < hexString.Length; i += 2)
            {
                string hs = hexString.Substring(i, 2);

                sb.Append((char)Convert.ToUInt32(hs, 16));
            }

            return sb.ToString();
        }

The correct output of the PHP code is: Fail (1) Not a valid Request or Command.

The output of the C# code is: ²H,-§±uH¤¥±BÃrY¡|¡JJѾà`ªx"äommand

I'm guessing that I have some sort of encoding issue, although I've tried many different options without success. Both code snippets are running on a windows box, so I believe the default encoding is windows-1252.

Any suggestions would be appreciated.

Replacement for ConvertHex which fixed my issues (thanks to owlstead's help)

public static byte[] StringToByteArray(string hex)
{
    return Enumerable.Range(0, hex.Length)
                     .Where(x => x % 2 == 0)
                     .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
                     .ToArray();
}
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • dsv17139 dsv17139 7年前

    You are using the first 16 bytes of string data instead of 16 bytes of binary data. This is what is causing the main issue. You need first to convert hex to bytes and then strip off the first 16 bytes to use as IV. Your ConvertHex method (not shown) is broken, it should return a byte array. The fact that your decrypted plaintext does end correctly with "ommand" clearly indicates a problem with the IV value.

    点赞 评论 复制链接分享

为你推荐