首先测试过 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",""); } } }
园子里有一篇参考博文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; } }
前提是两边的MD5后值是一致的,所以MD5可以排除,还是谢谢你的回复!
@Jommy: 你提问中所写的解密代码不需要这么复杂吧?
@Jommy: 建议提供一个MD5加密后的字符串,这样可以方便大家测试
@dudu: 密钥MD5后的值为dcff09f0abcba03bd89df9a90d656dfa,
PHP对hello加密为HTyphi3Osr4=
@Jommy: 原始密钥是什么?
@dudu: 密钥就是dcff09f0abcba03bd89df9a90d656dfa取前24位呀
@Jommy: 你加密时密钥不是一个字符串?
@dudu: 我c#使用随机向量将hello加密,密文为LJvPRmrtYFc=,与php的加密后的不一致
@Jommy: 你要解决的问题是不是用PHP加密,用C#解密?如果是,需要提供一下PHP加密所用的密钥,以及加密后的字符串。
@Jommy: 怎么解决的?
如果你对字符串,字节,base64,UTF8,unicode等这些概念都理解正确的话,鉴于你采用了 3DES 算法,那么请你把 CipherMode,PaddingMode,Key,IV 都仔细检查一遍,看看是否匹配。
双方都是采用UTF-8编码的,运算模式也都是ECB,填充模式为NONE,KEY也是一致,偏移量php是随机生成的,所以在C#中我就没设置IV值了。现在两边加解密结果就老是不一致了。
@Jommy: 把PHP 生成的 IV 也传递过来。
@Launcher: PHP是随机生成,我试着也随机生成IV,但密文与PHP的就是不一致
@Jommy: 如果用 KEY,IV 加密,那么解密的时候你需要原来加密使用的同样的KEY,IV。每两次 3DES 加密的密文是不同的(你为什么要纠结这个呢?这是算法设计使然,就是怕通过相同的密文让破解者猜测出KEY 和 IV),但是只要使用相同的 KEY,IV,那么解密肯定是能成功的。
@Launcher: KEY是相同,IV是随机生成,PHP的是第三方的,我们无权调整,我们只是使用c#解密。
@Jommy: 他们需要把 KEY 和 IV 都传递给你,你解密的时候需要用。