使用.NET或MS SQL模拟MySql的密码()加密

时间:2009-05-15 12:46:03

标签: .net sql mysql sql-server encryption

我正在将旧的ASP / MySql webapp更新为ASP.NET / MS SQL。

我们希望旧网站的登录信息能够在新应用中保留。

不幸的是,密码使用MySql的password()函数存储在MySql DB中。

是否可以在.NET或.NET中模拟MySql的password()函数    MS SQL?

感谢任何帮助/链接。

7 个答案:

答案 0 :(得分:13)

根据MySQL文档,该算法是双SHA1哈希。在检查MySQL源代码时,您会在libmysql / password.c中找到一个名为make_scrambled_pa​​ssword()的函数。该功能定义如下:

/*
    MySQL 4.1.1 password hashing: SHA conversion (see RFC 2289, 3174) twice
    applied to the password string, and then produced octet sequence is
    converted to hex string.
    The result of this function is used as return value from PASSWORD() and
    is stored in the database.
  SYNOPSIS
    make_scrambled_password()
    buf       OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
    password  IN  NULL-terminated password string
*/

void
make_scrambled_password(char *to, const char *password)
{
  SHA1_CONTEXT sha1_context;
  uint8 hash_stage2[SHA1_HASH_SIZE];

  mysql_sha1_reset(&sha1_context);
  /* stage 1: hash password */
  mysql_sha1_input(&sha1_context, (uint8 *) password, (uint) strlen(password));
  mysql_sha1_result(&sha1_context, (uint8 *) to);
  /* stage 2: hash stage1 output */
  mysql_sha1_reset(&sha1_context);
  mysql_sha1_input(&sha1_context, (uint8 *) to, SHA1_HASH_SIZE);
  /* separate buffer is used to pass 'to' in octet2hex */
  mysql_sha1_result(&sha1_context, hash_stage2);
  /* convert hash_stage2 to hex string */
  *to++= PVERSION41_CHAR;
  octet2hex(to, (const char*) hash_stage2, SHA1_HASH_SIZE);
}

考虑到这种方法,你可以创建一个基本上做同样事情的.NET对应物。这就是我想出的。当我运行SELECT PASSWORD('test');对于我的本地MySQL副本,返回的值是:

*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29

根据源代码(再次在password.c中),开头的星号表示这是加密密码的MySQL 4.1后方法。例如,当我在VB.Net中模拟功能时,我就会想到这一点:

Public Function GenerateMySQLHash(ByVal strKey As String) As String
    Dim keyArray As Byte() = Encoding.UTF8.GetBytes(strKey)
    Dim enc = New SHA1Managed()
    Dim encodedKey = enc.ComputeHash(enc.ComputeHash(keyArray))
    Dim myBuilder As New StringBuilder(encodedKey.Length)

    For Each b As Byte In encodedKey
        myBuilder.Append(b.ToString("X2"))
    Next

    Return "*" & myBuilder.ToString()
End Function

请记住,SHA1Managed()位于System.Security.Cryptography命名空间中。此方法返回与MySQL中的PASSWORD()调用相同的输出。我希望这对你有所帮助。

编辑:这是C#中的相同代码

public string GenerateMySQLHash(string key)
{
    byte[] keyArray = Encoding.UTF8.GetBytes(key);
    SHA1Managed enc = new SHA1Managed();
    byte[] encodedKey = enc.ComputeHash(enc.ComputeHash(keyArray));
    StringBuilder myBuilder = new StringBuilder(encodedKey.Length);

    foreach (byte b in encodedKey)
        myBuilder.Append(b.ToString("X2"));

    return "*" + myBuilder.ToString();
}

答案 1 :(得分:1)

您可以使用.Net中的MD5或SHA1加密字符串,但MySQL使用的实际算法可能与这两种方法不同。我怀疑它是基于某种基于服务器实例的“盐”,但我不知道。

理论上,由于我认为MySQL是开源的,你可以调查源并确定如何完成。

http://dev.mysql.com/doc/refman/5.1/en/encryption-functions.html#function_password

编辑1:我相信使用的算法是双SHA1和其他'调整'(根据this博客文章)。

答案 2 :(得分:1)

  

“他们不会透露什么   他们使用的算法“

呃......有人应该醒来并告诉你MySQL是 OPEN SOURCE ......他们不需要“透露”某些东西,因为每个人都可以阅读数据库的结构 - 只需下载来源,搜索加密函数(我猜他们正在使用C ++)并开始调查...... SHA1现在看起来非常不安全 - 就在最近,一些科学家已经证明,可以无限制地选择 20%的数据,并且生成相同的哈希,这样就可以了建议使用AES或SHA2(因此不是MySQL- PASSWORD -func)

答案 3 :(得分:1)

修改了C#版本以纠正填充问题         [测试]         public void GenerateMySQLHashX2()         {             string password =“20iva05”;

        byte[] keyArray = Encoding.UTF8.GetBytes(password);
        SHA1Managed enc = new SHA1Managed();
        byte[] encodedKey = enc.ComputeHash(enc.ComputeHash(keyArray));
        StringBuilder myBuilder = new StringBuilder(encodedKey.Length);

        foreach (byte b in encodedKey)
        {
            log.Debug(b.ToString() + "    ->   " +  b.ToString("X2"));
            myBuilder.Append(b.ToString("X2"));
        }

        Assert.AreEqual("*8C2029A96507478FD1720F6B713ADD57C66EED49", "*" + myBuilder.ToString());
    } 

答案 4 :(得分:0)

对于VB net,这个填充左侧为0,这样当十六进制代码为[例如]'E'时,此函数将正确地将“0E”附加到结果字符串。所以最后,包括预先填写的'*',结果字符串将是41个字符长,如MySQL所要求的那样

Public Function GenerateMySQLHash(ByVal strKey As String) As String

    Dim keyArray As Byte() = System.Text.UTF8Encoding.UTF8.GetBytes(strKey)
    Dim enc = New Security.Cryptography.SHA1Managed()
    Dim encodedKey = enc.ComputeHash(enc.ComputeHash(keyArray))
    Dim myBuilder As New System.Text.StringBuilder(encodedKey.ToString.Length)

    For Each b As Byte In encodedKey
        myBuilder.Append(Strings.Right("0" & b.ToString("X"), 2))
    Next

    Return "*" & myBuilder.ToString()
End Function

答案 5 :(得分:0)

mysql密码功能不是特别安全 (例如,没有盐或其他防止寻找匹配哈希的方法) 我想看到想要复制算法的唯一原因是 1:你有一个mysql password()s的用户列表/表 2:你想从用户表中的哈希中破解mysql密码。

否则使用不同的东西,例如将用户名(和/或其他行不变)与其密码组合在一起的散列。如果两个用户选择相同的密码,那将是不明显的。如果表被暴露,安全性不会以相同的速率降低 (例如google for 446a12100c856ce9,这是一个非常受欢迎的密码的密码()哈希)

答案 6 :(得分:-3)

您将无法模拟MySql密码()函数。至少没有大量的工作和运气。由于MySql使用他们自己的算法来单向加密字符串,他们不会透露他们使用的算法;这意味着您必须进行反复试验,比较结果字符串等。

解决问题:

我会复制数据库,但保持与MySql的连接。使用标志来标识首次登录。让他们使用他们当前的密码;使用MySql password()函数验证密码。如果密码有效;通过再次输入相同的密码或新密码,让他们重置密码;此时使用您最喜欢的加密算法并将结果存储在MS Sql DB中。

我知道这听起来很痛苦,但是你最好不要试图破解你的解密MySql加密算法。

祝你好运!