【问题标题】:ASP.NET membership salt?ASP.NET 会员盐?
【发布时间】:2014-08-14 17:20:21
【问题描述】:

ASP.NET 成员如何生成他们的 salt key,然后他们如何对其进行编码(即是 salt + password 还是 password + salt)?

我将SHA-1 用于我的会员资格,但我想重新创建相同的盐,以便内置会员资格的东西可以像我的东西一样散列这些东西。

编辑 2: 没关系。我误读了它,并认为它说的是字节,而不是位。所以我传递的是 128 字节,而不是 128 位。

编辑:我一直在努力做到这一点。这就是我所拥有的,

public string EncodePassword(string password, string salt)
{
    byte[] bytes = Encoding.Unicode.GetBytes(password);
    byte[] src = Encoding.Unicode.GetBytes(salt);
    byte[] dst = new byte[src.Length + bytes.Length];

    Buffer.BlockCopy(src, 0, dst, 0, src.Length);
    Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);

    HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");

    byte[] inArray = algorithm.ComputeHash(dst);

    return Convert.ToBase64String(inArray);
}

private byte[] createSalt(byte[] saltSize)
{
    byte[] saltBytes = saltSize;

    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    rng.GetNonZeroBytes(saltBytes);

    return saltBytes;
}

所以我没有尝试查看 ASP.NET 成员是否会识别这一点,但散列密码看起来很接近。我只是不知道如何将其转换为 base64 的盐。

我做了这个

byte[] storeSalt = createSalt(new byte[128]);
string salt = Encoding.Unicode.GetString(storeSalt);
string base64Salt = Convert.ToBase64String(storeSalt);

int test = base64Salt.Length;

测试长度为 172,远远超过 128 位,所以我做错了什么?

这就是他们的盐的样子

vkNj4EvbEPbk1HHW+K8y/A==

这就是我的盐的样子

E9oEtqo0livLke9+csUkf2AOLzFsOvhkB/NocSQm33aySyNOphplx9yH2bgsHoEeR/aw/pMe4SkeDvNVfnemoB4PDNRUB9drFhzXOW5jypF9NQmBZaJDvJ+uK3mPXsWkEcxANn9mdRzYCEYCaVhgAZ5oQRnnT721mbFKpfc4kpI=

【问题讨论】:

标签: asp.net security hash asp.net-membership


【解决方案1】:

What is default hash algorithm that ASP.NET membership uses? 对他们的默认算法进行了很好的讨论。

希望对你有帮助!

编辑- 我指的答案是顶帖中的代码,

   public string EncodePassword(string pass, string salt)
    {
        byte[] bytes = Encoding.Unicode.GetBytes(pass);
        //byte[] src = Encoding.Unicode.GetBytes(salt); Corrected 5/15/2013
        byte[] src = Convert.FromBase64String(salt); 
        byte[] dst = new byte[src.Length + bytes.Length];
        Buffer.BlockCopy(src, 0, dst, 0, src.Length);
        Buffer.BlockCopy(bytes, 0, dst, src.Length, bytes.Length);
        HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
        byte[] inArray = algorithm.ComputeHash(dst);
        return Convert.ToBase64String(inArray);
    } 

他们正在使用 BlockCopy 结合 Unicode Salt + Pass

-- 回答你的问题:

这两种算法都是必要的,并且扮演着不同的角色......

RNG Crypto 用于生成盐。它基本上是一长串随机数据。这是基于每个用户生成和存储的。通常这是在创建用户或更改密码时完成的。

BlockCopy 只是他们用来将盐与密码结合起来的方法。上面的代码本质上等同于盐+密码。

您将无法重新创建盐值,因为它是完全随机的。但是,它由框架为每个用户存储。

将盐与密码结合起来,并使用上述技术对其进行散列处理,将允许您使用框架存储的散列值验证用户密码。

我认为我们都以不同的方式阅读您的问题。我发布的代码不会生成你的 salt,但它会让你以与 ASP.NET 成员资格兼容的方式使用它。

对不起,我的解释不是最好的——这能回答你的问题吗?

【讨论】:

  • 没有告诉你微软是怎么做 Salt 的。
  • 顶帖展示了算法 - 为了清楚起见,我在这里复制了它。
  • 对不起-我明白你的意思了。我假设他正在寻找如何组合它以从现有数据中重新创建。
  • 嗨,我不明白。他们说他们使用 RNGCrypto 的文档中的 blockCopy 是什么。它也不会生成盐。
  • Grr - 在 cmets 中无法清楚地解释。我会将所有内容添加到我的帖子正文中。对不起。
【解决方案2】:

以下是 SQLMembershipProvider 生成盐的方式。

    private string GenerateSalt() {
        var buf = new byte[16];
        (new RNGCryptoServiceProvider()).GetBytes(buf);
        return Convert.ToBase64String(buf);
   }

您可以下载 ASP.NET 的 SQL Provider 代码here

我遇到的问题是在 IIS7 上运行的开发应用程序。 .NET 4.0 使用的默认哈希算法与 .NET 2.0 的默认 HashAlgorithmType 不同。

在 Microsoft 的“EncodePassword”示例代码中,他们引用了Membership.HashAlgorithmType,如果web.config 中未指定,我相信它会返回框架的默认值。

我能够让 GenerateSalt 和 EncodePassword 方法都适用于我的应用程序。

我的组合代码:

internal string GenerateSalt()
{
    byte[] buf = new byte[16];
    (new RNGCryptoServiceProvider()).GetBytes(buf);
    return Convert.ToBase64String(buf);
}

internal string EncodePassword(string pass, int passwordFormat, string salt)
{
    if (passwordFormat == 0) // MembershipPasswordFormat.Clear
        return pass;

    byte[] bIn = Encoding.Unicode.GetBytes(pass);
    byte[] bSalt = Convert.FromBase64String(salt);
    byte[] bAll = new byte[bSalt.Length + bIn.Length];
    byte[] bRet = null;

    Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
    Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);
    if (passwordFormat == 1)
    { // MembershipPasswordFormat.Hashed
        HashAlgorithm s = HashAlgorithm.Create("SHA1");
        // Hardcoded "SHA1" instead of Membership.HashAlgorithmType
        bRet = s.ComputeHash(bAll);
    }
    else
    {
        bRet = EncryptPassword(bAll);
    }
    return Convert.ToBase64String(bRet);
}

【讨论】:

  • RhinoDevX64,您的答案正是我想要的!非常感谢,您结束了我数日来试图弄清楚如何将我的字符串与数据库中的哈希/盐信息进行比较的斗争!
  • 谢谢。但我不明白,如果盐是随机生成的,那么您可以将登录时使用的纯文本密码与存储的散列密码进行比较。盐需要存放在某个地方才能匹配吗?
【解决方案3】:

这是一种方法。盐只是一个随机数,您可以使用框架库中的 RNGCryptoServiceProvider 类生成好的随机数作为盐使用

private const int ITERATIONS = 10000;
private const int SALT_SIZE = 32;
private const int HASH_SIZE = 32;

public void SaltAndHashPassword(string password, out byte[] salt,
  out byte[] hash)
{
  Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(
    password,
    SALT_SIZE,
    ITERATIONS);

  salt = rdb.Salt;
  hash = rdb.GetBytes(HASH_SIZE);
}

【讨论】:

  • 嗨,我在 msdn 上找到了这个“PasswordSalt:随机生成的 128 位值,用于对密码哈希进行加盐;以 base-64 编码形式存储”msdn.microsoft.com/en-us/library/aa478949.aspx 那么我该怎么做128?哈希大小如何?
  • 他们也有这个 MembershipPasswordFormat.Hashed(默认),它存储从密码和密码答案生成的加盐哈希。 salt 是由 .NET Framework 的 RNGCryptoServiceProvider 类生成的随机 128 位值。每个密码/密码答案对都使用这个唯一值加盐,加盐存储在 aspnet_Membership 表的 PasswordSalt 字段中。密码和盐的散列结果存储在密码字段中。同样,密码答案和盐的散列结果存储在 PasswordAnswer 字段中。
猜你喜欢
  • 2012-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多