[每日短篇]4-密码的设计要点

前言

设计一个系统的时候难免要涉及到密码,从密码的设计处理上很可以看出来水平。网上还是很容易见到某些国内自称优秀的框架设计的密码存储是明文的,更是见过某不只是世界500强公司的安全 SE 写个规范要求 web 端把密码 MD5 之后再传输。实际上要设计一个健壮安全的系统,远不是一个密码可以解决的,也远不是一个短篇可以解决的,今天的重点仅放在密码的一点点最最基本的设计上,毕竟大多数人是不会同时知道 hash 和 salt 的,系统里看不到明文,然后还有至少一个概念没听过,足以让对方觉得你专业了。

要点

1. 密码要 hash 存储不要存储明文,算法选择 MD5 在可预见的未来用在非敏感系统上没有问题,针对一个已知的 hash 值构造一个碰撞并不容易,别信那些出于为了表现自己懂密码学说 MD5 已经被破解了的人说的任何话。推荐用 SHA-256,可以在未来若干年内不用担心在各种莫名规定下被迫更换强度更高的算法;
2. 要有一个 salt 字段,这个字段一定要随机生成而不要是从用户名或者别的什么东西推导出来的值,长度推荐与密码的最大长度一致或者至少20字符(个人推荐,没有什么科学道理,主要担心数据库设计密码最大长度太短)。个人推荐 salt 加在密码明文前面再做 hash,实际上加在前中后都可以,重要的只是位数要够长;
3. 传输密码时最容易实现且保证安全的方式是通过 https 传输密码的明文,各种客户端花式加密对于保护密码安全没有任何用处,更何况那只是个待验证的密码;
4. 移动端不管是 app 还是 web,要么直接密码框显示明文,要么提供一个明文和隐藏切换的按钮,这已经是明显的趋势了;
5. 不要自作聪明从客户端将密码 hash 之后再传递到服务器端与存储的 hash 比较,这跟传明文是一样的,别人用获取明文的技术获取的 hash 值传递给服务器端后还是会通过验证,怕被嗅探就上 https 好了;
6. 限制密码字符在 ASCII 范围内,通常支持大小写英文字母、数字和常见的符号就好了,不然很可能会栽在真实用户五花八门的系统的字符集上,这条其实真不该有,但是想想有几个人可以正确理解和处理好字符集问题,那还是有吧~

程序上的提示

1. Hash
Apache Commons Codec 方案

String sha256hex = DigestUtils.sha256Hex(originalString);

Guava 方案

String sha256hex = Hashing.sha256().hashString(originalString, StandardCharsets.UTF_8).toString();

我更推荐 Apache Commons Codec 方案,除了短之外,关键就是不涉及字符集。从经验来看,只要是在公司里跟别人合写代码,最好是选择看不到字符集的解决方案。这2个库当前最新版坐标

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.11</version>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>27.0-jre</version>
</dependency>

2. Salt
简单粗暴用 UUID 就好

String salt = UUID.randomUUID().toString();

3. 比较密码
Apache Commons Codec 贴心地从 Lang3 里面把 StringUtils.equals 复制来了,用这个最省心,不用再依赖 Lang3。如果用原生的 API,记得要用 equals 方法,莫要直接 ==。

转载于:https://my.oschina.net/u/1762727/blog/2558941

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值