mysql - 用户内容网站在mysql中的密码存储

标签 mysql hash passwords sha

为了存储用户密码,我将使用 SHA 256 + 加盐。只是想确认这些是否正确。业务要求是密码应最少 8 个输入,最多 32 个输入。 (除空格外任何输入均有效)

因此,为了满足这些要求,计划是:
前端 - 验证 32 的最大输入和 8 的最小输入。

后端数据库 (MySQL) 架构将是:
pass_hash(64) CHAR - 存储密码哈希
pass_slt(32) VARCHAR - 为每个用户存储唯一的盐

对于加盐,我还不确定要使用什么值。但我认为当用户创建一个帐户时,我会为每个用户创建一个随机字符并使用它。那么另一个问题是:我是将盐存储为纯文本还是也需要散列/加密?

此外,我不知道这是否重要,但当前计划的密码能否支持多语言,或者我会遇到任何问题吗? (我说的是像阿拉伯语、中文等时髦的字符)

最佳答案

关于盐:

salt 是公共(public)数据(如果它是保密的,那么它就不会被称为“salt”,而是“key”)。盐必须是已知的才能验证密码(因为它与密码一起进入哈希函数)所以它被存储为明文,正如您打算做的那样。

加盐的目的是防止攻击者在攻击实例之间分摊攻击成本。猜测用户选择的密码通常是可能的(用户只有人脑,很少善于记住复杂的密码)。盐至少确保攻击者必须为每个被攻击的密码支付密码猜测的全部代价(即“尝试”可能密码的大字典)。

只要盐对于每个密码都是唯一的,它就可以正常工作。请注意,对每个用户 唯一是不够的:有时,用户会更改他们的密码,而您不希望对下一个密码使用相同的加盐(否则,某种程度的成本分摊可用于攻击者)。因此,您希望在每次存储密码时选择一个新盐,即创建帐户时每当更改密码时。

使用足够大的随机盐很容易确保盐的唯一性。 32 字节的盐对此绰绰有余:选择两次相同盐(运气不好)的风险可以忽略不计。

除了加盐之外,另一个安全级别是使密码散列“昂贵”。例如,当您对(加盐的)密码进行哈希处理时,实际上是对 salt+密码序列的 10000 次串联进行哈希处理。这使您和攻击者的密码验证成本提高 10000 倍。通常情况下,合法的密码验证可以在计算上变得更重而没有明显的效果(即使你每秒检查 100 个用户密码,你仍然可以投入 100 微秒,它只会使用你的处理时间的 1%),但是让攻击者的难度增加 10000 倍是个好主意。

关于语言:

非 ASCII 密码的主要问题是某些字形可能使用多种编码。例如,“é”可以使用 Unicode 编码为单个代码点(U+00E9 带尖音符号的拉丁文小写字母 E)或两个代码点(U+0065 拉丁文小写字母 E,后跟 U+0301 组合重音)。请注意,此示例是关于一个相当常见的法语字母,没有中文或韩文那么花哨(计算机方面)。编码问题可以通过 Unicode Normalization Forms 处理但这不是一项简单的编程任务。一些编程环境可以提供帮助(例如,在 Java 中,使用 java.text.Normalizer,它实现了 UNF)。

此外,对于切换键盘的用户来说,非 ASCII 密码可能难以输入,例如当用户想在酒店或机场使用共享计算机时(在此类系统上键入敏感密码无论如何都不是一个好主意)。

如果可能,我建议尝试强制使用仅 ASCII 密码,否则硬着头皮执行:执行 UNF(使用 NFD 格式),然后执行 UTF-8 编码。生成的字节序列进入哈希阶段。

关于mysql - 用户内容网站在mysql中的密码存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4084563/

相关文章:

MySQL 分组依据为空

c++ - 创建更好的哈希函数

javascript - python bcrypt 和 node.js bcrypt

javascript - 如何从 JavaScript 更改密码字段的文本?

c++ - 如何在 C++ 中删除密码屏蔽

shell - 如何更改AWS Cognito用户的密码?

c# - 将 MVC 连接到现有表

datetime - MySQL:过去 24 小时按小时插入的记录

mysql - 如何将(可变!) map 实现到网站中

c# - Telerik Sitefinity 密码哈希函数