热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

程序员之网络安全系列(二):如何安全保存用户密码及哈希算法

#post_detailh2{color:#000;padding:5px;margin-bottom:10px;

系列目录:

  • 程序员之网络安全系列(一):为什么要关注网络安全?
  • 程序员之网络安全系列(二):如何安全保存用户密码及哈希算法
  • 程序员之网络安全系列(三):数据加密之对称加密算法
  • 程序员之网络安全系列(四):数据加密之非对称秘钥
  • 程序员之网络安全系列(五):数字证书以及12306的证书问题
  • 程序员之网络安全系列(六):动态密码

前言

在很多网站的早期,甚至是现在仍然有一些网站,当你点击忘记密码功能时,你的邮箱会收到一封邮件,然后里面赫然写着你的密码,很多普通用户还会觉得庆幸,总算是找回来了,殊不知,这是多么可怕地一件事,说明了网站是“几乎是”明文存储你的密码,一旦数据用户数据泄露或者被拖库,那么用户密码将赤裸裸的暴露了,想想之前几次互联网密码泄露事件。

那么如何解决呢?

加密

为了不让密码明文存储,我们需要对密码进行加密,这样即使数据库用户密码暴露,也是加密后的。但是如何让加密后的数据难以解密呢?我们现在比较流行的做法就是把密码进行Hash存储。

Hash

哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式. 典型的哈希算法包括 MD2、MD4、MD5 和 SHA-1

Hash算法是给消息生成摘要,那么什么是摘要呢?

举个例子:

比如你给你女朋友写了一封邮件,确保没被人改过,你可以生成这样一份摘要 “第50个字是我,第100个字是爱, 第998个字是你”,那么你女朋友收到这个摘要,检查一下你的邮件就可以了。

Hash算法有两个非常主要的特征:

  • 不能通过摘要来反推出原文
  • 原文的非常细小的改动,都会引起Hash结果的非常大的变化

因此,这个比较适合用来保存用户密码,因为不能反推出用户密码,Hash结果一致就证明原文一致,我们来用Ruby代码试一下上面的第二点 (MD5是一种常用的Hash算法)

2.2.3 :003 > require 'digest/md5.so'
=> true
2.2.3 :004 > puts Digest::MD5.hexdigest('I love you')
e4f58a805a6e1fd0f6bef58c86f9ceb3
=> nil
2.2.3 :005 > puts Digest::MD5.hexdigest('I love you!')
690a8cda8894e37a6fff4d1790d53b33
=> nil
2.2.3 :006 > puts Digest::MD5.hexdigest('I love you !')
b2c63c3ca6019cff3bad64fcfa807361
=> nil
2.2.3 :007 > puts Digest::MD5.hexdigest('I love you')
e4f58a805a6e1fd0f6bef58c86f9ceb3
=> nil
2.2.3 :008 >

那么我们在使用MD5保存密码时候的验证流程是什么呢?

  • 用户注册时,把用户密码是MD5(password)后保存到数据库。
  • 用户输入用户名和密码
  • 服务器从数据库查找用户名
  • 如果有这个用户,A=MD5(input password), B=Database password
  • 如果A==B, 那么说明用户密码输入正确,如果不相等,用户输入错误。

为什么Hash(MD5)后仍然不够安全?

穷举

但是,如果你认为就只是这样密码就不会被人知道,那么就不对了,这只是比明文更安全,为什么?

因为,大部分人的密码都非常简单,当拿到MD5的密码后,攻击者也可以通过比对的方式,比如你的密码是4218

2.2.3 :008 > puts Digest::MD5.hexdigest('4218')
d278df4919453195d221030324127a0e

那么攻击者可以把1到4218个数字都MD5一下,然后和你密码的MD5对比一下,就知道你原密码是什么了。

曾经我的密码箱密码忘了,我把锁给撬了,后来我才想起可以用穷举法,最多就999次不就打开了?那么问题来了,你的密码箱还安全吗?

彩虹表

除了穷举法外,由于之前的密码泄露,那么攻击者们,手上都有大量的彩虹表,比如"I love you",生日等等,这个表保存了这些原值以及MD5后的值,那么使用时直接从已有库里就可以查出来对应的密码。

加盐 Salt

那么,由于简单的对密码进行Hash算法不够安全,那么我们就可以对密码加Salt,比如密码是"I love you", 虽然彩虹表里有这条数据,但是如果加上"安红我爱你",这样MD5结果就大不一样.

jacks-MacBook-Air:~ jack$ irb
2.2.3 :001 > require 'digest/md5.so'
=> true
2.2.3 :002 > puts Digest::MD5.hexdigest('I love you')
e4f58a805a6e1fd0f6bef58c86f9ceb3
=> nil
2.2.3 :003 > puts Digest::MD5.hexdigest('I love you安红我爱你')
b10d890bf46b1a045eb99af5d43c7b13
=> nil
2.2.3 :004 > puts Digest::MD5.hexdigest('I dont love you')
c82294c9a7b6e4a372ad25ed4d6011c9
=> nil
2.2.3 :005 > puts Digest::MD5.hexdigest('I dont love you安红我爱你')
dce67bcdfdf007445dd4a2c2dc3d29c1
=> nil
2.2.3 :006 >

如此一来,因为攻击者很难猜到“安红我爱你”,那么自然彩虹表里是没有的,当然我建议你在实际项目中不要使用"安红我爱你",你应该使用一个连你自己都猜不到的较长的字符串。

加盐了,就安全了吗?

实际上,加盐并不能100%保证安全,假如有人泄露了你的Salt呢?实际上通过反编译程序很容易可以拿到这个,由于WEB程序一般放在WEB服务器上,那么就需要保证服务器不被攻击,当然这个是运维人员去操心。

为了让加盐更安全,一般情况下我们可以使用一个“盐+盐”,也就是为每个用户保存一个"Salt", 然后再使用全局的盐,我们可以对用户的盐使用自己的加密算法。那么代码就如下:

if MD5(userInputPpassword+globalsalt+usersalt)===user.databasePassword) 
{
login success
}

普通用户如何做?

由于这个是写给程序员,当然是说在前端用户注册时密码应该如何设置,很简单,我们要求用户必须输入强密码!但是,我知道很多用户觉得很烦,这样你就失掉了一个用户,但我们需要做一个适当的折中,比如至少有一个大写字母,小写字母和数字的组合。

最后

我们来看看解决了之前文章下面例子的什么问题。

假如,明明和丽丽相互不认识,明明想给丽丽写一封情书,让隔壁老王送去

  1. 如何保证隔壁老王不能看到情书内容?(保密性)
  2. 如何保证隔壁老王不修改情书的内容?(完整性)
  3. 如何保证隔壁老王不冒充明明?(身份认证)
  4. 如何保证明明不能否认情书是自己写的?(来源的不可否认)

通过了解hash算法,"明明" 就有办法让丽丽知道信的内容没有修改,他可以对邮件进行Hash生成邮件的摘要,然后让"隔壁的李叔叔"把摘要送给丽丽,丽丽拿到邮件的摘要后,把邮件内容也Hash一下,然后把结果和"隔壁的李叔叔"给的摘要对比一下,然后通过比较结果就知道邮件有没有被"隔壁的王叔叔"更改过了。


推荐阅读
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • svnWebUI:一款现代化的svn服务端管理软件
    svnWebUI是一款图形化管理服务端Subversion的配置工具,适用于非程序员使用。它解决了svn用户和权限配置繁琐且不便的问题,提供了现代化的web界面,让svn服务端管理变得轻松。演示地址:http://svn.nginxwebui.cn:6060。 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了2019年上半年内蒙古计算机软考考试的报名通知和考试时间。考试报名时间为3月1日至3月23日,考试时间为2019年5月25日。考试分为高级、中级和初级三个级别,涵盖了多个专业资格。报名采取网上报名和网上缴费的方式进行,报考人员可登录内蒙古人事考试信息网进行报名。详细内容请点击查看。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • PDO MySQL
    PDOMySQL如果文章有成千上万篇,该怎样保存?数据保存有多种方式,比如单机文件、单机数据库(SQLite)、网络数据库(MySQL、MariaDB)等等。根据项目来选择,做We ... [详细]
  • 本文介绍了自动化测试专家Elfriede Dustin在2008年的文章中讨论了自动化测试项目失败的原因。同时,引用了IDT在2007年进行的一次软件自动化测试的研究调查结果,调查显示很多公司认为自动化测试很有用,但很少有公司成功实施。调查结果表明,缺乏资源是导致自动化测试失败的主要原因,其中37%的人认为缺乏时间。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • 本文讨论了如何在codeigniter中识别来自angularjs的请求,并提供了两种方法的代码示例。作者尝试了$this->input->is_ajax_request()和自定义函数is_ajax(),但都没有成功。最后,作者展示了一个ajax请求的示例代码。 ... [详细]
  • 31.项目部署
    目录1一些概念1.1项目部署1.2WSGI1.3uWSGI1.4Nginx2安装环境与迁移项目2.1项目内容2.2项目配置2.2.1DEBUG2.2.2STAT ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
author-avatar
初始163
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有