PHP中的密码加密的解决方案
层出不穷的类似事件对用户会造成巨大的影响,因为人们往往习惯在不同网站使用相同的密码,一家“暴库”,全部遭殃
一般的解决方案
1、将明文密码做单向hash
$password = md5($_POST["password"]);
2、密码+salt后做单向hash,PHP内置了hash()
函数,你只需要将加密方式传给hash()
函数就好了。你可以直接指明sha256
, sha512
, md5
, sha1
等加密方式
<?php function generateHashWithSalt($password) {
$intermediateSalt = md5(uniqid(rand(), true));
$salt = substr($intermediateSalt, 0, 6);
return hash("sha256", $password . $salt);
}
单向哈希算法有一个特性,无法通过哈希后的摘要(digest)恢复原始数据,常用的单向哈希算法包括SHA-256,SHA-1,MD5等。例如,对密码“passwordhunter”进 行SHA-256哈希后的摘要(digest)如下:
“bbed833d2c7805c4bf039b140bec7e7452125a04efa9e0b296395a9b95c2d44c”
注意:攻击者可以将所有密码的常见组合进行单向哈希,得到一个摘要组合,然后与数据库中的摘要进行比对即可获得对应的密码。这个摘要组合也被称为rainbow table。更糟糕的是,一个攻击者只要建立上述的rainbow
table,可以匹配所有的密码数据库。仍然等同于一家“暴库”,全部遭殃
比较好的解决方案
Bcrypt
<?php
function generateHash($password) {
if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
$salt = '$2y$11$' . substr(md5(uniqid(rand(), true)), 0, 22);
return crypt($password, $salt);
}
}
Bcrypt 其实就是Blowfish和crypt()函数的结合,我们这里通过CRYPT_BLOWFISH判断Blowfish是否可用,然后像上面一样生成一个盐值,不过这里需要注意的是,crypt()的盐值必须以$2a$或者$2y$开头,详细资料可以参考下面的链接:
http://www.php.net/security/crypt_blowfish.php
http://php.net/manual/en/function.crypt.php
Password Hashing API
Password Hashing API
是PHP 5.5之后才有的新特性,它主要是提供下面几个函数供我们使用
password_hash() – 对密码加密.
password_verify() – 验证已经加密的密码,检验其hash字串是否一致.
password_needs_rehash() – 给密码重新加密.
password_get_info() – 返回加密算法的名称和一些相关信息.
虽然说crypt()
函数在使用上已足够,但是password_hash()
不仅可以使我们的代码更加简短,而且还在安全方面给了我们更好的保障,所以,现在PHP的官方都是推荐这种方式来加密用户的密码,很多流行的框架比如Laravel
就是用的这种加密方式
<?php
$hash = password_hash($passwod, PASSWORD_DEFAULT);
PASSWORD_DEFAULT
目前使用的就是Bcrypt
,最好的还是Password Hashing API
。这里需要注意的是,如果你代码使用的都是PASSWORD_DEFAULT
加密方式,那么在数据库的表中,password字段就得设置超过60个字符长度,你也可以使用PASSWORD_BCRYPT
,这个时候,加密后字串总是60个字符长度。
这里使用password_hash()
你完全可以不提供盐值(salt)
和 消耗值 (cost)
,你可以将后者理解为一种性能的消耗值,cost
越大,加密算法越复杂,消耗的内存也就越大。当然,如果你需要指定对应的盐值和消耗值,你可以这样写
<?php
function custom_function_for_salt(){
return $salt = '$2y$11$' . substr(md5(uniqid(rand(), true)), 0, 22);
} $password =123456; $options = [
'salt' => custom_function_for_salt(), //write your own code to generate a suitable salt
'cost' => 12 // the default cost is 10
];
$hash = password_hash($password, PASSWORD_DEFAULT, $options);
echo $hash;
密码加密过后,我们需要对密码进行验证,以此来判断用户输入的密码是否正确
<?php
if (password_verify($password, $hash)) {
// Pass
}
else {
// Invalid
}
直接使用password_verify
就可以对我们之前加密过的字符串(存在数据库中)进行验证了
如果有时候我们需要更改我们的加密方式,如某一天我们突然想更换一下盐值或者提高一下消耗值,我们这时候就要使用到password_needs_rehash()
函数了
<?php
if (password_needs_rehash($hash, PASSWORD_DEFAULT, ['cost' => 12])) {
// cost change to 12
$hash = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]); // don't forget to store the new hash!
}
只有这样,PHP的Password Hashing API
才会知道我们重现更换了加密方式,这样的主要目的就是为了后面的密码验证,password_get_info()
,这个函数一般可以看到下面三个信息
algo – 算法实例
algoName – 算法名字
options – 加密时候的可选参数
PHP中的密码加密的解决方案的更多相关文章
- glassfish配置中数据库密码加密方法
glassfish配置中数据库密码加密方法 Glassfish中的数据库连接池需要使用密文保存数据库密码.如果不是,则可按如下方法可配置 通过Glassfish中的Alias实现,配置方法如下: 1. ...
- 关于SQL 数据表中的密码加密
首先,都知道一个字节(byte)等于八位二进制数.在数据表中将密码字段设置为binary类型,再结合哈希散列运算可以实现密码加密. 下面介绍下binary 和 varbinary: binary 和 ...
- java工具类学习,系统中用户密码加密总结
现在项目,用户注册登录部分很少有涉及到了,原因:现在热门开发框架都已经在底层帮我们做了一套用户注册,密码加密,登录认证,权限控制,缓存数据等基本功能. 这有利于项目的快速完成,只需要搬砖码畜们专注于业 ...
- 对于HTTP过程中POST内容加密的解决方案
0x00前言 前几天我师傅和我提及了这件事情 正常情况下 抓包过程中遇到加密情况会很迷茫 昨天把这个都弄了一下 也感谢大佬中间的指导 我一开始看到密码的类型下意识的是base64 但是去解密发现不对 ...
- 13flask密码加密
一,了解密码加密方式 密码具有私有性较强的特性,预测密码加密对个人隐私的保护有这非常大的作用.在用flask搭建网站时候若服务器有被攻破的风险,要是用户表中密码字段也被拿走,后果将不堪设想. 在密码保 ...
- c#程序中对密码进行加密的方法
在ADO.NET中,向数据库添加数据时,怎样对数据中的密码进行加密?(也就是说在数据表中也看不到用户的密 码,只是一些经过编译后的字符串,以防止数据库管理员利用用户的密码进行非法操作.) 首先, ...
- 在OpenErp的配置文件中为数据库密码加密
openerp连接数据库的用户名和密码可以命令行给出, 也可以设置在配置文件中, 如下例所示: db_user = openerp db_password = laoliu 因为它使用了明文的密码 ...
- Jmeter 请求参数中包含 MD5 加密的密码
如何在jmeter中对参数进行加密 使用工具:java+myeclipse 让开发将他的加密类从eclipse中导出来打成jar包,放在jmeter安装文件夹lib文件夹中%JMETER HOME%\ ...
- ssh登录时在参数中加入密码的解决方案
在使用ssh登录远程服务器的时候,在执行完ssh user@ip后,要输入登录密码,有时候登录密码记不住,这样以来Ian带来的很多的麻烦,有没有一种在ssh的参数中直接加入密码的方法呢?查看ssh的帮 ...
随机推荐
- Tomcat 下 Memcached 集群与 Terracotta 集群比较
总结:Terracotta 集群配置要比Memcached 集群简单,但Terracotta 集群启动的速度要比Memcached 集群慢,性能Terracotta 集群要比Memcached 集群好 ...
- synchronized与lock,哪个效率更高
Java在一开始就提供了synchronized关键字,用于多线程之间的同步.它使用简便,不会出现拿锁之后不归还的情况,可以避免一些编程错误. 而jdk5时提供的concurrent包里,有一个Loc ...
- JQuery实现可直接编辑的表格
本文实例讲述了JQuery实现可直接编辑的表格.分享给大家供大家参考.具体分析如下: 功能: 创建一个表格,用户单击某个单元格后,可以直接修改单元格文本.在编辑状态下,用户可按回车键确认修改,按ESC ...
- Ceph rgws客户端验证
修改/etc/ceph/ceph.conf文件,加入rados gw监听的端口 [client.rgw.rgws] rgw_frontends = "civetweb port=80&quo ...
- C语言:通过函数指针来完成两个数的加减乘除(函数指针当做参数使用)
// // main.c // Function_pointer // // Created by mac on 15/8/2. // Copyright (c) 2015年. All rig ...
- Qt学习之对话框与主窗口的创建
Qt中的信号与槽机制 qt中槽和普通的C++成员函数几乎是一样的--可以是虚函数,可以被重载,可以是共有的,保护的或者私有的. 槽可以和信号连接在一起,在这种情况下,每当发射这个信号的信号,就会自动调 ...
- Linux c 屏蔽信号、切换信号
信号导致的问题 不是任何信号我们都需要的,如果遇到我们不想处理的信号,我们怎么避免这个信号? 1. 信号屏蔽 intsigprocmask(int how,//操作方式 SIG_BLOCK屏 ...
- MySql无法远程登录以及IP被锁解决办法
授权 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '' WITH GRANT OPTION;Query OK, 0 rows aff ...
- GetProcAddress 使用注意事项
使用 GetProcAddress Function 时,有以下几点需要特别留意: 1. 第二个参数类型是 LPCSTR,不是 : 2. 用 __declspec(dllexport),按 C 名称修 ...
- 单页WEB应用(三),Chat聊天模块
Chat 聊天模块 这个模块应该就是该书全篇的唯一一个模块吧,后面差点儿全部的篇章都环绕这个模块去实现的,只是就通过这一个模块的实现和上线,也能体现单页应用开发到公布上线的整个过程,毕竟后面的数据.通 ...