PHP密码加密实战:从MD5到Bcrypt与PasswordHashingAPI全解析
php当中openssl_private_encrypt加密的时候为什么只能加密117个字符的长度的字符串,超过这个长度的字
PHPRSA采用非对称加密解密,对应密钥长度/8-11。您可以使用AES/DES对称加密和解密,且不限制长度。
php加密方式?
有什么办法可以对PHP代码进行加密,使其不被破解在使用PHP开发Web应用程序时,很多应用程序都会要求用户进行注册,而注册时,我们需要处理的用户信息无非就是而不是电子邮件和密码。
本文的目的是讨论密码的处理:即密码的加密。
MD5
相信很多PHP开发者第一次接触PHP时,处理密码首选的加密函数可能就是MD5:
$password=md5($_POST["password"]);
上面的代码是不是听起来很熟悉?不过MD5加密方法目前在PHP界还不是很流行,因为它的加密算法其实有点简单,而且很多密码破解网站都存储了大量的MD5加密的密码字符串,所以这里我强烈推荐使用MD5。
劝阻你。
单独加密用户密码。
SHA256和SHA512
其实还存在一种SHA1加密方式,和之前的MD5类似,但是算法比较简单,这里简单提一下。
我们这里要讲的SHA256和SHA512都是SHA2家族的加密函数。
您可能从名称中猜到,这两种加密方法都会分别生成长度为256和512位的哈希字符串。
它们的用法如下:
?php
$password=hash('sha256',$password);
PHP它有一个内置的hash()函数,你只需要将加密方法传递给hash()函数即可。
可以直接使用sha256、sha512、md5、sha1等加密可以指定方法。
盐值
在加密过程中,我们还有一个很常见的伙伴:盐值。
是的,我们在加密的时候,实际上会在加密的字符串中添加一个额外的字符串,以达到一定程度的安全性:
?php
functiongenerateHashWithSalt($password){$intermediateSalt=md5(uniqid(rand(),true));$salt=substr($intermediateiateSalt,0,6);
returnhash('sha256',$password.$salt);}
Bcrypt
如果你想给我一个建议对于加密方式来说,Bcrypt可能是我推荐给你的最低要求,因为我会强烈推荐后面会谈到的HashingAPI,但Bcrypt也是一种比较好的加密方式。
?php
functiongenerateHash($password){
if(define("CRYPT_BLOWFISH")CRYPT_BLOWFISH){$salt='$2y$11$'.substr(md5(uniqid(rand(),true)),0,22);returncrypt($password,$salt);
}
}
Bcrypt实际上是Blowfish和crypt()函数的组合,我们使用CRYPT_BLOWFISH来判断Blowfish是否可用并生成salt值如上所述,但这里需要注意的是,crypt()的salt值应该从$2a$或$2y$开始。
详细信息请参见以下链接:
更多信息您可以在这里查看:
HashingAPI
这是我们的亮点。
PasswordHashingAPI是自PHP5.5起才提供的新功能。
它主要提供以下函数供我们使用:
password_hash()-对密码进行加密。
password_verify()-验证加密后的密码,检查hash字符串是否一致。
是与否。
password_needs_rehash()-重新加密密码。
password_get_info()-返回加密算法的名称和一些相关信息。
?php
$hash=password_hash($passwod,PASSWORD_DEFAULT);是的,就是这么简单,一行代码,Allden。
PASSWORD_DEFAULT目前使用的是Bcrypt,所以上面我会推荐它,但是因为PasswordHashingAPI效果更好,所以我应该认真向你推荐PasswordHashingAPI。
这里需要注意的是,如果你的代码使用PASSWORD_DEFAULT加密方式,那么在数据库表中,密码字段必须设置为不超过60个字符的长度。
您还可以使用加密字符串,在本例中该字符串的长度始终为60个字符。
这里可以使用password_hash(),Salt提供价值(salt)和消费价值(cost)。
后者你可以理解为性能消耗值,加密算法越复杂,内存消耗越高。
当然,如果需要指定对应的盐值和消耗值,可以这样写:
?php
$options=[
'salt'=custom_function_for_salt(),//writeyourowncodetogenerateasuitablesalt'cost'=12//默认cost为10
];
$hash=password_hash($password,PASSWORD_DEFAULT,$options);密码加密后,我们需要验证密码,判断用户输入的密码是否正确:
?php
if(password_verify($password,$hash)){
//通过
}
否则{
//无效
}
这很容易。
,你可以直接验证我们已经加密的字符串(存储在数据库中)。
您可以使用密码验证。
但是,如果有时候我们需要改变我们的加密方式,比如有一天我们突然想改变salt值或者增加消耗值,我们就会使用password_needs_rehash()会用到函数:
?php
if(password_needs_rehash($hash,PASSWORD_DEFAULT,['cost'=12])){//costchangeto12
$hash=password_hash($password,PASSWORD_DEFAULT,['cost'=12]);//别忘了存储新哈希!
}
仅此,PHP的PasswordHashingAPI就会知道我们再次改变了加密方式。
其主要目的是为了后续的密码验证。
简单说一下password_get_info(),这个函数一般可以看到以下三条信息:
Algo-算法示例
algoname-算法名称
选项-加密过程中的可选参数
所以,现在就开始使用PHP5.5,担心较低版本就不要这样做了。
HappyHacking
PHP中有多少种加密方法?
...原生加密功能还在加密PHP源文件吗?
函数是
md5()
md5_file()
crypt()
sha1()
sha1_file()等需要具体查看
PHP源文件加密是ZEND
PHP账户密码哪种加密方式比较好一般采用非对称加密,32位md5就够了。
验证密码是否正确时,对密码进行明文md5加密并与密文进行比较,如果一致则说明密码正确
如何加密PHP文件PHP加密平台自开放以来,已加密PHP文件670367个,总数据大小5823.04MB2015-04-18更新:PHP在线加密测试版支持命名空间加密,即对PHP源代码中带有命名空间的文件进行加密。
2015-01-13维护:修复PHP5.5及以上版本,更好支持PHP加密(免费版未更新,不会修复)
PHP授权用户移动性已简化,仅状态记录授权变更的情况2014-12-09添加自定义授权错误信息提示(之前白屏)2014-06-22支持Heredoc添加了Nowdoc语法结构的字符串2014-03-24修复了部分代码中使用__FILE__不一致的bug2013-09-02修改:PHP免费加密后版权信息添加中文声明2013-08-01新增功能:授权版可以锁定PHP文件的加密文件名,PHP文件加密后不允许更改文件名。
该功能与域名锁定功能结合使用效果更佳。
修复:部分环境下无法获取服务器IP地址2013-06-20维护:定期更新维护,对PHP加密代码进行小调整。
2013-05-12修改:重写了授权版的PHP加密算法,提高代码安全性。
2013-04-11调整:发现部分用户使用我们的免费PHP加密平台对PHP源代码进行加密以达到非法目的,因此将免费版本中上传的PHP文件大小调整为50K。
2013-03-11修订:增加付费授权版、免费版、付费授权版的安全性。
这些算法是单独处理的。
在未来的升级过程中,我们将主要升级付费授权版本,仅修复免费版本的Bug。
2013-02-01修改:免费版版权信息不再显示内核更新日期。
修改:编码增加混乱2013-01-07修改:从PHP加密代码中删除“PHPJM_”区别字符。
新增:先压缩php源代码,然后加密,以减少加密后的php文件的大小。
解决方案:php源代码中的php标签中只有?是的,但是不是?BUG2012-12-11新功能:可以锁定授权版本在一定日期范围内运行以发布您的代码作为测试。
修改:不再限制运行.php扩展名的加密文件,并支持保存任意扩展名的加密文件。
修复:优化版权信息乱码BUG2012-11-14PHP在线加密平台于2012-11-06上线,完成PHP加密核心算法代码。
PHP中的加密方法如下
1.MD5加密
stringmd5(string$str[,bool)$raw_output=false])
参数
str--原始字符串。
raw_output——如果可选的raw_output设置为TRUE,则MD5消息摘要将以原始二进制格式返回,长度为16字节。
这是不可逆加密,执行以下代码
$password='123456';
echomd5($password);
结果是e10adc3949ba59abbe56e057f20f883e
2.Crype加密
stringcrypt(string$str[,string$salt])
crypt()返回基于标准UNIXDES算法或系统哈希的值。
其他可用的字符串替代算法。
参数
str--要散列的字符串。
Salt--可选的盐值字符串。
如果未提供,算法行为将由不同的算法实现决定,并可能导致意外的结果。
这也是一种不可逆加密,执行以下代码
代码如下:
$password='123456';
$salt="test";//只取前两项
echocrypt($password,$salt);
结果为teMGKvBPcptKo
自动使用salt值的例子如下代码为:
代码如下:
$password=crypt('mypassword');//自动生成salt值
/*您应该将crypt()获得的完整结果用作密码验证的盐值,以避免使用不同的哈希算法引起的问题。
(如上所述,基于标准DES算法的密码哈希使用2个字符的盐,但基于MD5算法的哈希使用12个字符的盐。
)*/
if(crypt('mypassword',$password)==$password){
echo"Passwordverified!";
}
执行结果输出密码已验证!
使用不同哈希类型的crypt()示例如下:代码如下:
if(CRYPT_STD_DES==1){
回显'标准DES:'.crypt('rasmuslerdorf','rl').''\n";
}
if(CRYPT_EXT_DES==1){
echo'增强edDES:'.crypt('rasmuslerdorf','_J9..rasm')."\n";
}
if(CRYPT_MD5==1){<
ECho'MD5:'.crypt('rasmuslerdorf','$1$rasmusle$')."\n";
}
if(CRYPT_BLOWFISH==1){
echo'Blowfish:'.crypt('rasmuslerdorf','$2a$07$usesomesillystringforsalt$')."\n";
}
if(CRYPT_SHA256==1){
echo'SHA-256:'.crypt('rasmuslerdorf','$5$rounds=5000$usesomesillystringforsalt$')."\n";
}
if(CRYPT_SHA512==1){
echo'SHA-512:'.crypt('rasmuslerdorf','$6$rounds=5000$usesomesillystringforsalt$')."\n";
}
结果如下
标准DES:rl.3StKT.4T8M
扩展DES:_J9..rasmBYk8r9AiWNc
MD5:$1$rasmusle$rISCgZzpwk3UhDidwXvin0
河豚:$2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi
SHA-256:$5$round=5000$usesomesillystri$KqJWpanXZHKq2BOB43TSaYhEWsQ1Lr5QNyPCDH/Tp.6
在支持哈希的系统上,以下常量设置为0或1,具体取决于相应类型是否可用:CRYPT_STD_DES-"./0-9A-Za基于标准DES算法的哈希,使用-z"字符充当两个字符盐值。
在salt值中使用非法字符将导致crypt()失败。
CRYPT_EXT_DES-基于DES算法的扩展哈希。
salt值是一个9个字符的字符串,由下划线后跟4字节循环计数和4字节salt值组成。
它们以可打印字符编码,每个字符6位,最低有效位在前。
0到63被编码为“./0-9A-Za-z”。
在salt值中使用非法字符将导致crypt()失败。
CRYPT_MD5-MD5哈希使用以$1$开头的12字符字符串盐。
CRYPT_BLOWFISH-Blowfish算法使用以下盐值:“$2a$”、两位数的成本参数“$”以及包含“./0-9A-”的64位字符串字母“Za-z”。
在salt值中使用此范围之外的字符会导致crypt()返回空字符串。
两位数的成本参数是基于参数2的周期数的对数。
它的范围是04-31,如果超过这个范围,就会生成crypt()。
失败的。
CRYPT_SHA256-SHA-256算法使用以$5$开头的16个字符的字符串盐进行哈希处理。
如果salt字符串以“round=$”开头,则N的数值将为。
这用于指定哈希循环执行的次数,这在Blowfish算法中使用。
成本与参数类似。
默认循环次数为50。
00,最小值为1000,最大值为999,999,999。
在此范围之外,N将四舍五入到最接近的值。
CRYPT_SHA512-SHA-512算法使用以$6$开头的16个字符的字符串盐。
该值经过哈希处理。
如果盐值字符串以“round=$”开头,则将使用n的数值来引用它。
哈希值决定了循环执行的次数,类似于Blowfish算法的成本参数。
默认循环次数为5000,最小值为1000,最大值为999,999,999,将四舍五入到最接近的值/p>
3.Sha1加密
stringsha1(string$str[,bool$raw_output=false])
参数
str--输入字符串。
$password='123456';
echosha1($password);
得到的结果是7c4a8d09ca3762af61e59520943dc26494f8941b
虽然上述加密方式是不可逆的,但是通过查字典也可以解密。
您是否认为以下地址提供了解密上述加密结果的功能,即使添加加密也无用?其实并非如此,只要你的加密足够复杂,被破解的几率就很低。
比如使用上面的三种加密方式进行混合加密,稍后我会向大家推荐一个PHP加密库。
4.URL加密
stringurlencode(string$str)
>该函数用于对字符串进行编码,允许您在URL的请求部分使用它,还允许您将变量传递到下一页。
返回一个字符串,其中除-_之外的所有非字母数字字符都将替换为百分号(%)后跟两个十六进制数字,空格将替换为加号(+)编码为.这种编码类似于WWW表单POST数据的编码方法,以及application/x-www-form-urlencoded的媒体类型编码方法。
由于历史原因,此编码与RFC1738编码的不同之处在于加号(+)形式的编码空间。
stringurldecode(string$str)
解码给定编码字符串中的任何%##。
加号(“+”)被解码为空格字符。
这是一种可逆加密。
加密时使用urlencode方法,解密时使用urldecode方法:
$url='';
$encodeUrl=urlencode($url);echo$encodeUrl."\n";//如果是网页显示,则将\n改为
echourldecode($encodeUrl);
得到的结果如下
http%3A%2F%2F
基于RFC3986的URL加密方法如下:
代码如下:
functionmyUrlEncode($string){
$entities=array('%21','%2A','%27','%28','%29','%3B'、'%3A'、'%40'、'%26'、'%3D'、'%2B'、'%24'、'%2C'、'%2F'、'%3F'、'%25','%23','%5B','%5D');
$replace=array('!','*',"'","(",")"","",":","@","","=","+","$","","/","?","%","#","[","]");returnstr_replace($entities,$replacements,urlencode($string));
}
5、Base64信息编码与加密
stringbase64_encode(string$data)
data使用Base64进行编码。
此编码旨在使二进制数据能够通过非纯8位传输层(例如电子邮件正文)进行传输。
Base64编码的数据比原始数据多占用约33%的空间。
stringbase64_decode(string$data[,bool$strict=false])
解码Base64编码数据。
参数
数据--编码数据。
Strict——如果输入数据大于Base64字符集,则返回FALSE。
执行以下代码:
代码如下:
$name='CraryPrimitiveMan';
$encodeName=base64_encode($name);
echo$encodeName."\n";
echobase64_decode($encodeName);
结果如下
这样的代码是:
Q3JhcnlQcmltaXRpdmVNYW4=
CraryPrimitiveMan
推荐的phpass由phpass0.3测试,用户在存储到数据库之前使用保护密码的标准方法是对其进行哈希处理。
许多常用的哈希算法(例如md5甚至sha1)对于密码存储来说并不安全,因为黑客可以使用这些算法轻松破解密码。
对密码进行哈希处理的最安全方法是使用bcrypt算法。
开源PHPASS库在一个易于使用的类中提供了此功能。
代码如下:
?php
//包含phpass库
require_once('phpass-03/PasswordHash.php')
//使哈希器不可移植(更安全)
$hasher=newPasswordHash(8,false);
//计算哈希值价值。
$hashedPassword是一个60个字符的字符串。
$hashedPassword=$hasher-HashPassword('mysupercoolpassword');
$hasher-checkpassword('密码错误',$hashedpassword);//faphp加密和解密的代码
PHP提供的加密功能并不限于MD5,尽管MD5是最常用的,因为它的安全性相对较好。但现在也有一些网站提供了庞大的数据库来破解它(例如www.cmd5.com)。
除了MD5之外,PHP还支持Base64加密。
该函数可以解密,但是这种方式加密的结果不是很安全,如果要求不是太高的话可以使用。
Base64加密的函数是:base64_encode($str);相比之下,解密加密结果的函数是:base64_decode($str)。
例如:<?php$a='admin';$b=base64_encode($a);$c=base64_decode($b);echo'加密前:\$a=',$a,'
";echo"加密后:\$b=",$b,"
";echo"解密后:\$c=",$c,"
";?>如果您从这样得到的加密结果如果您不满意,您可以更改加密结果,然后在加密之前将字符串反转(反转以方便解密),然后加密或相关处理将由您自己完成。