PHP 7: 真实世界的应用开发
  • 前言
  • 模块一
    • 第一章、建立基础
      • PHP 7 安装注意事项
      • 使用内置的 PHP web 服务器
      • 创建一个 MySQL 测试数据库
      • 安装 PHPUnit
      • 实现类的自动加载
      • 抓取一个网站
      • 建立一个深度网络扫描器
      • 创建一个 PHP 5 到 PHP 7 代码转换器
    • 第二章、使用 PHP 7 高性能特性
      • 了解抽象语法树
      • 理解句法分析中的差异
      • 理解 foreach() 处理中的差异
      • 使用 PHP 7 增强功能提高性能
      • 遍历海量文件
      • 将电子表格上传到数据库
      • 递归目录迭代器
    • 第三章、使用 PHP 函数
      • 函数开发
      • 数据类型提示
      • 使用返回值数据类型
      • 使用迭代器
      • 使用生成器编写自己的迭代器
    • 第四章、使用 PHP 面向对象程序设计
      • 类的开发
      • 类的扩展
      • 使用静态属性和方法
      • 使用命名空间
      • 定义可见性
      • 使用接口
      • 使用特性
      • 实现匿名类
    • 第五章、与数据库的交互
      • 使用PDO连接数据库
      • 构建一个 OOP SQL 查询生成器
      • 处理分页
      • 定义实体以匹配数据库表
      • 将实体类与RDBMS查询绑定
      • 将二次查找嵌入到查询结果中
      • 实现jQuery DataTables的PHP查找
    • 第六章、建立可扩展的网站
      • 创建通用表单元素生成器
      • 创建一个HTML单选元素生成器
      • 创建一个HTML选择元素生成器
      • 实现表单工厂
      • 链式 $_POST 过滤器
      • 链式 $_POST 验证器
      • 将验证绑定到表单
    • 第七章、访问Web服务
      • 在PHP和XML之间转换
      • 创建一个简单的REST客户端
      • 创建一个简单的REST服务器
      • 创建一个简单的SOAP客户端
      • 创建一个简单的SOAP服务器
    • 第八章、处理日期/时间和国际化方面
      • 在视图脚本中使用 emoji
      • 转换复杂字符
      • 从浏览器数据获取语言环境
      • 按地区设置数字格式
      • 按地区处理货币
      • 按地区设置日期/时间格式
      • 创建一个HTML国际日历生成器
      • 构建一个周期性事件生成器
      • 不使用gettext处理翻译
    • 第九章、开发中间件
      • 使用中间件进行认证
      • 使用中间件实现访问控制
      • 使用高速缓存提高性能
      • 实施路由选择
      • 进行框架间的系统调用
      • 使用中间件来跨语言
    • 第十章、高级算法
      • 使用 getter 和 setter
      • 实现一个链表
      • 建立冒泡排序
      • 实现一个堆栈
      • 构建一个二分法查找类
      • 实现一个搜索引擎
      • 显示多维数组并累计总数
    • 第十一章、软件设计模式的实现
      • 创建数组到对象的转化器
      • 构建对象到数组到转化器
      • 实施策略模式
      • 定义一个映射器
      • 实现对象关系映射
      • 实施发布/订阅设计模式
    • 第十二章、提高网站安全
      • 过滤$_POST数据
      • 验证$_POST数据
      • 保护PHP session
      • 用令牌保护表格的安全
      • 建立一个安全的密码生成器
      • 带有验证码的安全保护表格
      • 不使用mcrypt进行加密/解密
    • 第十三章、最佳实践、测试和调试
      • 使用特征和接口
      • 通用异常处理程序
      • 通用错误处理程序
      • 编写一个简单的测试
      • 编写测试套件
      • 生成虚假的测试数据
      • 使用session_start参数自定义会话
    • PSR-7
  • 模块二
  • 模块三
    • GoF 设计模式
      • 结构型
      • 行为型
      • 小结
    • SOLID 设计原则
      • 开闭原则
      • 里氏替换原则
      • 接口隔离原则
      • 依赖反转原则
      • 小结
    • 模块化网店应用的需求规范
      • 线框设计
      • 定义技术栈
      • 小结
    • Symfony 概述
      • 创建一个空白项目
      • 使用 Symfony 控制台
      • 控制器
      • 路由
      • 模板
      • 表单
      • 配置 Symfony
      • bundle 系统
      • 数据库和 Doctrine
      • 测试
      • 验证
      • 小结
    • 构建核心模块
    • 构建目录模块
    • 构建客户模块
    • 构建支付模块
    • 构建发货模块
    • 构建销售模块
    • 总结
由 GitBook 提供支持
在本页
  • 如何做...
  • 如何运行...
  • 更多...
  • 更多...
  1. 模块一
  2. 第十二章、提高网站安全

不使用mcrypt进行加密/解密

在一般的 PHP 社区成员中,一个鲜为人知的事实是,作为大多数基于 PHP 的加密的核心的 mcrypt 扩展被认为是安全的,但它并不安全。从安全的角度来看,最大的问题之一是 mcrypt 扩展需要高级的密码学知识才能成功运行,而很少有程序员具备这些知识。这就导致了严重的误操作,最终导致数据损坏的几率为256分之一等问题。这可不是什么好机会。此外,开发人员对libmcrypt的支持,即mcrypt扩展所基于的核心库,已于2007年被放弃,这意味着代码库已经过时,错误百出,并且没有应用补丁的机制。因此,了解如何在不使用mcrypt的情况下进行强加密/解密是非常重要的。

如何做...

1.之前提出的问题的解决方案,如果你想知道,就是使用openssl。这个扩展维护得很好,并且具有现代的、非常强大的加密/解密功能。

为了使用任何openssl*函数,openssl PHP扩展必须被编译并启用!此外,你需要在你的Web服务器上安装最新的OpenSSL包。

2. 首先,你需要确定你的安装中哪些密码方法是可用的。为此,您可以使用 openssl_get_cipher_methods() 命令。例子包括基于高级加密标准(AES)、BlowFish(BF)、CAMELLIA、CAST5、数据加密标准(DES)、Rivest密码(RC)(也被亲切地称为Ron's Code)和SEED的算法。你会注意到,这个方法显示的密码方法是大写和小写重复的。

3. 接下来,你需要弄清楚哪种方法最适合你的需求。下面是一个表格,对各种方法进行了快速的总结。

方法

发布时间

密钥大小(bits)

密钥块大小 (bytes)

备注

camellia

2000

128, 192, 256

16

由三菱和NTT共同开发

aes

1998

128, 192, 256

16

由Joan Daemen和Vincent Rijmen开发。最初以Rijndael的名义提交

seed

1998

128

16

由韩国信息安全局开发

cast5

1996

40-128

8

由Carlisle Adams和Stafford Tavares开发

bf

1993

1 - 448

8

由Bruce Schneier设计

rc2

1987

8 - 1,024

默认 64

8

由Ron Rivest(RSA的核心创始人之一)设计

des

1977

56 (+8 奇偶校验位)

8

由IBM开发,基于Horst Feistel的工作

4. 另一个考虑因素是你喜欢的块密码操作模式是什么。常见的选择总结在这个表中。

模式

代表

备注

ECB

Electronic Code Book

不需要初始化向量(IV);加密和解密都支持并行化;简单快速;不隐藏数据模式;不推荐!!!

CBC

Cipher Block Chaining

需要IV;后续的块,即使是相同的,也会与前一个块进行XOR编辑,从而获得更好的整体加密效果;如果IV是可预测的,第一个块可以被解密,剩下的信息就会暴露出来;信息必须被填充到密码块大小的倍数;只支持解密的并行化

CFB

Cipher Feedback

CBC的近亲,只是加密方式是反向的

OFB

Output Feedback

非常对称:加密和解密相同;完全不支持并行化

CTR

Counter

与OFB的操作类似;支持加密和解密的并行化

CCM

Counter with CBC-MAC

CTR的衍生物;仅设计为128位的块长;提供认证和保密性;CBC-MAC代表密码块链-信息认证码

GCM

Galois/Counter Mode

基于CTR模式;应该对每个流使用不同的IV进行加密;特别高的吞吐量(与其他模式相比);支持加密和解密的并行化

XTS

XEX-based Tweaked-codebook mode with ciphertext Stealing

相对较新(2010年)且速度较快;使用两把钥匙;增加了可作为一个区块安全加密的数据量

5. 在选择加密方法和模式之前,你还需要确定加密的内容是否需要在你的PHP应用之外解密。例如,如果你是将数据库凭证加密存储到一个独立的文本文件中,你是否需要具备从命令行解密的能力?如果是这样,请确保你选择的加密方法和操作模式是目标操作系统所支持的。

6. 为IV提供的字节数根据选择的密码方法而变化。为了得到最好的结果,可以使用 random_bytes()(PHP 7 中新增),它返回一个真正的 CSPRNG 字节序列。IV的长度有很大的不同。试着从16开始。如果产生警告,将显示该算法所需提供的正确字节数,因此要相应调整大小。

$iv  = random_bytes(16);

7. 要执行加密,使用openssl_encrypt()。以下是需要传递的参数。

参数

备注

Data

纯文本你需要加密的内容

Method

你用openssl_get_cipher_methods()确定的一个方法,确定如下。 方法 - key_size - cipher_mode 所以,举例来说,如果你想采用AES的方法,密钥大小为256,并采用GCM模式,你可以输入aes-256-gcm。

Password

虽然这个参数被记录为密码,但它可以被看作是一个密钥。使用random_bytes()来生成一个与所需密钥大小相匹配的字节数的密钥。

Options

在你获得更多openssl加密经验之前,建议你坚持使用默认值0。

IV

使用random_bytes()来生成一个具有与密码方法相匹配的字节数的IV。

8. 举个例子,假设你想选择AES加密方式,密钥大小为256,XTS模式。下面是用于加密的代码。

$plainText = 'Super Secret Credentials';
$key = random_bytes(16);
$method = 'aes-256-xts';
$cipherText = openssl_encrypt($plainText, $method, $key, 0, $iv);

9. 要解密,对$key和$iv使用相同的值,以及openssl_decrypt()函数。

$plainText = openssl_decrypt($cipherText, $method, $key, 0, $iv);

如何运行...

为了查看可用的密码方法,创建一个名为chap_12_openssl_encryption.php的PHP脚本,然后运行这个命令。

<?php
echo implode(', ', openssl_get_cipher_methods());

输出应该是这样的。

接下来,可以为要加密的纯文本、方法、密钥和IV添加值。举个例子,试试使用XTS操作模式下的AES,密钥大小为256。

$plainText = 'Super Secret Credentials';
$method = 'aes-256-xts';
$key = random_bytes(16);
$iv  = random_bytes(16);

要加密,你可以使用openssl_encrypt(),指定之前配置的参数。

$cipherText = openssl_encrypt($plainText, $method, $key, 0, $iv);

你可能还想对结果进行base64编码,以使其更加可用。

$cipherText = base64_encode($cipherText);

解密时,使用相同的$key和$iv值。不要忘了先解密base64值。

$plainText = openssl_decrypt(base64_decode($cipherText), 
$method, $key, 0, $iv);

这里的输出显示的是base64编码的密码文本,然后是解密后的明文。

如果你为IV提供的字节数不正确,对于所选择的密码方法,将显示一条警告信息。

更多...

在 PHP 7 中,当使用 open_ssl_encrypt() 和 open_ssl_decrypt() 以及所支持的认证数据加密 (AEAD) 模式时出现了一个问题——GCM 和 CCM。因此,在 PHP 7.1 中,这些函数增加了三个额外的参数,如下所示。

参数

备注

$tag

通过引用传递的认证标签;如果认证失败,变量值保持不变。

$aad

额外的认证数据

$tag_length

GCM模式为4-16;CCM模式无限制;仅适用于open_ssl_encrypt()

更多信息,您可以参考https://wiki.php.net/rfc/openssl_aead。

更多...

关于为什么在 PHP 7.1 中取消 mcrypt 扩展的优秀讨论,请参考 https://wiki.php.net/rfc/mcrypt-viking-funeral 的文章。关于构成各种加密方法基础的块加密的良好描述,请参考 https://en.wikipedia.org/wiki/Block_cipher 的文章。关于AES的优秀描述,请参考https://en.wikipedia.org/wiki/Advanced_Encryption_Standard。关于描述加密操作模式的优秀文章,可以参考https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation。

对于一些较新的模式,如果要加密的数据小于块大小,openssl_decrypt()将不返回任何值。如果你把数据填充到至少是块大小,问题就会消失。大多数的模式都实现了内部填充,所以这不是问题。对于一些较新的模式(即xts),你可能会看到这个问题。在将你的代码投入生产之前,一定要对小于8个字符的短数据串进行测试。

上一页带有验证码的安全保护表格下一页第十三章、最佳实践、测试和调试

最后更新于4年前