V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kimwang
V2EX  ›  PHP

密码加密与登录验证的原理是怎样的?

  •  1
     
  •   kimwang · 2016-12-30 14:57:11 +08:00 · 12769 次点击
    这是一个创建于 2886 天前的主题,其中的信息可能已经有所发展或是发生改变。
    新人问题,大家请别笑,不是 ITer ,想撸个轻论坛,一切从概念学起。

    我了解了一下,常见加密方式可能有: escape 、 md5 、 sha 、 base64
    escape 和 base64 好像可逆?

    那么我应该采用哪种方式为密码加密?
    用户登录时验证,是对输入的密码从新加密一次,然后对比数据库已加密的字符是否一致来判断是否放行吗?

    麻烦一下各位,给个思路,然后我又继续找资料学习,感谢。
    54 条回复    2017-01-11 13:26:46 +08:00
    qiayue
        1
    qiayue  
       2016-12-30 14:58:19 +08:00   ❤️ 1
    关键字:加盐
    kimwang
        2
    kimwang  
    OP
       2016-12-30 15:04:48 +08:00
    @qiayue 一般情况下,有没有必要混合加密?
    jimxu16
        3
    jimxu16  
       2016-12-30 15:08:22 +08:00   ❤️ 1
    md5 是不可逆的
    "用户登录时验证,是对输入的密码从新 md5 加密一次,然后对比数据库已 md5 加密的字符是否一致来判断"是可行的

    还可以将用户的登录状态存入到 session 中
    jessynt
        4
    jessynt  
       2016-12-30 15:15:19 +08:00   ❤️ 5
    看了下, LZ 发在了 PHP 节点,那就用 `password_hash` 和 `password_verify ` 吧
    shiji
        5
    shiji  
       2016-12-30 15:18:23 +08:00 via Android   ❤️ 3
    escape 是啥?从没听说过
    md5 sha 是散列函数,不是加密。
    base64 是编码,就像把汉字转换成电报代码,根本不能加密。

    标准做法:网站强制 ssl ,用户名密码原样提交至服务器。服务端使用 bcrypt 生成散列指纹,存入数据库。

    还有个比较接近中国特色的,打死不用 ssl ,服务端返回 RSA 公钥,客户端用 cryptoJS 处理密码加密提交,服务器那边再来解密。缺点是完全不可防御中间人攻击。还有直接用 AES 加密的,密钥就藏在代码里。 189 网上营业厅好像就是这么干的
    xavierskip
        6
    xavierskip  
       2016-12-30 15:18:42 +08:00   ❤️ 1
    1.通过哈希算法存储用户口令。哈希算法不可逆。

    2.因为用户会在各个站点使用同样的口令,防止别的地方泄露的密码被暴力破解后影响到你的站点。给每个用户的口令加上一段随机生成的字符串凑在一起通过哈希算法来存储密码。保存好密码和这段随机生成的字符串,这段字符俗称『盐』。
    shiji
        7
    shiji  
       2016-12-30 15:21:31 +08:00 via Android   ❤️ 2
    如果用的是 PHP , PHP 不是古董版本,就按照 4 楼提到的那两个函数操作即可。非常符合行业标准。最靠谱
    kimwang
        8
    kimwang  
    OP
       2016-12-30 15:22:49 +08:00
    @jessynt 没错,因为我准备用 PHP+MYSQL ,其它需要容器、 APP 什么的语言对我来说太难。

    想知道现在程序员通常会用什么方案处理?
    kimwang
        9
    kimwang  
    OP
       2016-12-30 15:27:57 +08:00
    @shiji 不好意思,我自己也比较乱,概念名词不一定说得准,有时会影响理解。

    http://www.w3school.com.cn/jsref/jsref_escape.asp
    我想说的是 JavaScript escape() 函数
    kimwang
        10
    kimwang  
    OP
       2016-12-30 15:31:41 +08:00
    @shiji 明白,谢谢。
    kimwang
        11
    kimwang  
    OP
       2016-12-30 15:32:15 +08:00
    @shiji 考虑尽量用 PHP7 ,图速度快。
    kimwang
        12
    kimwang  
    OP
       2016-12-30 15:34:39 +08:00
    @xavierskip 了解,谢谢。
    Eugene1024
        13
    Eugene1024  
       2016-12-30 15:37:20 +08:00   ❤️ 1
    登录时验证是验证输入的字符加密后和数据库中的加密字符是否相匹配,一般的加密算法如 MD5 ,网上都有代码,建议楼主可以先搜索了了解下
    kimwang
        14
    kimwang  
    OP
       2016-12-30 15:41:42 +08:00
    @Eugene1024 找了一个叫“ ph pass ”的类库来了解,据说 YII 和 wordpress 都在用, MD5 不知道破解的事是不是真……
    whx20202
        15
    whx20202  
       2016-12-30 15:52:04 +08:00
    @shiji 真的假的? 189 这么厉害?
    ZSeptember
        16
    ZSeptember  
       2016-12-30 15:56:04 +08:00   ❤️ 1
    一种可行的思路,每次登录都用一个 Token ,服务端在 sesion 中保存 Token
    客户端提交的是 hash(token,hash(hash(pwd),salt) 在数据库中保存的是 hash(hash(pwd),salt)
    在服务端计算 hash ( token,保存的值),然后比较, 不管对错,清除 token 。

    自己不是做安全的,不知道这样还有什么问题。
    一般这样应该差不多了,毕竟 https 要钱。
    wy315700
        17
    wy315700  
       2016-12-30 15:58:41 +08:00
    @ZSeptember
    这是一个 CHAP 协议
    你把 hash(hash(pwd),salt) 当做一个变量,你会发现,其实服务器这样做以后保存的是 明文,

    普通的 CHAP 协议的一个问题吧,必须保存明文密码。
    shiji
        18
    shiji  
       2016-12-30 16:01:14 +08:00
    @whx20202
    先去 http://login.189.cn/login
    会包含这样的 JS : http://login.189.cn/bundles/jquery
    beautify 一下,有如下代码:

    $.fn.aesEncrypt = function(n) {
    var t = CryptoJS.MD5("login.189.cn"),
    i = CryptoJS.enc.Utf8.parse(t),
    r = CryptoJS.enc.Utf8.parse("1234567812345678"),
    u = CryptoJS.AES.encrypt(n, i, {
    iv: r
    });
    return u + ""
    };
    $.fn.aesDecrypt = function(n) {
    var t = CryptoJS.MD5("login.189.cn"),
    i = CryptoJS.enc.Utf8.parse(t),
    r = CryptoJS.enc.Utf8.parse("1234567812345678");
    return CryptoJS.AES.decrypt(n, i, {
    iv: r
    }).toString(CryptoJS.enc.Utf8)
    };
    kimwang
        19
    kimwang  
    OP
       2016-12-30 16:11:00 +08:00
    https://www.zhihu.com/question/20299384

    我找了一篇知乎的文章,各位有兴趣可以看看。
    现在有点困惑“随机盐值”,如果盐值随机,那么验证的时候怎么跟生成的时候一样?
    lisijing1221
        20
    lisijing1221  
       2016-12-30 16:22:10 +08:00   ❤️ 1
    @kimwang 可以把 salt 存起来, salt 作用主要就是防止彩虹表
    crab
        21
    crab  
       2016-12-30 16:23:21 +08:00   ❤️ 1
    好多都是 sha1.返回公钥或者内置固定公钥。
    lisijing1221
        22
    lisijing1221  
       2016-12-30 16:26:41 +08:00   ❤️ 1
    @kimwang 就是比如 你的密码进行 md5 散列之后,会得到一个固定的值,虽然这个值不能逆向,但是只要你有足够的数据,就能直接索引了,加盐就是稍稍阻止一下这个过程
    kimwang
        23
    kimwang  
    OP
       2016-12-30 16:33:50 +08:00
    @crab
    http://blog.coderzh.com/2016/01/10/a-password-security-design-example/
    找了一篇文章,跟你说的思路相同的。
    kimwang
        24
    kimwang  
    OP
       2016-12-30 16:37:41 +08:00
    @lisijing1221 明白,还有个问题,如果盐值随机,那么验证的时候怎么跟生成的时候一样?( 19 楼)
    ZSeptember
        25
    ZSeptember  
       2016-12-30 16:42:06 +08:00
    @wy315700 仔细想想确实是,但是其他的也一样的了。只要被拖库了,密钥都是明文的。
    lisijing1221
        26
    lisijing1221  
       2016-12-30 16:49:29 +08:00
    @kimwang 盐值 的话 是可以存在同一个库里面,当然也可以分库, MD5 的彩虹表很少有计算非常长的字符串的,因为穷举非常长的字符串特别耗费时间,盐值足够随机足够长就可以了,其实存哪里不是很有必要考虑
    hahaDashen
        27
    hahaDashen  
       2016-12-30 16:52:34 +08:00
    各位大佬方法都好多 我一般写小程序就是先验证字符串是否有特殊字符 有就返回错误 然后没有的话就 md5 后存数据库 登录就把用户输入的密码 md5 后和数据库的对比 通过后存个 SESSION 存个 Cookies 两边一边一个随机密钥 判断的时候首先判断服务器端和客户端的 Cookies 是否存在 如果不存在肯定是没有登录 存在的话就验证两面的密钥 一样就代表登录 不一样就清空然后跳转到登录界面 各位大佬轻喷 用习惯这种做法了 有什么不对的还望指出
    tabris17
        28
    tabris17  
       2016-12-30 16:56:09 +08:00   ❤️ 1
    建议先搞清楚编码、散列、加密的区别
    lynnX
        29
    lynnX  
       2016-12-30 16:57:35 +08:00
    "用户登录时验证,是对输入的密码从新加密一次,然后对比数据库已加密的字符是否一致来判断是否放行吗? " 一般来说 就是这样 就是一个密码的生成过程 我现在是这样的处理的 根据用户注册的主键 ID 和密码 按照一定方式混合之后去加密 登录的时候 对密码按照我的加密方式加密之后和数据库对比
    lisijing1221
        30
    lisijing1221  
       2016-12-30 16:59:13 +08:00   ❤️ 1
    @kimwang 彩虹表不会计算特别长的字符串,比如你的密码+盐值是 64 的长度,那么彩虹表的计算就穷举 64 位长的所有字符组合,这就非常恐怖耗时间了,所以盐值足够随机,足够长就 ok 了
    monkeyk
        31
    monkeyk  
       2016-12-30 17:13:03 +08:00
    来, 我给你一套完整方案, 专做移动安全的
    woostundy
        32
    woostundy  
       2016-12-30 17:41:33 +08:00
    escape 和 base64 不是加密,是混淆, md5 和 sha 是哈希,登录密码一般就是比对哈希值。
    t6attack
        33
    t6attack  
       2016-12-30 17:42:32 +08:00
    腾讯、京东,是 RSA 。
    如果你有意留存一份用户密码明文数据,那就 RSA 一下。私钥自己收好。
    xavierskip
        34
    xavierskip  
       2016-12-30 19:51:46 +08:00   ❤️ 1
    再说一遍 MD5 不是加密算法,用户口令也不需要加密。那叫散列、哈希、摘要算法。

    至于保持用户登录状态,一般都是通过 cookie 存储 session token ,一般的 web 框架都会有相应的处理功能。
    sununiq
        35
    sununiq  
       2016-12-30 20:01:08 +08:00
    单向散列,加盐
    kimwang
        36
    kimwang  
    OP
       2016-12-30 22:53:19 +08:00
    @xavierskip 明白,我有些概念名词和功能可能会说错,会抓紧学习。
    J0022ZjV7055oN64
        37
    J0022ZjV7055oN64  
       2016-12-30 23:08:12 +08:00   ❤️ 1
    md5 简单密码的会被暴力破解 建议
    mcfog
        38
    mcfog  
       2016-12-30 23:53:10 +08:00 via Android
    一定自己手动加盐的话建议 hmac
    Ultraman
        39
    Ultraman  
       2016-12-30 23:57:54 +08:00 via Android
    想起来三周前偶然听了一节密码学选修课,,,
    RqPS6rhmP3Nyn3Tm
        40
    RqPS6rhmP3Nyn3Tm  
       2016-12-31 04:44:44 +08:00 via iPhone
    @shiji 看到中国特色笑出声,这么麻烦直接上 SSL 多好……
    公私钥用错地方了喂
    shiji
        41
    shiji  
       2016-12-31 05:54:04 +08:00 via Android
    @BXIA 可不是咋的,如果死活不用,这就就是个凑合着能加密的方法。根本不能防中间人
    kn007
        42
    kn007  
       2016-12-31 10:09:53 +08:00   ❤️ 1
    php 的话通过 4L 挺好的,只要你无需跟前台或其他后端程序交互,完全没必要哈希,哈希我觉得更多为了协同。
    kimwang
        43
    kimwang  
    OP
       2016-12-31 11:01:16 +08:00
    @kn007 可是四楼的 password_hash 不就是创建密码的哈希吗?我的理解,哈希和加盐主要是防止被脱裤后被暴力,而我觉得这个影响极坏,所以比较重视这一块,而我完全没有实操经验,欢迎各位多多分享实战经验和个人看法。
    vugusurk
        44
    vugusurk  
       2016-12-31 15:17:01 +08:00
    @kimwang LZ 没啥实操经验直接用 4L 的不就行了,业界通用方案, PHP 官方推荐,还能坑你不成
    johnj
        45
    johnj  
       2016-12-31 18:18:40 +08:00
    @kimwang salt 可以是生成一段随机字符,然后跟密码一起哈希。 salt 可以保存在数据库中,也可以跟哈希值以一定规则编码在一起,就不用单独存 salt 了,用的时候再反向把 salt 从混合编码中提取出来。
    mingyun
        46
    mingyun  
       2017-01-01 19:28:22 +08:00
    @kimwang
    JamesRuan
        47
    JamesRuan  
       2017-01-01 23:18:18 +08:00   ❤️ 1
    去看看 Key derivation function
    kimwang
        48
    kimwang  
    OP
       2017-01-02 12:58:55 +08:00
    @JamesRuan 谢谢,这个中文文献比较少。
    JamesRuan
        49
    JamesRuan  
       2017-01-02 20:26:37 +08:00   ❤️ 1
    @kimwang
    我写了一批文章,专门讲讲这个事:

    https://zhuanlan.zhihu.com/p/24678857
    kimwang
        50
    kimwang  
    OP
       2017-01-03 19:24:36 +08:00
    @JamesRuan 已拜读,感谢如此有心之人。
    学习 PHP ,路漫漫其修远兮~
    kimwang
        51
    kimwang  
    OP
       2017-01-03 19:46:22 +08:00
    @lisijing1221 那些所谓的“慢函数”如何理解?为什么执行得慢~
    JamesRuan
        52
    JamesRuan  
       2017-01-03 21:17:10 +08:00   ❤️ 1
    @kimwang 本来就想写,很早就埋了坑,无非这次是机缘巧合,你这个问题给了我动力罢了
    garrydzeng
        53
    garrydzeng  
       2017-01-10 23:25:11 +08:00   ❤️ 1
    @kimwang

    1. 盐是需要存下来的,比如 bcrypt 前 22 个字符就是盐,参见 https://en.wikipedia.org/wiki/Bcrypt 的示例说明
    2. MD5 破解是用彩虹表
    3. 慢函数可以扛暴力破解,做到破解之后信息已经没有用了

    如有错误欢迎纠正
    password_hash 的 $algo 参数设为 PASSWORD_BCRYPT 即是 bcrypt
    我平常也是用 bcrypt 算法
    kimwang
        54
    kimwang  
    OP
       2017-01-11 13:26:46 +08:00
    @garrydzeng 谢谢介绍,我继续去了解。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4028 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 05:13 · PVG 13:13 · LAX 21:13 · JFK 00:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.