过去一段时间以来, 许多的网站遭遇用户密码数据泄露事件, 这其中包括顶级的互联网企业–Linkedin, 国内诸如CSDN,该事件横扫整个国内互联网,随后又爆出多玩游戏800万用户资料被泄露,另有传言人人网、开心网、天涯社区、世纪佳缘、百合网等社区都有可能成为黑客下一个目标。层出不穷的类似事件给用户的网上生活造成巨大的影响,人人自危,因为人们往往习惯在不同网站使用相同的密码,所以一家“暴库”,全部遭殃。

那么我们作为一个Web应用开发者,在选择密码存储方案时, 容易掉入哪些陷阱, 以及如何避免这些陷阱?

普通方案

目前用的最多的密码存储方案是将明文密码做单向哈希后存储,单向哈希算法有一个特征:无法通过哈希后的摘要(digest)恢复原始数据,这也是“单向”二字的来源。常用的单向哈希算法包括SHA-256, SHA-1, MD5等。

Go语言对这三种加密算法的实现如下所示:

//import "crypto/sha256"
h := sha256.New()
io.WriteString(h, "His money is twice tainted: 'taint yours and 'taint mine.")
fmt.Printf("% x", h.Sum(nil))//import "crypto/sha1"
h := sha1.New()
io.WriteString(h, "His money is twice tainted: 'taint yours and 'taint mine.")
fmt.Printf("% x", h.Sum(nil))//import "crypto/md5"
h := md5.New()
io.WriteString(h, "需要加密的密码")
fmt.Printf("%x", h.Sum(nil))

单向哈希有两个特性:

  • 1)同一个密码进行单向哈希,得到的总是唯一确定的摘要。
  • 2)计算速度快。随着技术进步,一秒钟能够完成数十亿次单向哈希计算。

结合上面两个特点,考虑到多数人所使用的密码为常见的组合,攻击者可以将所有密码的常见组合进行单向哈希,得到一个摘要组合, 然后与数据库中的摘要进行比对即可获得对应的密码。这个摘要组合也被称为rainbow table

因此通过单向加密之后存储的数据,和明文存储没有多大区别。因此,一旦网站的数据库泄露,所有用户的密码本身就大白于天下。

进阶方案

通过上面介绍我们知道黑客可以用rainbow table来破解哈希后的密码,很大程度上是因为加密时使用的哈希算法是公开的。如果黑客不知道加密的哈希算法是什么,那他也就无从下手了。

一个直接的解决办法是,自己设计一个哈希算法。然而,一个好的哈希算法是很难设计的——既要避免碰撞,又不能有明显的规律,做到这两点要比想象中的要困难很多。因此实际应用中更多的是利用已有的哈希算法进行多次哈希。

但是单纯的多次哈希,依然阻挡不住黑客。两次 MD5、三次 MD5之类的方法,我们能想到,黑客自然也能想到。特别是对于一些开源代码,这样哈希更是相当于直接把算法告诉了黑客。

没有攻不破的盾,但也没有折不断的矛。现在安全性比较好的网站,都会用一种叫做“加盐”的方式来存储密码,也就是常说的 “salt”。他们通常的做法是,先将用户输入的密码进行一次MD5(或其它哈希算法)加密;将得到的 MD5 值前后加上一些只有管理员自己知道的随机串,再进行一次MD5加密。这个随机串中可以包括某些固定的串,也可以包括用户名(用来保证每个用户加密使用的密钥都不一样)。

//import "crypto/md5"
//假设用户名abc,密码123456
h := md5.New()
io.WriteString(h, "需要加密的密码")//pwmd5等于e10adc3949ba59abbe56e057f20f883e
pwmd5 :=fmt.Sprintf("%x", h.Sum(nil))//指定两个 salt: salt1 = @#$%   salt2 = ^&*()
salt1 := "@#$%"
salt2 := "^&*()"//salt1+用户名+salt2+MD5拼接
io.WriteString(h, salt1)
io.WriteString(h, "abc")
io.WriteString(h, salt2)
io.WriteString(h, pwmd5)last :=fmt.Sprintf("%x", h.Sum(nil))

在两个salt没有泄露的情况下,黑客如果拿到的是最后这个加密串,就几乎不可能推算出原始的密码是什么了。

专家方案

上面的进阶方案在几年前也许是足够安全的方案,因为攻击者没有足够的资源建立这么多的rainbow table。 但是,时至今日,因为并行计算能力的提升,这种攻击已经完全可行。

怎么解决这个问题呢?只要时间与资源允许,没有破译不了的密码,所以方案是:故意增加密码计算所需耗费的资源和时间,使得任何人都不可获得足够的资源建立所需的rainbow table

这类方案有一个特点,算法中都有个因子,用于指明计算密码摘要所需要的资源和时间,也就是计算强度。计算强度越大,攻击者建立rainbow table越困难,以至于不可继续。

这里推荐scrypt方案,scrypt是由著名的FreeBSD黑客Colin Percival为他的备份服务Tarsnap开发的。

目前Go语言里面支持的库http://code.google.com/p/go/source/browse?repo=crypto#hg%2Fscrypt

dk := scrypt.Key([]byte("some password"), []byte(salt), 16384, 8, 1, 32)

通过上面的的方法可以获取唯一的相应的密码值,这是目前为止最难破解的。

golang存储密码相关推荐

  1. Android静态安全检测 - WebView明文存储密码

    WebView明文存储密码 -WebSettings.setSavePassword方法 一.API 1. 继承关系 [1]java.lang.Object [2]android.webkit.Web ...

  2. 为什么 char 数组比 String 更适合存储密码?

    另一个基于 String 的棘手 Java 问题,相信我只有很少的 Java 程序员可以正确回答这个问题. 这是一个真正艰难的核心 Java 面试问题,并且需要对 String 的扎实知识才能回答这个 ...

  3. Java存储密码用字符数组

    字符数组和字符串都可以用于存储文本数据,但是在选择具体哪一种时,如果你没有针对具体的情况是很难回答这个问题的.但是任何与字符串相关的问题一定有线索可以在字符串的属性里面找到,比如不可变性.他就用这种方 ...

  4. 创建存储,修改存储_安全地创建和存储密码

    创建存储,修改存储 几乎每次涉及用户配置文件时,都必须管理用户凭据,从而能够创建和存储用户密码. 通常应该使用哈希密码和盐分密码来准备数据库公开和通过使用Rainbow表进行哈希逆转. 但是,找到以明 ...

  5. 安全地创建和存储密码

    几乎每次涉及用户配置文件时,都必须管理用户凭据,从而能够创建和存储用户密码. 通常应该使用散列密码和盐分密码来准备数据库公开和通过使用Rainbow表进行散列反转的密码. 但是,找到以明文形式存储的密 ...

  6. 国产加密实际运用:使用SM3加盐存储密码,并且使用SM2进行登录认证

    目录 1.简要 2.开发环境及工具 3.后台密码加密部分 3.1加密代码 3.2 SM3加密类(Sm3crypto) 3.3国密SM3工具类(Sm3Utils) 3.4国密相关依赖包 4.登录认证部分 ...

  7. 你的数据库到底应该如何存储密码?

    最近接手公司一个之前的服务,竟然发现用户密码是明文存储在数据库中! 说实话还是有点吃惊的,这可不兴学 CSDN 呀(手动狗头),至少也得搞个 MD5 存一存吧. 不过 MD5 其实也没啥用,今天我们就 ...

  8. 所有程序中的java在哪里设置密码_关于安全性:如何在桌面客户端应用程序(Java)中存储密码和敏感数据?...

    我想制作一个应用程序,它将监控用户的电子邮件帐户接收电子邮件,以及他的Twitter帐户的tweets.因此,用户必须提供登录凭据.我的疑问是如何和在哪里存储这些敏感数据?我不希望我的应用程序打扰用户 ...

  9. 密码忘了怎么办?——如何找回多可系统的加密存储密码

    今天有用户来电话说,他忘记加密存储的密码了,登不进系统,怎么办? 嗯,太正常了,非常理解,对我们大多数人来说,密码就是用来忘记的... 密码忘了不可怕,只要能找回就可以! 在多可文档管理系统里,你可以 ...

最新文章

  1. isnull的使用方法
  2. 笔记本电脑自带麦克风吗_小米电视可以唱歌吗
  3. 一、前端必须掌握HTML的基础知识
  4. Java线程池的工作原理与实现
  5. .NET Conf China 2020志愿者招募火热开启!还有神秘惊喜等你来领…
  6. leetcode174. 地下城游戏(动态规划)
  7. 敏捷开发用户故事系列之一:何为用户故事
  8. Inception-Resnet结构(code)
  9. xxx.app 已损坏无法打开,来自身份不明的开发者解决方法
  10. 华硕主板如何用u盘启动计算机,最新华硕主板bios设置u盘启动教程
  11. for /f 用法详解
  12. 北京理工大学计算机科学与技术培养方案,王全玉_北京理工大学计算机学院
  13. ps无法存储为html,ps一直无法存储因为程序错误的解决方法
  14. docker如何下载国外镜像
  15. ffserver服务器实现WebM格式视频直播
  16. android字体ratingbar,Android 自定义View之自定义评分选择器RatingBar
  17. 计算机B的IP地址是,IP地址202.117.17.255/22是什么地址?()。A.网络地址B.全局 - 信管网...
  18. 二进制文件操作,自己参考的
  19. 破解行Android apk 逆向工程研究﹣破解 MyTV HD 機種限制手記
  20. linux CPU主频设置

热门文章

  1. 【计算理论】正则语言 ( 正则表达式原子定义 | 正则表达式递归定义 | 正则表达式语言原子定义 | 正则表达式语言结构归纳 | 正则表达式语言示例 | 根据正则表达式构造自动机 )
  2. 【设计模式】原型模式 ( 概念简介 | 使用场景 | 优缺点 | 基本用法 )
  3. Mac启动时:boot task failed:fsck-safe处理办法
  4. Python爬虫从入门到放弃(十二)之 Scrapy框架的架构和原理
  5. xftp Initialize Flexnet Service failed / Error code: 50003
  6. canvas学习笔记(下篇) -- canvas入门教程--保存状态/变形/旋转/缩放/矩阵变换/综合案例(星空/时钟/小球)...
  7. 用JS实现一个定时间段的跳转
  8. 利用winston和morgan记录express日志信息
  9. Lync与Exchange 2013 UM集成配置
  10. python 简易HTTP服务器搭建