php传值解密,如何在php中加密/解密数据?

本文详细介绍了如何使用对称密码加密、单程密码散列和初始化向量来保护用户数据,如名字、电子邮件和密码。推荐使用AES-256-CBC模式,强调了加密密钥和IV的重要性,以及如何在数据库中存储这些加密后的信息。此外,还讨论了密码哈希的安全性,推荐使用bcrypt算法,并提供了PHP实现的示例。
摘要由CSDN通过智能技术生成

前言

从表定义开始:- UserID- Fname- Lname- Email- Password- IV

以下是一些变化:田野

Fname, Lname和

Email将使用对称密码加密,该密码由

这个

IV字段将存储用于加密。存储需求取决于所使用的密码和模式;稍后将详细介绍。

这个

Password字段将使用

单程密码散列,

加密

密码与模式

选择最佳的加密密码和模式超出了这个答案的范围,但最终的选择会影响加密密钥和初始化向量的大小;对于这篇文章,我们将使用AES-256-CBC,它的固定块大小为16字节,密钥大小为16、24或32字节。

加密密钥

一个好的加密密钥是由一个可靠的随机数生成器生成的二进制BLOB。建议采用以下示例(>=5.3):$key_size = 32; // 256 bits$encryption_key = openssl_random_pseudo_bytes($key_size, $strong);// $strong will be true if the key is crypto safe

这可以执行一次或多次(如果您希望创建一个加密密钥链)。把这些尽量保密。

四、四

初始化向量增加了加密的随机性,并且是CBC模式所必需的。理想情况下,这些值应该只使用一次(从技术上讲,每个加密密钥只使用一次),因此对行的任何部分的更新都应该重新生成它。

提供了一个函数来帮助您生成IV:$iv_size = 16; // 128 bits$iv = openssl_random_pseudo_bytes($iv_size, $strong);

让我们使用前面的$encryption_key和$iv要做到这一点,我们必须将数据填充到块大小:function pkcs7_pad($data, $size){

$length = $size - strlen($data) % $size;

return $data . str_repeat(chr($length), $length);}$name = 'Jack';$enc_name = openssl_encrypt(

pkcs7_pad($name, 16), // padded data

'AES-256-CBC',        // cipher and mode

$encryption_key,      // secret key

0,                    // options (not used)

$iv                   // initialisation vector);

存储要求

与IV一样,加密的输出是二进制的;在数据库中存储这些值可以通过使用指定的列类型来完成,例如BINARY或VARBINARY.

与IV一样,输出值是二进制的;要将这些值存储在MySQL中,请考虑使用BINARY或VARBINARY柱子。如果这不是一个选项,则还可以使用以下方法将二进制数据转换为文本表示。base64_encode()或bin2hex()这样做需要33%到100%的存储空间。

解密

存储值的解密类似于:function pkcs7_unpad($data){

return substr($data, 0, -ord($data[strlen($data) - 1]));}$row = $result->fetch(PDO::FETCH_ASSOC); // read from database result// $enc_name = base64_decode($row['Name']);// $enc_name = hex2bin($row['Name']);$enc_name = $row['Name'];// $iv = base64_decode($row['IV']);// $iv = hex2bin($row['IV']);$iv = $row['IV'];$name = pkcs7_unpad(openssl_decrypt(

$enc_name,

'AES-256-CBC',

$encryption_key,

0,

$iv));

认证加密

您可以通过附加从秘密密钥(不同于加密密钥)和密码文本生成的签名来进一步提高生成的密码文本的完整性。在解密密码文本之前,首先验证签名(最好采用常数时间比较方法)。

例// generate once, keep safe$auth_key = openssl_random_pseudo_bytes(32, $strong);// authentication$auth = hash_hmac('sha256', $enc_name, $auth_key, true);$auth_enc_name = $auth . $enc_name;// verification$auth = substr($auth_enc_name, 0, 32);$enc_name = substr($auth_enc_name, 32);$actual_auth = hash_hmac('sha256', $enc_name, $auth_key, true);if (hash_equals($auth, $actual_auth)) {

// perform decryption}

散列

必须尽可能避免在数据库中存储可逆密码;您只希望验证密码,而不希望知道其内容。如果用户丢失了密码,最好让他们重新设置密码,而不是发送给他们原来的密码(确保密码重置只能在有限的时间内完成)。

应用哈希函数是一种单向操作;之后,它可以安全地用于验证而不泄露原始数据;对于密码,蛮力方法是一种可行的方法来发现它,因为它的长度相对较短,而且很多人的密码选择都很差。

哈希算法(如MD5或SHA 1)用于根据已知的哈希值验证文件内容。他们进行了极大的优化,使这一验证尽可能快,同时仍然是准确的。考虑到它们相对有限的输出空间,使用已知密码和各自的散列输出彩虹表来构建数据库是很容易的。

在密码哈希之前添加一个盐将使彩虹表变得无用,但是最近的硬件进步使得蛮力查找成为一种可行的方法。这就是为什么你需要一个杂凑算法,这是刻意缓慢和根本不可能优化的。它还应该能够为更快的硬件增加负载,而不影响验证现有密码散列的能力,使其成为未来的证明。

目前有两种流行的选择:PBKDF 2(基于密码的密钥派生函数v2)

bcrypt(又名龙虾)

这个答案将使用bcrypt的例子。

世代

可以生成这样的密码哈希:$password = 'my password';$random = openssl_random_pseudo_bytes(18);$salt = sprintf('$2y$%02d$%s',

13, // 2^n cost factor

substr(strtr(base64_encode($random), '+', '.'), 0, 22));$hash = crypt($password, $salt);

盐是用openssl_random_pseudo_bytes()形成一个随机的数据块,然后通过base64_encode()和strtr()匹配所需的字母表[A-Za-z0-9/.].

这个crypt()函数根据以下算法执行散列($2y$对于Blowfish),成本因素(在一台3 GHz的机器上约为0.40)和22个字符的盐分(因子为13)。

验证

一旦获取了包含用户信息的行,就可以以下方式验证密码:$given_password = $_POST['password']; // the submitted password$db_hash = $row['Password']; // field with the password hash$given_hash = crypt($given_password, $db_hash);if (isEqual($given_hash, $db_hash)) {

// user password verified}// constant time string comparefunction isEqual($str1, $str2){

$n1 = strlen($str1);

if (strlen($str2) != $n1) {

return false;

}

for ($i = 0, $diff = 0; $i != $n1; ++$i) {

$diff |= ord($str1[$i]) ^ ord($str2[$i]);

}

return !$diff;}

要验证密码,请调用crypt()同样,但是您将先前计算的散列作为盐分值传递。如果给定密码与哈希匹配,则返回值将产生相同的哈希。为了验证哈希,通常建议使用常数时间比较函数来避免定时攻击。

用PHP5.5对密码进行散列

PHP 5.5引入了密码散列函数可以用来简化上述散列方法:$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 13]);

并核实:if (password_verify($given_password, $db_hash)) {

// password valid}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值