首页 新闻 会员 周边 捐助

php与c#加解密问题

0
悬赏园豆:50 [已解决问题] 解决于 2013-09-11 13:31

首先测试过 MD5是一样的。

但是用php和。net加密的结果不一样
用php加密的数据用。net解密就报错
请问为什么???

<?php
 $keys ='key';
 echo do_mencrypt('12345678',$keys);
 echo '<br/>'.md5($keys);

 
 
 /**
*加密函数
*$input 要被加密的字符串
*$key 密钥
*/
function do_mencrypt($input, $key)
    {
        $input = base64_encode(trim($input));
        $key = substr(md5($key), 0, 24);
        $td = mcrypt_module_open('tripledes', '', 'ecb', '');
        $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        mcrypt_generic_init($td, $key, $iv);
        $encrypted_data = mcrypt_generic($td, $input);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        return trim(base64_encode($encrypted_data));
    }
    
/**
*解密函数
*$input 要被解密的字符串
*$key 密钥
*/
function do_mdecrypt($input, $key)
    {
        $input = base64_decode(trim($input));
        $td = mcrypt_module_open('tripledes', '', 'ecb', '');
        $key = substr(md5($key), 0, 24);
        $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        mcrypt_generic_init($td, $key, $iv);
        $decrypted_data = mdecrypt_generic($td, $input);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        return trim(base64_decode($decrypted_data));
     }
?>

.net的

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace detest
{
    public class dllEncrypt
    {
        //矢量,矢量可以为空
        private const string sIV = "qcDY6X+aPLw=";
        //构造一个对称算法
        private SymmetricAlgorithm mCSP = new TripleDESCryptoServiceProvider();

        public dllEncrypt() { }

        #region public string EncryptString(string Value)
        ///
        /// 加密字符串
        ///
        /// 输入的字符串
        /// 加密后的字符串
        public string EncryptString(string Value,string sKey)
        {
            ICryptoTransform ct;
            MemoryStream ms;
            CryptoStream cs;
            byte[] byt;

            sKey = Md5(sKey);
            sKey = sKey.Substring(0,24);
            mCSP.Key = Encoding.UTF8.GetBytes(sKey);
            Value = Convert.ToBase64String(Encoding.UTF8.GetBytes(Value));
            //mCSP.IV = Convert.FromBase64String(sIV);
            //指定加密的运算模式
            mCSP.Mode = System.Security.Cryptography.CipherMode.ECB;
            //获取或设置加密算法的填充模式
            mCSP.Padding = System.Security.Cryptography.PaddingMode.None;
            mCSP.GenerateIV();
            ct = mCSP.CreateEncryptor();
            byt = padding(Encoding.UTF8.GetBytes(Value));
            ms = new MemoryStream();
            cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
            cs.Write(byt, 0, byt.Length);
            cs.FlushFinalBlock();
            cs.Close();
            return Convert.ToBase64String(ms.ToArray());
        }
        #endregion

        #region public string DecryptString(string Value)
        ///
        /// 解密字符串
        ///
        /// 加过密的字符串
        /// 解密后的字符串
        public string DecryptString(string Value, string sKey)
        {
            ICryptoTransform ct;
            MemoryStream ms;
            CryptoStream cs;
            byte[] byt;
            sKey = Md5(sKey);
            sKey = sKey.Substring(0, 24);
            mCSP.Key = Encoding.UTF8.GetBytes(sKey);
            //mCSP.IV = Convert.FromBase64String(sIV);
            mCSP.Mode = System.Security.Cryptography.CipherMode.ECB;
            mCSP.Padding = System.Security.Cryptography.PaddingMode.None;
            mCSP.GenerateIV();
            ct = mCSP.CreateDecryptor();
            byt = Convert.FromBase64String(Value);
            Console.WriteLine(Encoding.UTF8.GetString(byt));
            ms = new MemoryStream();
            cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
            cs.Write(byt, 0, byt.Length);
            cs.FlushFinalBlock();
            cs.Close();
            String re = Encoding.UTF8.GetString(ms.ToArray());
            re = upPadding(re);
            re = Encoding.UTF8.GetString(Convert.FromBase64String(re));
            return re;
        }
        #endregion



        public static string Md5(string str)
        {

            string pwd = "";
            MD5 md5 = MD5.Create();//实例化一个md5对像
            // 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择 
            byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
            // 通过使用循环,将字节类型的数组转换为字符串,此字符串是常规字符格式化所得
            for (int i = 0; i < s.Length; i++)
            {
                // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母,如果使用大写(X)则格式后的字符是大写字符

                pwd = pwd + s[i].ToString("X");

            }
            return pwd.ToLower();

        }

         static byte[] padding(byte[] source)
        {
            int len = source.Length;
            int s = len / 8;
            if (len % 8 > 0)
            {
                s = s + 1;
            }

            byte[] newV = new byte[s * 8];
            for (int i = 0; i < len; i++)
            {
                newV[i] = source[i];
            }
            for (int i = len; i < s * 8 - len; i++)
            {
                newV[i] = Convert.ToByte('\0');
            }

            return newV;
        }

        string upPadding(string p) 
        { 
           return p = p.Replace("\0","");
        }
    }

}
jommy的主页 jommy | 初学一级 | 园豆:77
提问于:2013-09-11 10:17
< >
分享
最佳答案
2

园子里有一篇参考博文C#兼容PHP中的MD5

public static string MD5(string password) {
   byte[] textBytes = System.Text.Encoding.Default.GetBytes(password);
   try {
      System.Security.Cryptography.MD5CryptoServiceProvider cryptHandler;
      cryptHandler = new System.Security.Cryptography.MD5CryptoServiceProvider();
      byte[] hash = cryptHandler.ComputeHash (textBytes);
      string ret = "";
      foreach (byte a in hash) {
         if (a<16)
            ret += "0" + a.ToString ("x");
         else
            ret += a.ToString ("x");
      }
      return ret ;
   }
   catch {
      throw;
   } 
} 
收获园豆:40
dudu | 高人七级 |园豆:29737 | 2013-09-11 10:46

前提是两边的MD5后值是一致的,所以MD5可以排除,还是谢谢你的回复!

jommy | 园豆:77 (初学一级) | 2013-09-11 10:52

@Jommy: 你提问中所写的解密代码不需要这么复杂吧?

dudu | 园豆:29737 (高人七级) | 2013-09-11 11:05

@Jommy: 建议提供一个MD5加密后的字符串,这样可以方便大家测试

dudu | 园豆:29737 (高人七级) | 2013-09-11 11:06

@dudu: 密钥MD5后的值为dcff09f0abcba03bd89df9a90d656dfa,
PHP对hello加密为HTyphi3Osr4=

jommy | 园豆:77 (初学一级) | 2013-09-11 11:11

@Jommy: 原始密钥是什么?

dudu | 园豆:29737 (高人七级) | 2013-09-11 11:13

@dudu: 密钥就是dcff09f0abcba03bd89df9a90d656dfa取前24位呀

jommy | 园豆:77 (初学一级) | 2013-09-11 11:21

@Jommy: 你加密时密钥不是一个字符串?

dudu | 园豆:29737 (高人七级) | 2013-09-11 11:23

@dudu: 我c#使用随机向量将hello加密,密文为LJvPRmrtYFc=,与php的加密后的不一致

jommy | 园豆:77 (初学一级) | 2013-09-11 11:23

@Jommy: 你要解决的问题是不是用PHP加密,用C#解密?如果是,需要提供一下PHP加密所用的密钥,以及加密后的字符串。

dudu | 园豆:29737 (高人七级) | 2013-09-11 11:28

@Jommy: 怎么解决的?

dudu | 园豆:29737 (高人七级) | 2013-09-11 13:34
其他回答(1)
0

如果你对字符串,字节,base64,UTF8,unicode等这些概念都理解正确的话,鉴于你采用了 3DES 算法,那么请你把 CipherMode,PaddingMode,Key,IV 都仔细检查一遍,看看是否匹配。

收获园豆:10
Launcher | 园豆:45050 (高人七级) | 2013-09-11 10:33

双方都是采用UTF-8编码的,运算模式也都是ECB,填充模式为NONE,KEY也是一致,偏移量php是随机生成的,所以在C#中我就没设置IV值了。现在两边加解密结果就老是不一致了。

支持(0) 反对(0) jommy | 园豆:77 (初学一级) | 2013-09-11 10:46

@Jommy: 把PHP 生成的 IV 也传递过来。

支持(0) 反对(0) Launcher | 园豆:45050 (高人七级) | 2013-09-11 10:54

@Launcher: PHP是随机生成,我试着也随机生成IV,但密文与PHP的就是不一致

支持(0) 反对(0) jommy | 园豆:77 (初学一级) | 2013-09-11 11:25

@Jommy: 如果用  KEY,IV 加密,那么解密的时候你需要原来加密使用的同样的KEY,IV。每两次 3DES 加密的密文是不同的(你为什么要纠结这个呢?这是算法设计使然,就是怕通过相同的密文让破解者猜测出KEY 和 IV),但是只要使用相同的 KEY,IV,那么解密肯定是能成功的。

支持(0) 反对(0) Launcher | 园豆:45050 (高人七级) | 2013-09-11 11:30

@Launcher: KEY是相同,IV是随机生成,PHP的是第三方的,我们无权调整,我们只是使用c#解密。

支持(0) 反对(0) jommy | 园豆:77 (初学一级) | 2013-09-11 11:36

@Jommy: 他们需要把 KEY 和 IV 都传递给你,你解密的时候需要用。

支持(0) 反对(0) Launcher | 园豆:45050 (高人七级) | 2013-09-11 11:42
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册