为什么要在密码里加点“盐”

盐(Salt)

在密码学中,是指通过在密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符,这种过程称之为“加盐”。

以上这句话是维基百科上对于 Salt 的定义,但是仅凭这句话还是很难理解什么叫 Salt,以及它究竟起到什么作用。

第一代密码

早期的软件系统或者互联网应用,数据库中设计用户表的时候,大致是这样的结构:

mysql> desc User;
+----------+--------------+------+-----+---------+-------+
| Field    | Type         | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| UserName | varchar(50)  | NO   |     |         |       |
| PassWord | varchar(150) | NO   |     |         |       |
+----------+--------------+------+-----+---------+-------+

数据存储形式如下:

mysql> select * from User;
+----------+----------+
| UserName | PassWord |
+----------+----------+
| lichao   | 123      |
| akasuna  | 456      |
+----------+----------+

主要的关键字段就是这么两个,一个是登陆时的用户名,对应的一个密码,而且那个时候的用户名是明文存储的,如果你登陆时用户名是 123,那么数据库里存的就是 123。这种设计思路非常简单,但是缺陷也非常明显,数据库一旦泄露,那么所有用户名和密码都会泄露,后果非常严重。参见 《优快云 详解 600 万用户密码泄露始末》

第二代密码

为了规避第一代密码设计的缺陷,聪明的人在数据库中不在存储明文密码,转而存储加密后的密码,典型的加密算法是 MD5 和 SHA1,其数据表大致是这样设计的:

mysql> desc User;
+----------+--------------+------+-----+---------+-------+
| Field    | Type         | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| UserName | varchar(50)  | NO   |     |         |       |
| PwdHash  | char(32)     | NO   |     |         |       |
+----------+--------------+------+-----+---------+-------+

数据存储形式如下:

mysql> select * from User;
+----------+----------------------------------+
| UserName | PwdHash                          |
+----------+----------------------------------+
| lichao   | 202cb962ac59075b964b07152d234b70 |
| akasuna  | 250cf8b51c773f3f8dc8b4be867a9a02 |
+----------+----------------------------------+

假如你设置的密码是 123,那么数据库中存储的就是 202cb962ac59075b964b07152d234b70 或 40bd001563085fc35165329ea1ff5c5ecbdbbeef。当用户登陆的时候,会把用户输入的密码执行 MD5(或者 SHA1)后再和数据库就行对比,判断用户身份是否合法,这种加密算法称为散列

严格地说,这种算法不能算是加密,因为理论上来说,它不能被解密。所以即使数据库丢失了,但是由于数据库里的密码都是密文,根本无法判断用户的原始密码,所以后果也不算太严重。

第三代密码

本来第二代密码设计方法已经很不错了,只要你密码设置得稍微复杂一点,就几乎没有被破解的可能性。但是如果你的密码设置得不够复杂,被破解出来的可能性还是比较大的。

好事者收集常用的密码,然后对他们执行 MD5 或者 SHA1,然后做成一个数据量非常庞大的数据字典,然后对泄露的数据库中的密码就行对比,如果你的原始密码很不幸的被包含在这个数据字典中,那么花不了多长时间就能把你的原始密码匹配出来。这个数据字典很容易收集,优快云 泄露的那 600w 个密码,就是很好的原始素材。

于是,第三代密码设计方法诞生,用户表中多了一个字段:

mysql> desc User;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| UserName | varchar(50) | NO   |     |         |       |
| Salt     | char(50)    | NO   |     |         |       |
| PwdHash  | char(32)    | NO   |     |         |       |
+----------+-------------+------+-----+---------+-------+

数据存储形式如下:

mysql> select * from User;
+----------+----------------------------+----------------------------------+
| UserName | Salt                       | PwdHash                          |
+----------+----------------------------+----------------------------------+
| lichao   | 1ck12b13k1jmjxrg1h0129h2lj | 6c22ef52be70e11b6f3bcf0f672c96ce |
| akasuna  | 1h029kh2lj11jmjxrg13k1c12b | 7128f587d88d6686974d6ef57c193628 |
+----------+----------------------------+----------------------------------+

Salt 可以是任意字母、数字、或是字母或数字的组合,但必须是随机产生的,每个用户的 Salt 都不一样,用户注册的时候,数据库中存入的不是明文密码,也不是简单的对明文密码进行散列,而是 MD5( 明文密码 + Salt),也就是说:

MD5('123' + '1ck12b13k1jmjxrg1h0129h2lj') = '6c22ef52be70e11b6f3bcf0f672c96ce'
MD5('456' + '1h029kh2lj11jmjxrg13k1c12b') = '7128f587d88d6686974d6ef57c193628'

当用户登陆的时候,同样用这种算法就行验证。

由于加了 Salt,即便数据库泄露了,但是由于密码都是加了 Salt 之后的散列,坏人们的数据字典已经无法直接匹配,明文密码被破解出来的概率也大大降低。

是不是加了 Salt 之后就绝对安全了呢?淡然没有!坏人们还是可以他们数据字典中的密码,加上我们泄露数据库中的 Salt,然后散列,然后再匹配。但是由于我们的 Salt 是随机产生的,假如我们的用户数据表中有 30w 条数据,数据字典中有 600w 条数据,坏人们如果想要完全覆盖的坏,他们加上 Salt 后再散列的数据字典数据量就应该是 300000* 6000000 = 1800000000000,一万八千亿啊,干坏事的成本太高了吧。但是如果只是想破解某个用户的密码的话,只需为这 600w 条数据加上 Salt,然后散列匹配。可见 Salt 虽然大大提高了安全系数,但也并非绝对安全。

实际项目中,Salt 不一定要加在最前面或最后面,也可以插在中间嘛,也可以分开插入,也可以倒序,程序设计时可以灵活调整,都可以使破解的难度指数级增长。

PS,文中所谓第一、二、三代密码的称呼,是我自己 YY 的。


http://www.libuchao.com/2013/07/05/password-salt

<think>好的,用户想了解Windows系统中文件名前出现的原因及解决方法。首先,我需要回忆一下Windows的文件命名规则。Windows不允许文件名以开头,这通常是类Unix系统的做法,比如Linux和macOS。所以,当用户提到文件名前面有,可能是在尝试创建以开头的文件时遇到了问题,或者是系统自动添加了。 接下来,检查用户提供的引用内容。引用[1]提到在Windows上创建以开头的文件会报错,说明正常情况下Windows不允许这样做。但用户的问题是关于文件名前自动添加的情况,这可能与某些程序或脚本有关。例如,某些应用程序或批处理脚本可能在保存文件时错误地添加了或者用户使用了第三方工具绕过限制,导致文件名异常。 然后,考虑可能的原因。一种可能是用户使用的软件或脚本存在bug,导致文件名被错误地添加了。另一种可能是用户在跨平台环境中工作,比如从Linux系统复制文件到Windows,导致文件名中出现,但这种情况通常会被Windows拒绝,除非使用特殊方法。 解决方法方面,首先需要确认这些文件是如何产生的。如果是手动创建,用户应避免使用开头,或使用命令行工具如`echo > .file`来创建,但需要管理员权限。如果是程序自动生成,需要检查程序逻辑,确保符合Windows命名规则。此外,可以使用批量重命名工具或脚本(如引用[2]提到的)来删除文件名前的。 还需要考虑系统错误或病毒的可能性,但这种情况较少见。用户应检查系统是否有异常进程,并运行杀毒软件扫描。最后,建议用户遵循Windows命名规范,避免特殊字符,以确保兼容性。</think>在Windows系统中,文件名前出现的情况通常与以下原因相关: ### 一、原因分析 1. **非法命名规则触发** Windows默认禁止文件名以(.)开头,这与UNIX/Linux系统不同。当尝试创建如`.npmignore`这类文件名时,系统会报错"必须键入文件名"[^1]。若出现文件名自动加的异常情况,可能是: - 使用了非官方文件管理工具绕过限制 - 从其他操作系统复制文件时残留的命名格式 - 程序代码未正确处理文件名校验 2. **脚本或程序缺陷** 某些批量重命名脚本(如引用[2]的汉字转拼音程序)若存在逻辑错误,可能在处理Unicode字符时异常添加特殊符号。类似问题也可能出现在自动化办公工具中[^3]。 ### 二、解决方法 1. **基础排查** ```cmd :: 在CMD中尝试创建带文件测试 echo test > .testfile ``` 若提示"文件名、目录名或卷标语法不正确",说明系统限制仍然生效,此时发现的带文件应为第三方工具生成。 2. **批量修正方案** 使用PowerShell脚本批量修正(示例): ```powershell Get-ChildItem -Path "目标目录" | Rename-Item -NewName { $_.Name -replace '^\.','' } ``` 该命令会删除文件名开头的,同时保留扩展名。 3. **预防措施** - 禁用非常规文件管理工具 - 跨平台传输文件时使用压缩包作为中介 - 开发涉及文件操作的代码时,添加命名规范校验: ```python def safe_filename(name): return name.lstrip('.') # 去除开头的 ``` ### 三、特殊场景说明 在NTFS文件系统中,虽然可以通过`\\?\`前缀创建特殊文件名,但这类操作会导致资源管理器显示异常,且可能引发应用程序崩溃,不建议普通用户使用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值