后端面试之系统设计 - 用户密码如何储存在DB里

news2024/11/24 0:54:40

原文地址:码农在新加坡的个人博客

背景

现在很多网站都因为爆库导致密码泄漏,要设计怎么样的密码储存机制,才能保证最大限度的不被盗取,即使数据泄漏,黑客也无法在短时间内获取对应的密码来登录用户的账号,而造成损失。

这篇博客就来讲解密码储存的过程。

明文储存密码

usernamepassword
aaa123456
bbbqwerty
cccpassword
ddd111111

假设我们有一张用户表,储存usernamepassword,密码我们是明文储存的。为什么这么不安全呢?

  1. 如果遭遇数据泄漏事件,明文密码将用户隐私完全暴露,任何人都可以登录暴露密码的账号,随意更改。
  2. 密码容易被网站的内部人员得知并获取;也就是内部员工也可以轻易访问用户的明文密码。可能会做一些违法的事情,所以网站基本不会明文储存密码。

当然也有例外,看下这个条新闻:

Hundreds of millions of Facebook users had their account passwords stored in plain text and searchable by thousands of Facebook employees — in some cases going back to 2012, KrebsOnSecurity has learned. Facebook says an ongoing investigation has so far found no indication that employees have abused access to this data.

Facebook 明文存储用户密码,大约有2亿~6亿的用户受到影响,预计超过2万名Facebook员工可检索这些村文本密码 Facebook Stored Hundreds of Millions of User Passwords in Plain Text for Years

所以说,明文储存密码是很不安全的,正常来说现在没有人会这么用。(以前经常还会爆出来)

用对称加密或者非对称加密函数加密储存密码

我想大部分人都了解对称加密和非对称加密,那么用这两种加密算法可不可行呢?
在这里插入图片描述

对称加密

在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。

密钥需要安全储存,否则就有严重的泄漏风险。

非对称加密

非对称加密是一份明文,经过公钥加密成密文,然后使用私钥解密成明文。

公钥和私钥不同,公钥可以公开,这样外部(客户端)可以使用公钥加密成密文,私钥必须保密,这样内部(服务器)才能使用私钥解密成明文。

用这种方式加密密码,能够降低黑客获取明文密码的概率。但密钥一旦泄露,用户的明文密码也就泄露了,不是一个好方法。

而且因为密钥在公司内部,不免有内部员工有不良动机导致账号信息被盗。

所以密码的储存一般不使用对称加密或者非对称加密。

那我们怎么做呢?

用MD5等Hash函数进行密码加密

首先解释一下:Hash 算法是一种消息摘要算法,不是一种加密算法,但由于其单向运算,具有一定的不可逆性,成为加密算法中的一个构成部分。所以为了通俗易懂,我们在本文中可以把MD5等Hash算法理解为加密算法。

MD5是一种Hash算法,也是最常用的一种消息摘要和数字签名算法,常常用于保存密码以及生成数字签名
在这里插入图片描述

MD5 算法具有以下特点:

  • 压缩性:任意长度的数据,算出的 MD5 值长度都是固定的(128 bit)。
  • 易计算:从原数据计算出 MD5 值很容易。
  • 抗修改:对原数据进行任何改动,哪怕只修改 1 个字节,所得到的 MD5 值都有很大区别。
  • 抗碰撞:已知原数据和其 MD5 值,想找到一个具有相同 MD5 值的数据(即伪造数据)是非常困难的(极小碰撞概率)。

实际上很多网站都是使用MD5SHA-1SHA-256等Hash算法及其变种来进行加密的。

MD5加密的优势:

  • 网站被攻破后,无法直接看到明文密码,相对安全性更高;
  • 即使是网站的内部人员也无法通过数据库里面的密文得到明文;

但是MD5就安全了吗?

不是的!

虽然无法可以直接获取明文,但可以通过穷举,列表查询方式获取明文,md5的查询库是非常丰富的。

下面我列出三种常用的解密方案。

  • 穷举法
  • 字典法攻击
  • 彩虹表攻击

也有不少网站可以直接进行 MD5 解密。就是用上述三种方法中之一。

在这里插入图片描述

MD5解密链接

穷举法

顾名思义就是穷举所有的明文生成MD5码,然后用MD5码跟泄漏的MD5对比。

在这里插入图片描述

比如我上面列出的这个123456的MD5的值E10ADC3949BA59ABBE56E057F20F883E,虽然我没办法从MD5推出它是的原文是123456,但是我可以使用很多方法来得到它的原文123456

第一步就是穷举法

比如我们穷举6位数数字。

  1. 计算000000的MD5值670B14728AD9902AECBA32E22FA4F6BD,不匹配,下一个。
  2. 计算000001的MD5值。
  3. 计算123456的MD值E10ADC3949BA59ABBE56E057F20F883E,匹配,原文为MD5。

由于现代计算机硬件的发展,CPU每秒钟能进行上百亿次的计算,所以在给定范围内的密码使用穷举法是可行的。

但是如果密码可以使用字母+数字+特殊符号,那么8位数的密码就有数百万亿个组合,16位呢?这个计算更加量庞大。

这种只适合在明文很小的情况下适用。比如6位数字密码

字典攻击法

固定长度的密码是有限集,所以生成的MD5值也是有限集。如果你的密码长度很小。那么完全可以生成一个字典表来做一个明文和密文的映射。拿到这个密文之后匹配明文就可以得到你的密码。

在这里插入图片描述

字典表就是提前构建一个 明文 ⇨ 密文 对应关系的一个大型数据库,破解时通过密文直接反查明文。但存储一个这样的数据库,空间成本是惊人的。

密码长度越大这个有限集越大,需要生成的字典表就越大,匹配明文的难度也就越大。所以记得设置密码的时候设置的长一点,同时多用点特殊字符。这样破解的难度会变大。你知道为什么了吧。

字典攻击法很简单,但是它的限制就是:面对储了大量密码的系统时会非常乏力(储存用于逆向查找的所有选项以及搜索大型数据库十分困难)。

彩虹表攻击

在这里插入图片描述

虽然在一定长度内的密码是有限集,但是长度增加的时候那个集合所占用的空间也是不可估量的。

彩虹表是在字典法的基础上改进,以时间换空间。是现在破解哈希函数常用的办法。

彩虹表是用于加密散列函数逆运算的预先计算好的表,常用于破解加密过的密码散列。彩虹表常常用于破解长度固定且包含的字符范围固定的密码(如信用卡、数字等)。这是以空间换时间的典型实践,比暴力破解(Brute-force attack)用的时间少,空间更多;但与储存密码空间中的每一个密码及其对应的哈希值(Hash)实现的查找表相比,其花费的时间更多,空间更少。使用加盐的密钥派生函数可以使这种攻击难以实现。

彩虹表的核心就是

  • H函数,也就是Hash函数,通过明文得到密文。
  • R函数,归约函数,通过密文得到一个指定长度的明文。

核心:时间换空间。

有兴趣的小伙伴可以看彩虹表的Wikipedia。
wikipedia

黑客可以使用彩虹表将用户密码复原出,网站常用的密码一般也就 6~16 位,这个取值空间还是很好破解的。

彩虹表(Rainbow Table)是一种破解哈希算法的技术,它的性能非常让人震惊,在一台普通PC上辅以NVidia CUDA技术,对于NTLM算法可以达到最高每秒103,820,000,000次明文尝试(超过一千亿次),对于广泛使用的MD5也接近一千亿次。更神奇的是,彩虹表技术并非针对某种哈希算法的漏洞进行***,而是类似暴力破解,对于任何哈希算法都有效。

MD5加盐(Salt)进行密码储存

与普通的MD5不同,把MD5(password+salt)进行MD5得到的密文储存在系统中,密文和Salt分别储存。

usernamepasswordsalt
aaa90005CB0DAE7C8BE36B3AD50FA638928abcdefghij
bbb471AE89F04C9B18B276FD7571D5402FAqweryuiop

根据安全级别,salt可以设置为固定值或者每一个用户不同的值,这个值一般为用户数据行的某一个固定值且对用户不可见的值,千万不要用username作为salt。这种如果有人知道了加salt的算法,那就跟普通的MD5没啥区别了。

在这里插入图片描述

每个salt都是独一无二的,随机生成的字符串,在哈希过程中添加到每个密码中。由于salt对于每个用户而言都是唯一的,因此,即使两个用户的密码是一样的123456,因为每个用户都有自己独立的 salt,所以最终储存在DB里面的password也是不一样的。

预防彩虹表攻击

salt还可以防止攻击者使用预先计算的彩虹表。最后,使用salt意味着无法在不破解哈希的情况下确定两个用户是否具有相同的密码,因为即使密码相同,不同的salt也会导致不同的哈希结果。

当然随着计算机硬件的飞速发展,现代CPU的运算速度越来越快,这种破解只会越来越容易。

密码验证流程

在这里插入图片描述

用户使用电脑输入账号密码(username+pwd),发送HTTPS网络请求,服务器收到请求后根据username查询数据库,匹配到一条数据,然后使用pwd和数据库里的独有的salt 进行MD5运算,得到的结果和数据库里面的password进行对比,匹配则密码正确,返回登录成功。

不匹配则密码错误,返回登录失败。

这个流程还有一个问题,虽然我们数据库里面储存的数据已经是MD5进行Hash之后的字符串,但是接收到的HTTPS的网络请求的pwd还是明文的,这样服务端的人员或者黑客也一样有机会能截取到密码明文,同样有安全隐患。

一般在发送网络请求之前,客户端/浏览器也需要对密码进行加密,一般来说客户端会用类似的MD5哈希算法。
可以使用多层Hash。

pwd = sha256(md5("123456")) //对密码进行md5然后sha256

这样通过网络发送的pwd就是加密之后的字符串。就有更强的安全性。

MD5+salt其实是很多互联网公司的比较普遍的密码加密算法了。基本上目前大部分互联网公司都是使用的这种加密,可以抵挡大部分的数据泄漏。

四、Bcrypt让你的密码更安全

即使是加了盐,密码仍有可能被暴力破解。因此,我们可以采取更「慢一点」的算法,让黑客破解密码付出更大的代价,甚至迫使他们放弃。提升密码存储安全的利器Bcrypt,应运而生。

bcrypt 是基于 eksblowfish 算法设计的加密哈希函数,它最大的特点是:可以动态调整工作因子(迭代次数)来调整计算速度,因此就算以后计算机能力不断增加,它仍然可以抵抗暴力攻击。

相对于MD5,Bcrypt加密算法的特点:

  1. 相同明文通过Bcrypt生成的密文每次都是不一样的,MD5则相同。这样就无法通过直接比对密文来反推明文。
  2. Bcrypt是种慢哈希算法,执行时间较长。有文章指出,针对某一字符串,Bcrypt执行一次加密约0.3秒,MD5加密约1微秒(百万分之一秒)。使得暴力破解Bcrypt的时间成本很高。https://www.jianshu.com/p/2b131bfc2f10
  3. Bcrypt加密长度60位,MD5是32位,提高穷举难度。

如图所示:

在这里插入图片描述

我们明文字符串123456经过10轮加密之后的密文如下:
其中:

  • 2a是Brcypt加密的版本号,有 2,2a,2b,2y等,有些因为安全原因已经废弃不用了。
  • Rounds是一个可选的随机数,默认为12,取值[4,31],同一个字符串由于Rounds不同得到的密文也会不同。
  • Salt 加盐字符串,如果未指定,则会自动生成一个加盐字符。
  • Hash生成的Hash值

那如果黑客使用彩虹表进行hash碰撞呢?

BCrypt算法最大的特点是我们可以通过参数设置重复计算的次数,重复计算的次数越多耗时越长。如果计算一个哈希值需要耗时1秒甚至更多,那么黑客们采用暴利法破解密码将几乎不再可能。破解一个6位纯数字密码需要耗时11.5天,更不要说高安全级别的密码了。

ScryptPBKDF2 也是类似的,有兴趣的小伙伴可以自己学习下。

结论

  1. 大部分公司使用MD5+Salt的方式进行密码加密,Salt要每个用户都不一样,可以增大彩虹表攻击的难度。
  2. 如果有更高的密码安全性要求,可以使用Bcrypt等算法进行密码加密,破解难度更高。

所以你知道为什么你忘记密码之后只能重置密码吗,因为网站也不知道你的密码原文,他们只知道你的密码经过一系列哈希之后的密文,密码校验的时候也是通过同样的哈希函数进行校验是否正确。所以当用户忘记密码的时候,提供的是重置密码而非找回密码。

<全文完>

本文已发布视频版本 bilibili.com,如果你觉得我的博客对你有所帮助,麻烦给个一键三连吧,谢谢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/115020.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeanCloud: 数据存储实现小程序云开发

1. LeanCloud 官网传送 2. LeanCloud选择原因 微信小程序的开发包括上线需要一个备案过的域名&#xff0c;而域名备案又需要一个服务器&#xff08;仅腾讯云而言&#xff09;。而微信云开发作为个人开发者受限于费用也不做考虑。 此时不考虑复杂的业务逻辑数据库读取是后端服…

A股、港股上市公司碳排放、碳强度和碳披露数据(2018-2021年)

随着中国碳强度减排任务的不断加重&#xff0c;当前政策的就业红利将不复存在&#xff0c;同时政策机制蕴含的资源错配、各行业边际减排成本不相等的问题则愈加严重&#xff0c;实施碳交易减排政策的时机逐渐成熟&#xff0c;政府应如何根据二氧化碳排放量、碳强度和碳披露等数…

带你走进Java字符串的小世界

目录 一. String 1. 什么是String 2. String常用构造器 3. 字符串的判断 4. 字符串的获取 5. 字符串的转换 6. 字符串比较和替换 7. 字符串的切割 二. StringBuffer与StringBuilder 2.1 关于StringBuffer 2.1.1 定义 2.1.2 构造方法 2.2 关于StringBuffer 三. StringJoiner的使…

分布式缓存的四大痛点

目前开发中经常用到的缓存&#xff0c;是我们必不可缺的&#xff0c;他大大的提高了我们整个项目的响应速度和并发量。但是带来好处的同时&#xff0c;也给我们带了了新的问题&#xff1a;缓存穿透、缓存击穿、缓存雪崩以及缓存一致性这么四个问题&#xff0c;也是分布式缓存的…

LeetCode算法之----动态规划

点赞收藏&#xff0c;以防遗忘 本文【程序大视界】已收录&#xff0c;关注免费领取互联网大厂学习资料&#xff0c;添加博主好友进群学习交流&#xff0c;欢迎留言和评论&#xff0c;一起交流共同进步。 目录 【一】前言 【二】打家劫舍 【三】不同路径 【四】最小路径和 …

【数据预处理】基于Kettle的字符串数据清洗、Kettle的字段清洗、Kettle的使用参照表集成数据

文章目录一.前言1.1 实验内容二.实验过程2.1 实验内容一&#xff1a;掌握基于Kettle的字符串数据清洗2.2 实验内容二&#xff1a;掌握基于Kettle的字段清洗2.3 实验内容三&#xff1a;掌握基于Kettle的使用参照表集成数据2.4 实验心得&#xff1a;一.前言 需要本文章的源文件下…

用零知识证明连接多链宇宙

目录 一、前言 二、Bridges和Zero Knowledge Proofs 三、Succinct Verification of Proof of Consensus (Succinct Labs)

【自然语言处理】【ChatGPT系列】ChatGPT的智能来自哪里?

相关博客 【自然语言处理】【ChatGPT系列】ChatGPT的智能来自哪里&#xff1f; 【自然语言处理】【ChatGPT系列】Chain of Thought&#xff1a;从大模型中引导出推理能力 【自然语言处理】【ChatGPT系列】InstructGPT&#xff1a;遵循人类反馈指令来训练语言模型 【自然语言处理…

二叉搜索树与Mysql索引的亲密关系

欢迎关注公众号&#xff1a;【离心计划】&#xff0c;一起逃离技术舒适圈 二叉搜索树 二叉搜索树大家应该多多少少听过&#xff0c;它有一个很重要的特征&#xff0c;就是父节点左子树所有结点的值小于父节点的值&#xff0c;右子树所有结点的值大于父节点的值&#xff0c;这个…

详解vue中vuex的用法

前言 说到 vuex 相信大家都不陌生&#xff0c;vuex 是一个专为 vue.js 应用程序开发的状态管理模式。vuex 背后的基本思想&#xff0c;就是单向数据流。今天我们就来好好聊聊 vuex。 vuex&#xff1f; 用官方的话来说&#xff0c;vuex 是一个专为 vue.js 应用程序开发的状态管…

【Linux】进程间通信之共享内存与信号量初识

目录&#x1f308;前言&#x1f338;1、System V共享内存&#x1f361;1.1、概念&#x1f362;1.2、原理&#x1f33a;2、共享内存相关函数和指令&#x1f361;2.1、shmget函数&#xff08;创建&#xff09;&#x1f362;2.2、shmctl函数&#xff08;控制&#xff09;&#x1f…

使用 DataAnnotations(数据注解)实现模型的通用数据校验

DataAnnotations 实现数据模型的通用校验参数校验的意义常用参数的校验.NET 中内置 DataAnnotations 提供的特性校验关于 DataAnnotations 中的特性介绍基于 DataAnnotations 的通用模型校验封装基于 DataAnnotations 的特性校验助手实现步骤如何使用 DataAnnotations 封装的特…

某农业学校 算法设计与分析-第五次实验-回溯算法

1. 罗密欧与朱丽叶的迷宫问题 问题描述 罗密欧与朱丽叶的迷宫。罗密欧与朱丽叶身处一个mn的迷宫中&#xff0c;如图所示。每一个方格表示迷宫中的一个房间。这mn个房间中有一些房间是封闭的&#xff0c;不允许任何人进入。在迷宫中任何位置均可沿8 个方向进入未封闭的房间。罗…

第二章:关系数据库

一、关系数据库结构及形式化定义 1、【单选题】 下图中&#xff0c;关系D1、D2、D3笛卡尔积的目和基数分别为 正确答案&#xff1a; B 2、【多选题】下图中能够作为候选码的属性组为 正确答案&#xff1a; ABD 3、【多选题】关于关系数据库&#xff0c;说法正确的是 正确答…

二、栈和队列

二、栈和队列 栈——后进先出 应用&#xff1a;数制转换、括号匹配、行编辑程序、迷宫求解、表达式求值、八皇后问题、函数调用、递归调用的实现 队列——先进先出 应用&#xff1a;脱机打印输出 多用户系统用户排队分时循环使用CPU和主存 按用户优先级排队&#xff0c;每…

编译gtest报错‘is_trivially_copy_constructible’ is not a member of ‘std’

编译gtest报错‘is_trivially_copy_constructible’ is not a member of ‘std’一、问题描述二、原因分析三、升级gcc版本四、验证一、问题描述 在一个新的Redhat7.6 linux虚拟机上&#xff0c;将gtest clone下来之后编译&#xff0c;一堆报错&#xff1a; /opt/googletest/…

多线程问题(二)(安全问题)

目录 一、多线程不安全引例 二、线程不安全的原因 1、线程是抢占式执行 2、多线程共享同一变量 3、对变量的操作不是原子性 4、内存可见性 5、指令重排序 三、线程不安全问题的解决方案 1、使用synchronized关键字进行加锁 a、 synchronized修饰普通方法 b、sy…

Maleimide-PEG-Biotin,Biotin-PEG-MAL,生物素PEG马来酰亚胺用于生物分子检测

化学试剂生物素聚乙二醇马来酰亚胺&#xff0c;其英文名为Maleimide-PEG-Biotin&#xff0c;Biotin-PEG-MAL&#xff0c;它所属分类为Biotin PEG Multi-arm PEGs。 该试剂质量控制为95%&#xff0c;试剂的储存条件为&#xff1a; -20℃长期保存&#xff0c;避光&#xff0c;干…

数据结构---图

&#xff08;一&#xff09; 相关知识点 图&#xff08;graph&#xff09;&#xff1a;图是由顶点的有穷非空集合和顶点之间边的集合组成&#xff0c;通常表示为&#xff1a;G(V,E)&#xff0c;其中&#xff0c;G表示一个图&#xff0c;V是图G中的顶点的集合&#xff0c;E是图G…

SpringBoot系列之自动装配原理详解

文章目录前言一、SpringBoot自动配置-Condition-11、观察spring自动创建bean过程2、创建自定义bean对象3、根据条件创建自定义bean二、 SpringBoot自动配置-Condition-2三、SpringBoot自动配置-切换内置web服务器1、查看继承关系图2、shiftdelete 排除Tomcat四、SpringBoot自动…