🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 普通方案 ``` //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. 计算速度快。随着技术进步,一秒钟能够完成数十亿次单向哈希计算。 单向哈希有两个特性: 1. 同一个密码进行单向哈希,得到的总是唯一确定的摘要。 2. 计算速度快。随着技术进步,一秒钟能够完成数十亿次单向哈希计算。 结合上面两个特点,考虑到多数人所使用的密码为常见的组合,攻击者可以将所有密码的常见组合进行单向哈希,得到一个摘要组合, 然后与数据库中的摘要进行比对即可获得对应的密码。这个摘要组合也被称为`rainbow table` ## 进阶方案-加盐 ``` //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)) ``` ## 专家方案 上面的进阶方案在几年前也许是足够安全的方案,因为攻击者没有足够的资源建立这么多的`rainbow table`。 但是,时至今日,因为并行计算能力的提升,这种攻击已经完全可行 这里推荐`scrypt`方案,scrypt是由著名的FreeBSD黑客Colin Percival为他的备份服务Tarsnap开发的。 目前Go语言里面支持的库 https://github.com/golang/crypto/tree/master/scrypt ``` // DO NOT use this salt value; generate your own random salt. 8 bytes is // a good length. salt := []byte{0xc8, 0x28, 0xf2, 0x58, 0xa7, 0x6a, 0xad, 0x7b} dk,err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32) if err != nil { panic(err) } fmt.Printf("%+v\n", base64.StdEncoding.EncodeToString(dk)) ```