两者区别:
1.Hash不可逆,且具有相同的长度; Encrypt可逆的,长度一般与明文长度成正比
2.Hash是多对一的,即两个不同的明文有可能会生成同一个Hash,两者称为碰撞; Encrypt是一对一的
两者选择:
如果数据仅仅是用来验证 则使用Hash,反之则使用Encrypt
两者使用:
常用的Hash算法有MD5和SHA1,我们知道Hash算法是存在碰撞这种情况的,所以要通过Hash算法的验证 除了可以用原文之外 也可以通过原文的一个碰撞通过;另外也可以通过穷举法 不停的试错;所以在开发中,对于需要用于验证的数据,最好使用多重混合Hash,再或者使用salt
/**
* 多重混合hash
* md5: hash('md5', 'xxxx');
* sha1: hash('sha1', 'xxxx')
*/
$text = '123456';
$salt = 'abc';
//eg1
$hash = sha1(md5($text).md5($text));
//eg2
$hash = sha1(md5($text).md5($salt));
//以上需要将$hash,$salt都存入数据库
常用的Encrypt算法有DES和AES,我们知道加密是可逆的,这就需要我们再加密后的密文中再次加入一些混淆,来增加破解的难度 下面用手册的例子作说明
//数据加密
$plaintext = "message to be encrypted";//原文
$cipher="AES-128-CBC"; //加密类型
$ivlen = openssl_cipher_iv_length($cipher);//根据加密类型获取向量长度
$iv = openssl_random_pseudo_bytes($ivlen);//根据向量长度生成随机向量数值
$ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
//以上加密就算完成了 以下为增加加密后的混淆
//对密文进行二进制的hash
$hmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
//将向量的值,密文的hash值,密文进行base64编码
$ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );
//至此一个完整的加密流程结束
//数据解密
$cipher="AES-128-CBC"
$c = base64_decode($ciphertext);//先base64解码
$ivlen = openssl_cipher_iv_length($cipher);//根据加密类型获取向量长度
$iv = substr($c, 0, $ivlen);//从密文中读取向量的值
$hmac = substr($c, $ivlen, $sha2len=32);//从密文中读取密文的hash值
$ciphertext_raw = substr($c, $ivlen+$sha2len);//获取真正的密文
$calcmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);//对密文hash
if (hash_equals($hmac, $calcmac))//判断当前密文hash与获取到的hash是否匹配
{//匹配则进行解密
$original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $key,
$options=OPENSSL_RAW_DATA, $iv);//对密文进行解密
echo $original_plaintext."\n";//输出原始密文
}
Hash比较
$a = '0e123123123';
$b = '0e789789789';
if ($a == $b){
echo '==:true';
if(hash_equals($a,$b)){
echo 'hash: true';
} else {
echo 'hash: false';
}
} else {
echo '==:false';
}
/*
输出结果:
// '==:true
// 'hash: false'
*/
在php中 0eXXX 如果是0e开头的且后面均为数字的 会认为是0的XXX次幂 然后得出结果为0
所以我们需要使用 hash_equals ,当然也可以使用 全等于“===”