【发布时间】:2019-05-29 04:42:53
【问题描述】:
我在 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# 中创建的 Hash 进行比较,以检查我在数据库中拥有的数据的完整性。这适用于所有没有特殊字符的行,但对于包含任何特殊字符(如 é 或 ö)的所有行都失败。
这是我前段时间遇到的一个问题,但是任务被其他优先级暂停了,我不记得我已经尝试过哪些解决方案,我记得我尝试了一些解决方案来改变 C# 中字符串的编码但是没有工作。
我做错了什么?
提前致谢。
【问题讨论】:
-
看起来您已经将
nvarchar数据压缩为varchar,是的:会破坏很多非ASCII 字符。尝试始终使用nvarchar? -
也:“从 SQL Server 2016 (13.x) 开始,除 SHA2_256 和 SHA2_512 之外的所有算法都已弃用。较旧的算法(不推荐)将继续工作,但它们会引发弃用事件。” - 服务器不希望您为此使用 MD5。 您的用户不希望您为此使用 MD5。并且:它要求您发送未散列的密码而不是必要的。 IMO 你应该尽快散列 - 大概是立即在应用层 - 使用加盐和强(读取:慢)散列算法,如 PBKDF2、bcrypt 或 scrypt。
-
var encoding = new ASCIIEncoding();将删除不可打印的字符。
-
@jdweng 它肯定会消除任何非 ASCII 字符,你是对的;不过控制字符应该没问题
-
如果您实际上没有对密码进行哈希处理,请重命名该函数。如果您实际上是在散列密码,请停止使用 MD5。请注意,加密与散列不同(即使散列是加密散列);错误地使用这些词可能会导致一些混乱。您通常不会加密散列。如果散列仅用作加速查找或检测其他受信任环境中差异的一种方式,则不需要安全地对行数据进行散列,但散列密码没有这样的借口。
标签: c# sql-server cryptography md5 cryptographic-hash-function