php安全加密的方法,PHP安全-加密

加密

作为一本相关安全方面的书,通常加密是需要提及的话题。我之所以在本书的主体部分忽略了加密问题,是因为它的用途是狭窄的,而开发者应从大处着眼来考虑安全问题。过分依赖于加密常常会混淆问题的根源。尽管加密本身是有效的,但是进行加密并不会神奇地提高一个应用的安全性。

一个PHP开发人员应主要熟悉以下的加密方式:

l 对称加密

l 非对称加密(公钥)

l Hash函数(信息摘要)

l 信息验证码

本附录主要关注于使用mcrypt扩展的对称加密算法。你需要参考的资料如下:

实用加密技术(Applied Cryptography), by Bruce Schneier

(Wiley)

http://www.php.cn/

http://www.php.cn/

http://www.php.cn/

http://www.php.cn/

http://www.php.cn/

C.1. 密码的存储

当你在数据库内存储的密码时,永远不要以明码方式存入,而是应该存储密码的hash值并同时使用附加字串:

/* $password contains the password. */

$salt = 'SHIFLETT';

$password_hash = md5($salt . md5($password .

$salt));

/* Store password hash. */

?>

当你需要确认一个密码是否正确时,以同样的方式计算出hash值并比较异同:

$salt = 'SHIFLETT';

$password_hash = md5($salt .

md5($_POST['password'] . $salt));

/* Compare password hashes. */

?>

如果hash值完全相同,你就有理由认为密码也是相同的。

如果使用了这个技巧,是不可能告诉用户他们的密码是什么的。当用户忘记密码时,你只能让他录入一个新密码并重新计算hash值存入数据库。当然,你需要非常小心地对用户进行身份确认——密码提醒机制是易受频繁攻击的目标,同时也是经常出现安全漏洞的源头。

C.2. 使用mcrypt

PHP的标准加密扩展是mcrypt,它支持很多不同的加密算法。你可以通过mcrypt_list_algorithms(

)函数来查看你的平台上支持的算法列表:

echo '

' .

print_r(mcrypt_list_algorithms(), TRUE) . '

';

?>

加密和解密分别由mcrypt_encrypt( ) 及 mcrypt_decrypt(

)函数来实现。这两个函数都有5个参数,第一个参数是用于指定使用的算法:

mcrypt_encrypt($algorithm,

$key,

$cleartext,

$mode,

$iv);

mcrypt_decrypt($algorithm,

$key,

$ciphertext,

$mode,

$iv);

?>

其中的加密键(第二个参数)是非常敏感的数据,因此你要确保把它存放在安全的地方。可以用第八章中保护数据库权限的方法来保护加密键。如果经济条件允许的话,硬件加密键是最好的选择,它提供了超级强大的安全性。

函数有多种模式可供选择,你可以使用mcrypt_list_modes(

)来列出所有支持的模式:<?php

echo '

' . print_r(mcrypt_list_modes(),

TRUE) . '

';

?>

第五个参数($iv)为初始化向量,可以使用mcrypt_create_iv( )函数建立。

下面的示例类提供了基本的加密解密方法:

class crypt

{

private $algorithm;

private $mode;

private $random_source;

public $cleartext;

public $ciphertext;

public $iv;

public function __construct($algorithm =

MCRYPT_BLOWFISH,

$mode =

MCRYPT_MODE_CBC,

$random_source =

MCRYPT_DEV_URANDOM)

{

$this->algorithm = $algorithm;

$this->mode = $mode;

$this->random_source = $random_source;

}

public function generate_iv()

{

$this->iv =

mcrypt_create_iv(mcrypt_get_iv_size($this->algorithm,

$this->mode),

$this->random_source);

}

public function encrypt()

{

$this->ciphertext =

mcrypt_encrypt($this->algorithm,

$_SERVER['CRYPT_KEY'], $this->cleartext,

$this->mode, $this->iv);

}

public function decrypt()

{

$this->cleartext =

mcrypt_decrypt($this->algorithm,

$_SERVER['CRYPT_KEY'], $this->ciphertext,

$this->mode, $this->iv);

}

}

?>

上面的类会在其它示例中使用,下面是它的使用方法示例:

$crypt = new crypt();

$crypt->cleartext = 'This is a string';

$crypt->generate_iv();

$crypt->encrypt();

$ciphertext =

base64_encode($crypt->ciphertext);

$iv = base64_encode($crypt->iv);

unset($crypt);

/* Store $ciphertext and $iv (initialization

vector). */

$ciphertext = base64_decode($ciphertext);

$iv = base64_decode($iv);

$crypt = new crypt();

$crypt->iv = $iv;

$crypt->ciphertext = $ciphertext;

$crypt->decrypt();

$cleartext = $crypt->cleartext;

?>

小提示

本扩展要求你在编译PHP时使用-mcrypt标识。安装指南及要求详见http://www.php.cn/。

C.3. 信用卡号的保存

我常常被问到如何安全地保存信用卡号。我的总是会首先询问他们是否确实有必要保存信用卡号。毕竟不管具体是如何操作的,引入不必要的风险是不明智的。同时国家法律还有关于信用卡信息处理方面的规定,我还时刻小心地提醒我并不是一个法律专家。

本书中我并不会专门讨论信用卡处理的方法,而是会说明如何保存加密信息到数据库及在读取时解密。该流程会导致系统性能的下降,但是确实提供了一层保护措施。其主要优点是如果数据库内容泄密暴露出的只是加密信息,但是前提是加密键是安全的。因此,加密键与加密的实现方法本身同样重要。

保存加密数据到数据的过程是,首先加密数据,然后通过初始向量与明文建立密文来保存到数据库。由于密文是二进制字符串,还需要通过base64_encode(

)转换成普通文本字符串以保证二进制编码的安全存储。

$crypt = new crypt();

$crypt->cleartext = '1234567890123456';

$crypt->generate_iv();

$crypt->encrypt();

$ciphertext = $crypt->ciphertext;

$iv = $crypt->iv;

$string = base64_encode($iv . $ciphertext);

?>

保存该字串至数据库。在读取时,则是上面流程的逆处理:

$string = base64_decode($string);

$iv_size = mcrypt_get_iv_size($algorithm,

$mode);

$ciphertext = substr($string, $iv_size);

$iv = substr($string, 0, $iv_size);

$crypt = new crypt();

$crypt->iv = $iv;

$crypt->ciphertext = $ciphertext;

$crypt->decrypt();

$cleartext = $crypt->cleartext;

?>

本实现方法假定加密算法与模式不变。如果它们是不定的话,你还要保存它们以用于解密数据。加密键是唯一需要保密的数据。

C.4. 加密会话数据

如果你的数据库存在安全问题,或者部分保存在会话中的数据是敏感的,你可能希望加密会话数据。除非很有必要,一般我不推荐这样做,但是如果你觉得在你的情形下需要这样做的话,本节提供了一个实现方法的示例。

这个方案十分简单。实际上,在第八章中,已经说明了如何通过调用session_set_save_handler(

)来执行你自己的会话机制。通过对保存和读取数据的函数的少量调整,你就能加密存入数据库的数据及在读取时解密数据:

function _read($id)

{

global $_sess_db;

$algorithm = MCRYPT_BLOWFISH;

$mode = MCRYPT_MODE_CBC;

$id = mysql_real_escape_string($id);

$sql = "SELECT data

FROM sessions

WHERE id = '$id'";

if ($result = mysql_query($sql, $_sess_db))

{

$record = mysql_fetch_assoc($result);

$data = base64_decode($record['data']);

$iv_size = mcrypt_get_iv_size($algorithm,

$mode);

$ciphertext = substr($data, $iv_size);

$iv = substr($data, 0, $iv_size);

$crypt = new crypt();

$crypt->iv = $iv;

$crypt->ciphertext = $ciphertext;

$crypt->decrypt();

return $crypt->cleartext;

}

return '';

}

function _write($id, $data)

{

global $_sess_db;

$access = time();

$crypt = new crypt();

$crypt->cleartext = $data;

$crypt->generate_iv();

$crypt->encrypt();

$ciphertext = $crypt->ciphertext;

$iv = $crypt->iv;

$data = base64_encode($iv . $ciphertext);

$id = mysql_real_escape_string($id);

$access = mysql_real_escape_string($access);

$data = mysql_real_escape_string($data);

$sql = "REPLACE

INTO sessions

VALUES ('$id', '$access',

'$data')";

return mysql_query($sql, $_sess_db);

}

以上就是PHP安全-加密的内容,更多相关内容请关注PHP中文网(www.php.cn)!

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值