用户注册登录密码保存传输方案

MD5加密属于不可逆的,同一字符,加密后的16进制数是不变的。自从出现彩虹表,对于公司内部员工来说,可以反查数据,获取不可能的权限,所以出现了salt算法。

一般采用:md5注册登录双重加盐密码保护。

一、方案一:加盐账号

md5加盐目的

1、为了防止底层人员和外部入侵能查看到数据库的用户密码,需要对密码加盐处理,使得用户的密码泄露时不能通过彩虹表等手段容易破解得到明文。

2、在用户登录时,传输密码再次加盐,使得用户入侵者就是拿到前端已经加盐的哈希值也不能与后台数据库的哈希值相对应。

注册时

//num:用户账号    pass:用户密码明文(其中num认为是盐slot)

let pwd = md5(num+md5(pass));

登录时

登录时密码流程:

1、密码先以注册时的形式(账号为盐)加盐,得到的结果就是与数据库一样的加密值。

2、将以上的加密值再加入时间戳为参数(秒/10),加密以上的加密值,传输到后台。

3、PHP重复第二步骤,将该用户的数据库密码值以第二步加密,然后比较前台请求的加密数据是否与后台的相等。

//js前端登录密码加密:
var timestamp =parseInt(Date.parse(new Date())/10000);
          let pw = md5(num+md5(pass));
          let pwd = md5(pw+timestamp);

//php后台密码处理:
     $time = intval(time()/10);
      $pw =$userInfo['u_pwd'].$time;
       $pwd = md5($pw);

为了防止网络延迟导致time不一致(加盐不一致),timestamp作为调用参数传递到后台。

ps:数据库中保存的是明文密码的md5加盐账号后md5值,即md5(num+md5(pass))

二、方案二:传输串包含盐

一般使用的加盐:md5(Password+UserName),即将用户名和密码字符串相加再MD5,这样的MD5摘要基本上不可反查。

但有时候用户名可能会发生变化,发生变化后密码即不可用了(验证密码实际上就是再次计算摘要的过程)。

设计一个非常简单的加盐算法:每次保存密码到数据库时,都生成一个随机16位数字,将这16位数字和密码相加再求MD5摘要,然后在摘要中再将这16位数字按规则掺入形成一个48位的字符串。在验证密码时再从48位字符串中按规则提取16位数字,和用户输入的密码相加再MD5。按照这种方法形成的结果肯定是不可直接反查的,且同一个密码每次保存时形成的摘要也都是不同的。

ps:数据库中保存的可以为明文密码的md5值,注册时直接上报后台密码的md5值可行(只有注册时一次)。

三、方案三:GoLang golang.org/x/crypto/bcrypt

安全存储用户密码的原则是:如果网站数据泄露了,密码也不能被还原。

以前常用简单的方式是通过md5多层加密及加盐。比如:md5( md5( password + '用户注册的时间戳' )[8:20] )

这种可以在安全度不够高的情况下使用,下面介绍一种较为安全的加密方式,使用GoLang golang.org/x/crypto/bcrypt 模块。

golang.org/x/crypto模块官方文档:https://godoc.org/golang.org/x/crypto/bcrypt

Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing algorithm. bcrypt算法对于同一个密码,每次生成的hash不一样。
package main

import (
    "fmt"
    "golang.org/x/crypto/bcrypt"
)

func main() {

    passwordOK := "admin"
    passwordERR := "adminxx"

    hash, err := bcrypt.GenerateFromPassword([]byte(passwordOK), bcrypt.DefaultCost)
    if err != nil {
        fmt.Println(err)
    }
    //fmt.Println(hash)

    encodePW := string(hash)  // 保存在数据库的密码,虽然每次生成都不同,只需保存一份即可
    fmt.Println(encodePW)

    // 正确密码验证
    err = bcrypt.CompareHashAndPassword([]byte(encodePW), []byte(passwordOK))
    if err != nil {
        fmt.Println("pw wrong")
    } else {
        fmt.Println("pw ok")
    }

    // 错误密码验证
    err = bcrypt.CompareHashAndPassword([]byte(encodePW), []byte(passwordERR))
    if err != nil {
        fmt.Println("pw wrong")
    } else {
        fmt.Println("pw ok")
    }
}

 

参考:

1. md5注册登录双重加盐密码保护

2. MD5加密+加盐

3. 消息摘要算法HMAC

posted @ 2016-05-16 21:38  yuxi_o  阅读(961)  评论(0编辑  收藏  举报