PHP实现基于3DES算法加密解密字符串示例


Posted in PHP onAugust 24, 2018

本文实例讲述了PHP实现基于3DES算法加密解密字符串。分享给大家供大家参考,具体如下:

3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称。它相当于是对每个数据块应用三次DES加密算法。由于计算机运算能力的增强,原版DES密码的密钥长度变得容易被暴力破解;3DES即是设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。

项目地址:https://github.com/lizhibin205/lizhibin-php-mcrypt

一、为什么要进行数据加密

数据的安全性越来越得以重视。举个例子说,保存在数据库中的用户密码并不是明文保存的,而是采用md5加密后存储,这样即使数据库被脱库,仍能保证用户密码安全。但是,md5是不可逆的,开发人员根本就不知道用户的密码到底是什么。有些时候,我们希望加密后存储的数据是可逆的,比如一些接口密钥,这样即使数据库被脱库,如果没有对应的解密方式,攻击者盗取的密钥也是不能使用的。

二、3DES加密简介

3DES(即Triple DES)是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准),加密算法,其具体实现如下:设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,M代表明文,C代表密文,这样:

3DES加密过程为:C=Ek3(Dk2(Ek1(M)))

3DES解密过程为:M=Dk1(EK2(Dk3(C)))

三、使用PHP实现3DES加密

1. 使用PHP实现3DES流程图

PHP实现基于3DES算法加密解密字符串示例

要使用以上的函数,在编译PHP的时候必须添加--with-mcrypt选项。

2. PHP实现3DES代码

<?php
/**
* 3DES加解密类
* @Author: 黎志斌
* @version: v1.0
* 2016年7月21日
*/
class Encrypt
{
  //加密秘钥,
  private $_key;
  private $_iv;
  public function __construct($key, $iv)
  {
    $this->_key = $key;
    $this->_iv = $iv;
  }
  /**
  * 对字符串进行3DES加密
  * @param string 要加密的字符串
  * @return mixed 加密成功返回加密后的字符串,否则返回false
  */
  public function encrypt3DES($str)
  {
    $td = mcrypt_module_open(MCRYPT_3DES, "", MCRYPT_MODE_CBC, "");
    if ($td === false) {
      return false;
    }
    //检查加密key,iv的长度是否符合算法要求
    $key = $this->fixLen($this->_key, mcrypt_enc_get_key_size($td));
    $iv = $this->fixLen($this->_iv, mcrypt_enc_get_iv_size($td));
    //加密数据长度处理
    $str = $this->strPad($str, mcrypt_enc_get_block_size($td));
    if (mcrypt_generic_init($td, $key, $iv) !== 0) {
      return false;
    }
    $result = mcrypt_generic($td, $str);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
    return $result;
  }
  /**
  * 对加密的字符串进行3DES解密
  * @param string 要解密的字符串
  * @return mixed 加密成功返回加密后的字符串,否则返回false
  */
  public function decrypt3DES($str)
  {
    $td = mcrypt_module_open(MCRYPT_3DES, "", MCRYPT_MODE_CBC, "");
    if ($td === false) {
      return false;
    }
    //检查加密key,iv的长度是否符合算法要求
    $key = $this->fixLen($this->_key, mcrypt_enc_get_key_size($td));
    $iv = $this->fixLen($this->_iv, mcrypt_enc_get_iv_size($td));
    if (mcrypt_generic_init($td, $key, $iv) !== 0) {
      return false;
    }
    $result = mdecrypt_generic($td, $str);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
    return $this->strUnPad($result);
  }
  /**
  * 返回适合算法长度的key,iv字符串
  * @param string $str key或iv的值
  * @param int $td_len 符合条件的key或iv长度
  * @return string 返回处理后的key或iv值
  */
  private function fixLen($str, $td_len)
  {
    $str_len = strlen($str);
    if ($str_len > $td_len) {
      return substr($str, 0, $td_len);
    } else if($str_len < $td_len) {
      return str_pad($str, $td_len, '0');
    }
    return $str;
  }
  /**
  * 返回适合算法的分组大小的字符串长度,末尾使用\0补齐
  * @param string $str 要加密的字符串
  * @param int $td_group_len 符合算法的分组长度
  * @return string 返回处理后字符串
  */
  private function strPad($str, $td_group_len)
  {
    $padding_len = $td_group_len - (strlen($str) % $td_group_len);
    return str_pad($str, strlen($str) + $padding_len, "\0");
  }
  /**
  * 返回适合算法的分组大小的字符串长度,末尾使用\0补齐
  * @param string $str 要加密的字符串
  * @return string 返回处理后字符串
  */
  private function strUnPad($str)
  {
    return rtrim($str);
  }
}
$key  = 'ABCEDFGHIJKLMNOPQ';
$iv  = '0123456789';
$des = new Encrypt($key, $iv);
$str = "abcdefghijklmnopq";
echo "source: {$str},len: ",strlen($str),"\r\n";
$e_str = $des->encrypt3DES($str);
echo "entrypt: ", $e_str, "\r\n";
$d_str = $des->decrypt3DES($e_str);
echo "dntrypt: {$d_str},len: ",strlen($d_str),"\r\n";

注意,如果要在数据库中保存加密后的数据,建议base64_encode之后再保存,以下是PHP官网上的建议:

如果你在例如 MySQL 这样的数据库中存储数据, 请注意 varchar 类型的字段会在插入数据时自动移除字符串末尾的“空格”。 由于加密后的数据可能是以空格(ASCII 32)结尾, 这种特性会导致数据损坏。 请使用 tinyblob/tinytext(或 larger)字段来存储加密数据。

PHP 相关文章推荐
snoopy PHP版的网络客户端提供本地下载
Apr 15 PHP
PHP5.2中date()函数显示时间与北京时间相差8小时的解决办法
May 28 PHP
php判断是否为json格式的方法
Mar 04 PHP
destoon二次开发模板及调用语法汇总
Jun 21 PHP
实现PHP框架系列文章(6)mysql数据库方法
Mar 04 PHP
php封装的smartyBC类完整实例
Oct 19 PHP
php自定义扩展名获取函数示例
Dec 12 PHP
利用PHP实现一个简单的用户登记表示例
Apr 25 PHP
PHP使用imagick扩展实现合并图像的方法
Apr 25 PHP
Laravel5.* 打印出执行的sql语句的方法
Jul 24 PHP
php删除一个路径下的所有文件夹和文件的方法
Feb 07 PHP
PHP面向对象程序设计(OOP)之方法重写(override)操作示例
Dec 21 PHP
PHP与以太坊交互详解
Aug 24 #PHP
php获取微信基础接口凭证Access_token
Aug 23 #PHP
php对微信支付回调处理的方法
Aug 23 #PHP
PHP封装的验证码工具类定义与用法示例
Aug 22 #PHP
Yii2语言国际化自动配置详解
Aug 22 #PHP
PHP实现负载均衡的加权轮询方法分析
Aug 22 #PHP
PHP实现负载均衡session共享redis缓存操作示例
Aug 22 #PHP
You might like
Windows2003 下 MySQL 数据库每天自动备份
2006/12/21 PHP
php 获取一个月第一天与最后一天的代码
2010/05/16 PHP
PHP json格式和js json格式 js跨域调用实现代码
2012/09/08 PHP
php简单的留言板与回复功能具体实现
2014/02/19 PHP
php 使用fopen函数创建、打开文件详解及实例代码
2016/09/24 PHP
php将文件夹打包成zip文件的简单实现方法
2016/10/04 PHP
一端时间轮换的广告
2006/06/26 Javascript
newxtree.js代码
2007/03/13 Javascript
javascript类继承机制的原理分析
2009/09/12 Javascript
jquery autocomplete自动完成插件的的使用方法
2010/08/07 Javascript
web基于浏览器的本地存储方法应用
2012/11/27 Javascript
把jQuery的类、插件封装成seajs的模块的方法
2014/03/12 Javascript
Javascript闭包用法实例分析
2015/01/23 Javascript
实例讲解避免javascript冲突的方法
2016/01/03 Javascript
JS监听微信、支付宝等移动app及浏览器的返回、后退、上一页按钮的事件方法
2016/08/05 Javascript
vue 2.0路由之路由嵌套示例详解
2017/05/08 Javascript
微信小程序出现wx.navigateTo页面不跳转问题的解决方法
2017/12/26 Javascript
尝试自己动手用react来写一个分页组件(小结)
2018/02/09 Javascript
webpack@v4升级踩坑(小结)
2018/10/08 Javascript
在Windows8上的搭建Python和Django环境
2014/07/03 Python
在Python中使用Mako模版库的简单教程
2015/04/08 Python
Django中对通过测试的用户进行限制访问的方法
2015/07/23 Python
python画折线图的程序
2018/07/26 Python
python实现批量文件重命名
2019/10/31 Python
CSS3 transforms应用于背景图像的解决方法
2019/04/16 HTML / CSS
碧欧泉法国官网:Biotherm法国
2019/10/23 全球购物
Woods官网:加拿大最古老、最受尊敬的户外品牌之一
2020/09/12 全球购物
物流专业求职计划书
2014/01/10 职场文书
社区志愿者培训方案
2014/06/10 职场文书
我的未来不是梦演讲稿
2014/09/02 职场文书
学校组织向国旗敬礼活动方案(中小学适用)
2014/09/27 职场文书
教师作风建设剖析材料
2014/10/11 职场文书
师德师风整改措施
2014/10/24 职场文书
银行中层干部培训心得体会
2016/01/11 职场文书
CSS3实现的侧滑菜单
2021/04/27 HTML / CSS
如何使用vue3打造一个物料库
2021/05/08 Vue.js