【问题标题】:Trying to encrypt a random key for password reset functionality尝试加密用于密码重置功能的随机密钥
【发布时间】:2014-09-27 16:06:32
【问题描述】:

当用户通过输入用户名使用忘记密码字段时,我正在尝试加密要存储在用户表中的随机令牌。它还将向更改用户密码页面发送一封带有 URL 的电子邮件。这个 url 将有一个名为“key”的查询字符串参数。

www.mysite.com/Changepassword?key=xfsdfsdffsdfiughjksdf.

一旦用户点击链接,他们就在这个页面上。我有一个函数可以通过 ResetToken 获取用户。如果它找到一个用户然后继续。

我需要一些建议:

  1. 我应该使用什么样的随机令牌/加密技术 确保没有人可以进入 Changepassword 页面并猜到一个密钥 并能够更改用户密码。
  2. 我将如何处理使这个关键 URL 友好?

【问题讨论】:

    标签: c# encryption public-key-encryption


    【解决方案1】:

    如果您想获得超级安全,使用cryptographically secure random number generator 就可以了。转换为十六进制是确保其 URL 安全的最简单方法:

    byte[] bytes = new byte[8];
    using (var rng = RandomNumberGenerator.Create())
    {
        rng.GetBytes(bytes);
    }
    string key = string.Join("", bytes.Select(b => b.ToString("X2")));
    

    编辑请记住,电子邮件可能不安全,因此您的邮件有可能(尽管不太可能)在到达收件人之前被恶意第三方拦截。

    【讨论】:

    • 太棒了!那么我是否能够获取此密钥并将其作为 char 字段存储在我的用户表中,并在 url 中发送带有密钥的电子邮件?它对网址友好吗?
    • 密钥将是十六进制字符(每个字节 2 个字符),因此如果您使用 8 个字节,那么您将有 16 个字符。这些字符将仅为 0123456789ABCDEF,因此它们将是 URL 安全的。如果您想在数据库中节省一点空间,您可以将字节直接保存为数据库中的二进制(8),但将其存储为 char(16)可能更容易,这样您就不必考虑关于再次在二进制和文本之间进行转换。
    • 很抱歉再次打扰您,但我正在尝试将返回的密钥字符串存储到我的数据库中的 varbinary(8) 字段中。实体框架告诉我它需要一个 byte[] 数组。所以我尝试了 User.ResetKey = Encoding.UTF8.GetBytes(key) 这不应该工作吗?保存时出错。
    • 在我的代码示例中,bytes 是一个字节数组,可以作为二进制(8)保存到数据库中。 key 是一个字符串,表示 8 个字节的十六进制代码,但 key 本身是 16 个字符。 Encoding.UTF8.GetBytes(key) 获取字符串并转换为字节,这将为您提供代表这 16 个字符的 16 个字节。如果您只有十六进制字符串,并且想要获取字节,则必须使用类似于this question 的答案。
    • 您还应该确保令牌只能使用一次并且在合理的时间后过期。
    猜你喜欢
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 2021-09-22
    • 1970-01-01
    • 2019-06-04
    • 1970-01-01
    • 1970-01-01
    • 2014-10-05
    相关资源
    最近更新 更多