匹配由Simplemembership创建的哈希密码和来自WPF的密码输入

时间:2014-01-08 01:27:18

标签: c# wpf encryption mvvm passwords

我有一个WPF应用程序和一个基于MVC的网站。我希望WPF应用程序读取MVC网站为密码信息创建的数据库是特定的哈希密码。如何散列输入的WPF密码以匹配MVC创建的数据库中的散列密码?

我已经拥有的东西:

  1. 是使用EF创建的基于MVC的网站 多个数据库。

  2. 其中一个数据库包含所有密码信息,例如 哈希密码和盐。

  3. 我在MVC项目中使用Simplemembership。

  4. 编辑:最初,我不知道我需要手动散列密码。感谢下面的解决方案,现在我知道了。我还没有测试过,因为我还在为它创建逻辑。

        [Table("webpages_Membership")]
    public class Membership
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int UserId { get; set; }
    
        public DateTime? CreateDate { get; set; }
        public string ConfirmationToken { get; set; }
        public bool IsConfirmed { get; set; }
        public DateTime? LastPasswordFailureDate { get; set; }
        public int PasswordFailuresSinceLastSuccess { get; set; }
        public string Password { get; set; }
        public DateTime? PasswordChangedDate { get; set; }
    
        [Required(AllowEmptyStrings = true), MaxLength(128)]
        public string PasswordSalt { get; set; }
    
        [MaxLength(128)]
        public string PasswordVerificationToken { get; set; }
    
        public DateTime? PasswordVerificationTokenExpirationDate { get; set; }
    }
    

    编辑: 我得出结论,我需要在网站上验证密码,并将布尔响应发送回验证凭据的wpf应用程序。我正在进一步研究这个问题,以确定我是否需要wcf或Web服务来实现这一目标。

2 个答案:

答案 0 :(得分:3)

我假设您使用的是SimpleMembershipProvider。默认情况下,密码是经过哈希处理的,这意味着加密只能以“单向”方式进行,一旦对字节数组进行哈希处理,就无法将其转换回纯文本格式。

基本上,您需要做的是从数据库和密码salt中检索哈希密码。然后对您的WPF应用程序用户提供的密码进行哈希处理(当前使用您刚刚从数据库中检索到的密码盐的纯文本。这是一个示例......

    public string HashPassword(string password, string passwordSalt)
    {
        int saltSize = 128 / 8;//128 bits = 16 bytes
        int PBKDF2SubkeyLength = 256 / 8; //256 bits = 32 bytes
        byte[] salt;
        byte[] subkey;
        using (var deriveBytes = new Rfc2898DeriveBytes(password, saltSize, 1000))
        {
            salt = deriveBytes.Salt;
            subkey = deriveBytes.GetBytes(PBKDF2SubkeyLength);
        }

        byte[] outputBytes = new byte[1 + saltSize + PBKDF2SubkeyLength];
        Buffer.BlockCopy(salt, 0, outputBytes, 1, saltSize);
        Buffer.BlockCopy(subkey, 0, outputBytes, 1 + saltSize, PBKDF2SubkeyLength);
        return Convert.ToBase64String(outputBytes);
    }

此方法将返回用于验证的密码哈希值,并将用户提供的密码与存储在数据库中的密码哈希值进行比较...

public bool Login(string username, string password)
{
    var user = GetUser(username); //get the user from the database including the password hash and salt

    //hash the password provided in the login screen
    string pwdHash = HashPassword(password, user.PasswordSalt);

   return pwdHash.equals(user.PasswordHash);
}

根据更多信息进行编辑

好的,你在这里遇到了一个大问题。从您提供的屏幕截图中我可以看到所有用户的密码盐都是空的,这可能是您所有问题的主要来源,因为密码是经过哈希处理的。我认为导致您发送空白密码盐的原因是您的EF实体中的映射,更具体地说是这一行代码......

[Required(AllowEmptyStrings = true), MaxLength(128)]
public string PasswordSalt { get; set; }

指示EF忽略空密码盐。您需要将其更改为...

[Required, MaxLength(128)]
public string PasswordSalt { get; set; }

但从本质上讲,您确实需要阅读SimpleMembershipProviderMVC4的教程,以便了解如何处理可能出现的其他问题。这是一个很好的Jon Galloway,请阅读

如果您遇到任何问题,请告诉我

答案 1 :(得分:0)

您可以使用客户端应用程序服务来执行此操作;见here