我在C#和SQL Server中使用MD5加密时遇到问题,它仅在具有特殊字符的行上发生。
这是c#中的代码:
public virtual string RowHash<T>(T item)
{
PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
var finalvalue = "";
foreach (PropertyInfo p in properties)
{
if (p.Name != "Hash")
{
if (!p.CanWrite || !p.CanRead) { continue; }
MethodInfo mget = p.GetGetMethod(false);
MethodInfo mset = p.GetSetMethod(false);
// Get and set methods have to be public
if (mget == null) { continue; }
if (mset == null) { continue; }
var value = p.GetValue(item, null) == null ? "" : p.GetValue(item, null) is Entity? ((Entity)p.GetValue(item, null)).Id.ToString() : p.GetValue(item, null).ToString();
finalvalue += value;
}
}
return finalvalue;
}
public static string GetMD5(string text)
{
var md5 = MD5CryptoServiceProvider.Create();
var encoding = new ASCIIEncoding();
byte[] stream = null;
var sb = new StringBuilder();
stream = md5.ComputeHash(encoding.GetBytes(text));
for (int i = 0; i < stream.Length; i++) sb.AppendFormat("{0:x2}", stream[i]);
return sb.ToString();
}
public static string PasswordMD5(string password)
{
var pwd = GetMD5(password + GetMD5(password).Substring(0,2));
return pwd;
}
通过方法RowHash,我将Row中的所有字段串联起来,除非将存储结果的字段哈希值合并在一起,然后将其发送到方法PasswordMD5,该方法创建了我们保存在数据库中的加密哈希。
然后我使用以下代码在SQL Server中执行相同的操作:
CONVERT(VARCHAR(32), HashBytes('MD5',CONVERT(VARCHAR(MAX),CONVERT(VARCHAR(MAX),ISNULL([Field1],''))+ISNULL([Field2],'')+ISNULL([Field3],'')+CONVERT(VARCHAR(MAX),ISNULL([Field4],''))+ISNULL(CONVERT(VARCHAR(MAX),[Field5]),'')+ISNULL(CONVERT(VARCHAR(MAX),Field6]),'')+CONVERT(VARCHAR(MAX),Field7]))+SUBSTRING(CONVERT(VARCHAR(32),HashBytes('MD5',CONVERT(VARCHAR(MAX),CONVERT(VARCHAR(MAX),ISNULL([Field1],''))+ISNULL([Field2],'')+ISNULL([Field3],'')+CONVERT(VARCHAR(MAX),ISNULL([Field4],''))+ISNULL(CONVERT(VARCHAR(MAX),Field5]),'')+ISNULL(CONVERT(VARCHAR(MAX),[Field6]),'')+CONVERT(VARCHAR(MAX),Field7]))) 2), 1, )), 2)
然后将其与我在C#中创建的哈希进行比较,以检查数据库中数据的完整性。对于没有特殊字符的所有行,此方法都可以很好地工作,但对于包含é或ö这样的特殊字符的所有行,此方法将失败。
这是我前一段时间遇到的一个问题,但是该任务由于其他优先级而暂停,我不记得我已经尝试过什么解决方案,我记得我尝试过一些解决方案来更改C#中字符串的编码,但是没有一个。
我做错了什么?
谢谢。
答案 0 :(得分:0)
最后,我无法使用MD5找到一个好的解决方案,我移至SHA256,并使用以下答案有效:
答案 1 :(得分:-1)
我将这种加密和解密方法用于我的代码,并且我已经用特殊字符对其进行了测试,它对我来说很好用。我希望我能将它发送给您,我会对其进行代码plz测试。
TableFilter是通用类文件,该文件包含加密和解密方法,您只能在.cs页上编写这两种方法。
public static string Encrypt(string toEncrypt, bool useHashing = true)
{
byte[] keyArray;
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
System.Configuration.AppSettingsReader settingsReader =
new AppSettingsReader();
// Get the key from config file
string key = (string)settingsReader.GetValue("EncryptionKey",
typeof(String));
//System.Windows.Forms.MessageBox.Show(key);
//If hashing use get hashcode regards to your key
if (useHashing)
{
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
//Always release the resources and flush data
// of the Cryptographic service provide. Best Practice
hashmd5.Clear();
}
else
keyArray = UTF8Encoding.UTF8.GetBytes(key);
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
//set the secret key for the tripleDES algorithm
tdes.Key = keyArray;
//mode of operation. there are other 4 modes.
//We choose ECB(Electronic code Book)
tdes.Mode = CipherMode.ECB;
//padding mode(if any extra byte added)
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateEncryptor();
//transform the specified region of bytes array to resultArray
byte[] resultArray =
cTransform.TransformFinalBlock(toEncryptArray, 0,
toEncryptArray.Length);
//Release resources held by TripleDes Encryptor
tdes.Clear();
//Return the encrypted data into unreadable string format
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public static string Decrypt(string cipherString, bool useHashing = true)
{
byte[] keyArray;
//get the byte code of the string
byte[] toEncryptArray = Convert.FromBase64String(cipherString);
System.Configuration.AppSettingsReader settingsReader =
new AppSettingsReader();
//Get your key from config file to open the lock!
string key = (string)settingsReader.GetValue("EncryptionKey",
typeof(String));
if (useHashing)
{
//if hashing was used get the hash code with regards to your key
MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
//release any resource held by the MD5CryptoServiceProvider
hashmd5.Clear();
}
else
{
//if hashing was not implemented get the byte code of the key
keyArray = UTF8Encoding.UTF8.GetBytes(key);
}
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
//set the secret key for the tripleDES algorithm
tdes.Key = keyArray;
//mode of operation. there are other 4 modes.
//We choose ECB(Electronic code Book)
tdes.Mode = CipherMode.ECB;
//padding mode(if any extra byte added)
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tdes.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(
toEncryptArray, 0, toEncryptArray.Length);
//Release resources held by TripleDes Encryptor
tdes.Clear();
//return the Clear decrypted TEXT
return UTF8Encoding.UTF8.GetString(resultArray);
}
:对于文本框字符串(而不是txtpassword.text,请使用testé123ö进行理解)
login_Model.Password = TableFilter.Encrypt("testingé123ö");
:Web.config
<add key="EncryptionKey" value="encyptionkeyvalue"/>