Web开发安全 之 信息加密
🎉欢迎大家观看AUGENSTERN_dc的文章(o゜▽゜)o☆✨✨
🎉感谢各位读者在百忙之中抽出时间来垂阅我的文章,我会尽我所能向的大家分享我的知识和经验📖
🎉希望我们在一篇篇的文章中能够共同进步!!!
🌈个人主页:AUGENSTERN_dc
🔥个人专栏:C语言 | Java | 数据结构 | 算法 | MySQL | RabbitMQ | Redis | 计算机网络
⭐个人格言:
一重山有一重山的错落,我有我的平仄
一笔锋有一笔锋的着墨,我有我的舍得
目前, 各种软件的登录方式依然包括了账号密码登录这一选项, 但是你有没有想过, 在数据库中, 我们的账号密码是如何存储的呢?
现在, 假设有一个小菜鸟, 叫小邓, 正在开发一个系统, 这个系统中的登录注册支持账号密码登录注册, 此时, 作为后端开发程序员的我, 正在认真思考, "账号密码登录注册嘛, 很简单啊, 用户输入自己的账号密码, 前端将账号密码传给我后端, 我直接就存到数据库中就好了嘛, so easy!"
1. 明文存储
很快小邓便开发完了登录注册功能, 随后便自信的提交了代码, 摇头晃脑合上了笔记本, 去吃自己点的拼好饭了.......
代码提交后三天.....
大牛怒气冲冲的走到小邓的桌前, "不是哥们, 登录注册这块是你写的吧? 你怎么能用明文存储用户的密码呢", 小邓一脸疑惑的望向大牛, "怎么啦, 大牛, 你这么生气干嘛, 我当时测试过了啊, 这一块没有bug, 你消消气, 慢慢说"
大牛稍微冷静了一些, 缓缓开口到, "用户密码用明文存储是十分危险, 且不合规的, 你怎么能存储明文呢?"
"啊? 我不知道啊, 我寻思这么存没什么问题呢"
大牛直接一个爆栗, 小邓捂住自己的脑袋, 倒吸了一口凉气.
"看你是一个刚入职的小菜鸟, 就不和你计较了, 接下来我教你, 你好好听着"
"咱么企业在开发项目的时候, 是有义务保护用户的隐私的, 你想啊, 如果你作为一个用户, 你的账号密码就这么赤裸裸的存储在数据库中, 企业的开发人员只要进入了数据库中, 就能随意窥探我们的账号密码, 这件事情被身为用户的你知道了, 你还会继续使用这个应用吗"
"那肯定不会啊, 我的账号密码可是我的秘密, 怎么能随随便便就让别人知道呢"
"那就对了, 所以我们开发人员在存储用户的密码时, 是不能使用明文的, 除此之外, 还有很重要的一个原因, 就是防止黑客窃取数据库信息, 你想, 如果某一天, 一个很厉害的黑客成功破解了我们的数据库, 读取到了我们数据库中的内容, 此时我们用户的账号密码都是明文, 那么黑客岂不是想登录谁的账号就登录谁的账号, 这对于整个项目来说, 都是灾难性的, 此时, 如果我们存储的是加密后的密码, 那么就算黑客破解了我们的数据库, 拿到了我们的密码, 那也只是加密后的一串字符出而已, 想要破解出真实的密码, 还需要很高的时间和人力成本的"
"原来如此, 我懂了, 那我要如何对密码进行加密呢?"
大牛笑了笑, "这个你可以自己先去了解一下, 相信通过你自己的努力找到答案, 比从我这里听来的答案, 会更加令人深刻............."
2. hash加密
不一会, 小邓就阅读完了网上的文章, 并写了几个简单的demo
"大牛, 我搞懂了, 为了保护用户的隐私, 以及考虑到系统的安全性的设计, 我们可以使用hash算法对我们的密码进行加密, 这样数据库中存储的密码就是加密过后的密码了, 在用户登录的时候, 我们可以将用户输入的密码以同样的方式进行加密, 然后将加密后的输入密码和数据库中的加密密码进行比较, 就可以知道用户输入的密码是否正确了"
"嗯, 很不错嘛, 学的挺快, 那你简单说说hash算法呗"
"hash算法嘛, 通俗的来说, 就是将某一个字符串, 进行一系列很复杂的数学运算, 得到了另外一个字符串, 经过hash算法得到的字符串有几个很大的特点,
第一, 这个字符串是固定长度的, 不同的hash算法, 生成的字符串长度是不同的, 这个得看他们的具体实现, 但是同一种的hash算法, 对不同的字符串进行加密后, 生成的加密后的字符串长度是相同的
第二, 这个加密过程是不可逆的, 也就是说, 从原字符串加密得到加密字符串这个过程是很容易的, 但是想从加密字符串解密成原字符串这个过程几乎是不可能的
第三, 加密算法具有雪崩效应, 一个字符串经过hash算法得到了一串加密字符串, 若将原字符串中的某一个字符进行改变, 得到的加密字符串和原来的加密字符串是几乎完全不同的
第四, 同一个字符串经过同一种hash算法加密后, 得到的加密字符串是相同的
其实还有其他的特点, 但这些是最重要的....."
"嗯, 你说的很对, 但是小邓, 你有没有想过, 其实你这么设计还是会有安全隐患呢?"
"啊? 都使用这么强大的hash算法了, 居然还有安全隐患, 果然人外有人, 天外有天啊!"
"是的, 应该说是, 道高一尺,魔高一丈, 例如你说的hash算法的第四个特点, 同一个字符串, 经过同一种hash算法加密后, 得到的加密字符串是相同的, 这里其实就有安全隐患, 此时, 我们的黑客小黑又登场了, 某一天小黑成功黑掉了某一家公司的数据库, 他将黑到的用户账号密码拿出来, 进行了一些简单的处理, 发现, 居然有某一些用户的密码的密文, 在数据库中是相同, 小黑大致推断出, 这家公司的密码应该只是简单的进行了一次hash加密处理(推断理由, 如hash算法的第四特点: 同一个字符串经过同一种hash算法加密后, 得到的加密字符串是相同的), 此时的小黑一脸坏笑的拿出了早就准备好的彩虹表, 那什么是彩虹表呢, 彩虹表其实就是一种用于破解哈希函数的预先计算的表, 可以简单理解为Java中的一个Map, 他的key是原始密码, value是加密后的密码, 黑客们可以预先往key中存放很多的常用密码组合, 虽然hash的过程是不可逆的, 但是我们可以提前用预先准备好的可能密码, 通过hash算法得到可能的加密密码, 那么这个彩虹表其实就是一个关于, 大量常用密码的原始密码和加密密码的映射表, 通过这张表, 小黑很快的就将大部分用户的原始密码给比较了出来, 从而破解了这家公司的数据库"
"不会吧, 原来hash算法并不是无敌的"
"是的, 但是我们还是有其他的方法应对黑客们的小阴招~~"
"那是啥呢, 大牛你快和我讲讲, 别卖关子啦!"
"哈哈, 好的, 那你可听好了"
"洗耳恭听......"
3. hash + salt 算法
"实际上啊, 为什么hash算法不安全, 主要是因为, hash算法的固定性, 同一个字符串, 加密后得到的字符串还是相同的, 那么黑客们就可以很轻松的利用这一点, 来破解hash算法, 只需要提前准保好原始密码和加密密码的对应关系就好了, 那么此时我们就可以采用hash值 + 盐值的方法, 来提高安全性"
"颜值? 是我想的那个颜值吗"
"别贫嘴, 是你平时吃的那个盐", 大牛笑着弹了小邓一下
"哦哦, 知道了, 没听说过嘛"
"所谓的hash + salt 算法, 简单来说, 就是在hash算法的基础上, 加入了盐值, 这里我举一个简单的例子, 例如, 现在我的密码是123456, 我的盐值是abcdefg, 我们可以将密码和盐值进行一个拼接, 得到123456abcdefg, 然后我们将拼接后的密码进行hash, 就得到了我们最终加密的密码, 然后将我们的盐值和加密后的密码存储到数据库中即可"
"那这样也不安全啊, 黑客依然可以通过彩虹表得到加密前的密码, 然后从加密前的密码中去掉盐值不久可以得到初始密码了吗?"
"哈哈, 看来你掉入了一个误区, 彩虹表不是万能的, 他也是有局限性的, 彩虹表是常用密码的一个, 从原始密码 -> hash值的一个映射关系表, 我们每一个用户的盐值是随机的, 同时盐值的拼接有很多种, 这样就极大的增加了初始密码的复杂性, 这样我们的初始密码+盐的字符串, 就很难出现在彩虹表中, 同时彩虹表只是针对某一个特定的hash算法的表, hash算法有很多种, 这样想通过彩虹表进行破解是很困难的, 同时黑客获取到盐值也是没有任何意义的, 首先, 密码和盐值的拼接方式有很多种, 可以, 其次, 我们不一定要将盐值与密码进行拼接, 也可以将盐值进行hash后, 再与密码进行拼接, 这样, 就算黑客获得了拼接后的密码, 但是不知道拼接规则, 不知道用来拼接的字符串是什么, 也就对我们的初始密码无可奈何"
"原来如此" 小菜恍然大悟, "看来我的学习之路还有很长啊, 我懂了, 大牛, 谢谢你! ovo"
"哈哈, 不客气, 希望你再接再厉!"