PHP对称加密算法(DES/AES)类的实现代码


Posted in PHP onNovember 14, 2017

对称密钥加密机制即对称密码体系,也称为单钥密码体系和传统密码体系。对称密码体系通常分为两大类,一类是分组密码(如DES、AES算法),另一类是序列密码(如RC4算法)。

AES 是一个新的可以用于保护电子数据的加密算法。明确地说,AES 是一个迭代的、对称密钥分组的密码,它可以使用128、192 和 256 位密钥,并且用 128 位(16字节)分组加密和解密数据。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据 的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换(permutations )和替换(substitutions)输入数据。Figure 1 显示了 AES 用192位密钥对一个16位字节数据块进行加密和解密的情形。

那DES是什么呢?DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。需要注意的是,在某些文献中,作为算法的DES称为数据加密算法(Data Encryption Algorithm,DSA),已与作为标准的DES区分开来。

DES设计中使用了分组密码设计的两个原则:混淆(confusion)和扩散(diffusion),其目的是抗击敌手对密码系统的统计分析。混淆是使密文的统计特性与密钥的取值之间的关系尽可能复杂化,以使密钥和明文以及密文之间的依赖性对密码分析者来说是无法利用的。扩散的作用就是将每一位明文的影响尽可能迅速地作用到较多的输出密文位中,以便在大量的密文中消除明文的统计结构,并且使每一位密钥的影响尽可能迅速地扩展到较多的密文位中,以防对密钥进行逐段破译。

/** 
 * 常用对称加密算法类 
 * 支持密钥:64/128/256 bit(字节长度8/16/32) 
 * 支持算法:DES/AES(根据密钥长度自动匹配使用:DES:64bit AES:128/256bit) 
 * 支持模式:CBC/ECB/OFB/CFB 
 * 密文编码:base64字符串/十六进制字符串/二进制字符串流 
 * 填充方式: PKCS5Padding(DES) 
 * 
 * @author: linvo 
 * @version: 1.0.0 
 * @date: 2013/1/10 
 */  
class Xcrypt{  
  
  private $mcrypt;  
  private $key;  
  private $mode;  
  private $iv;  
  private $blocksize;  
  
  /** 
   * 构造函数 
   * 
   * @param string 密钥 
   * @param string 模式 
   * @param string 向量("off":不使用 / "auto":自动 / 其他:指定值,长度同密钥) 
   */  
  public function __construct($key, $mode = 'cbc', $iv = "off"){  
    switch (strlen($key)){  
    case 8:  
      $this->mcrypt = MCRYPT_DES;  
      break;  
    case 16:  
      $this->mcrypt = MCRYPT_RIJNDAEL_128;  
      break;  
    case 32:  
      $this->mcrypt = MCRYPT_RIJNDAEL_256;  
      break;  
    default:  
      die("Key size must be 8/16/32");  
    }  
  
    $this->key = $key;  
  
    switch (strtolower($mode)){  
    case 'ofb':  
      $this->mode = MCRYPT_MODE_OFB;  
      if ($iv == 'off') die('OFB must give a IV'); //OFB必须有向量  
      break;  
    case 'cfb':  
      $this->mode = MCRYPT_MODE_CFB;  
      if ($iv == 'off') die('CFB must give a IV'); //CFB必须有向量  
      break;  
    case 'ecb':  
      $this->mode = MCRYPT_MODE_ECB;  
      $iv = 'off'; //ECB不需要向量  
      break;  
    case 'cbc':  
    default:  
      $this->mode = MCRYPT_MODE_CBC;  
    }  
  
    switch (strtolower($iv)){  
    case "off":  
      $this->iv = null;  
      break;  
    case "auto":  
      $source = PHP_OS=='WINNT' ? MCRYPT_RAND : MCRYPT_DEV_RANDOM;  
      $this->iv = mcrypt_create_iv(mcrypt_get_block_size($this->mcrypt, $this->mode), $source);  
      break;  
    default:  
      $this->iv = $iv;  
    }  
  
  }  
  
  /** 
   * 获取向量值 
   * @param string 向量值编码(base64/hex/bin) 
   * @return string 向量值 
   */  
  public function getIV($code = 'base64'){  
    switch ($code){  
    case 'base64':  
      $ret = base64_encode($this->iv);  
      break;  
    case 'hex':  
      $ret = bin2hex($this->iv);  
      break;  
    case 'bin':  
    default:  
      $ret = $this->iv;  
    }  
    return $ret;  
  }  
  
  /** 
   * 加密 
   * @param string 明文 
   * @param string 密文编码(base64/hex/bin) 
   * @return string 密文 
   */  
  public function encrypt($str, $code = 'base64'){  
    if ($this->mcrypt == MCRYPT_DES) $str = $this->_pkcs5Pad($str);  
  
    if (isset($this->iv)) {  
      $result = mcrypt_encrypt($this->mcrypt, $this->key, $str, $this->mode, $this->iv);   
    } else {  
      @$result = mcrypt_encrypt($this->mcrypt, $this->key, $str, $this->mode);   
    }  
  
    switch ($code){  
    case 'base64':  
      $ret = base64_encode($result);  
      break;  
    case 'hex':  
      $ret = bin2hex($result);  
      break;  
    case 'bin':  
    default:  
      $ret = $result;  
    }  
  
    return $ret;  
  
  }  
  
  /** 
   * 解密  
   * @param string 密文 
   * @param string 密文编码(base64/hex/bin) 
   * @return string 明文 
   */  
  public function decrypt($str, $code = "base64"){    
    $ret = false;  
  
    switch ($code){  
    case 'base64':  
      $str = base64_decode($str);  
      break;  
    case 'hex':  
      $str = $this->_hex2bin($str);  
      break;  
    case 'bin':  
    default:  
    }  
  
    if ($str !== false){  
      if (isset($this->iv)) {  
        $ret = mcrypt_decrypt($this->mcrypt, $this->key, $str, $this->mode, $this->iv);   
      } else {  
        @$ret = mcrypt_decrypt($this->mcrypt, $this->key, $str, $this->mode);   
      }  
      if ($this->mcrypt == MCRYPT_DES) $ret = $this->_pkcs5Unpad($ret);  
    }  
  
    return $ret;   
  }   
  
  private function _pkcs5Pad($text){  
    $this->blocksize = mcrypt_get_block_size($this->mcrypt, $this->mode);   
    $pad = $this->blocksize - (strlen($text) % $this->blocksize);  
    return $text . str_repeat(chr($pad), $pad);  
  }  
  
  private function _pkcs5Unpad($text){  
    $pad = ord($text{strlen($text) - 1});  
    if ($pad > strlen($text)) return false;  
    if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;  
    $ret = substr($text, 0, -1 * $pad);  
    return $ret;  
  }  
  
  private function _hex2bin($hex = false){  
    $ret = $hex !== false && preg_match('/^[0-9a-fA-F]+$/i', $hex) ? pack("H*", $hex) : false;    
    return $ret;  
  }  
  
}

使用实例

<?php  
header('Content-Type:text/html;Charset=utf-8;');  
  
include "xcrypt.php";  
  
echo '<pre>';  
//////////////////////////////////////  
$a = isset($_GET['a']) ? $_GET['a'] : '测试123';  
  
//密钥  
$key = '12345678123456781234567812345678'; //256 bit  
$key = '1234567812345678'; //128 bit  
$key = '12345678'; //64 bit  
  
//设置模式和IV  
$m = new Xcrypt($key, 'cbc', 'auto');  
  
//获取向量值  
echo '向量:';  
var_dump($m->getIV());  
  
//加密  
$b = $m->encrypt($a, 'base64');  
//解密  
$c = $m->decrypt($b, 'base64');  
  
echo '加密后:';  
var_dump($b);  
echo '解密后:';  
var_dump($c);  
  
/////////////////////////////////////////  
echo '</pre>';

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP如何编写易读的代码
Jul 10 PHP
JpGraph php柱状图使用介绍
Aug 23 PHP
php中使用DOM类读取XML文件的实现代码
Dec 14 PHP
PHP fopen 读取带中文URL地址的一点见解
Sep 25 PHP
php多重接口的实现方法
Jun 20 PHP
PHP中Session和Cookie是如何操作的
Oct 10 PHP
php获取图片信息的方法详解
Dec 10 PHP
PHP中SERIALIZE和JSON的序列化与反序列化操作区别分析
Oct 11 PHP
PHP使用 Pear 进行安装和卸载包的方法详解
Jul 08 PHP
PHP利用DWZ.CN服务生成短网址
Aug 11 PHP
PHP解密支付宝小程序的加密数据、手机号的示例代码
Feb 26 PHP
PHP实现rar解压读取扩展包小结
Jun 03 PHP
浅谈PHP中如何实现Hook机制
Nov 14 #PHP
PHP实现将几张照片拼接到一起的合成图片功能【便于整体打印输出】
Nov 14 #PHP
PHP封装的XML简单操作类完整实例
Nov 13 #PHP
PHP开发中解决并发问题的几种实现方法分析
Nov 13 #PHP
三个思路解决laravel上传文件报错:413 Request Entity Too Large问题
Nov 13 #PHP
kindeditor 加入七牛云上传的实例讲解
Nov 12 #PHP
Thinkphp5 微信公众号token验证不成功的原因及解决方法
Nov 12 #PHP
You might like
php中var_export与var_dump的区别分析
2010/08/21 PHP
9个实用的PHP代码片段分享
2015/01/22 PHP
浅谈json_encode用法
2015/03/05 PHP
php车辆违章查询数据示例
2016/10/14 PHP
浅析onsubmit校验表单时利用ajax的return false无效问题
2013/07/10 Javascript
javascript中取前n天日期的两种方法分享
2014/01/26 Javascript
javascript实现禁止右键和F12查看源代码
2014/12/26 Javascript
实现无刷新联动例子汇总
2015/05/20 Javascript
javascript:void(0)点击登录没反应怎么解决
2015/11/13 Javascript
AngularJS之自定义服务详解(factory、service、provider)
2017/04/14 Javascript
vue-cli常用设置总结
2018/02/24 Javascript
vue集成chart.js的实现方法
2019/08/20 Javascript
jquery将json转为数据字典的实例代码
2019/10/11 jQuery
ES6 Promise对象概念及用法实例详解
2019/10/15 Javascript
angular组件间通讯的实现方法示例
2020/05/07 Javascript
vue setInterval 定时器失效的解决方式
2020/07/30 Javascript
[26:24]完美副总裁、DOTA2负责人蔡玮专访:电竞如人生
2014/09/11 DOTA
bpython 功能强大的Python shell
2016/02/16 Python
在matplotlib的图中设置中文标签的方法
2018/12/13 Python
Pytorch之contiguous的用法
2019/12/31 Python
详解python内置常用高阶函数(列出了5个常用的)
2020/02/21 Python
Python Scrapy多页数据爬取实现过程解析
2020/06/12 Python
在tensorflow以及keras安装目录查询操作(windows下)
2020/06/19 Python
通过代码实例了解Python sys模块
2020/09/14 Python
如何实现一个python函数装饰器(Decorator)
2020/10/12 Python
Pretty Little Thing美国:时尚女性服饰
2018/08/27 全球购物
Nasty Gal英国:美国女性服饰销售网站
2021/03/02 全球购物
蔻驰英国官网:COACH英国
2020/07/19 全球购物
财务部副经理岗位职责
2014/03/14 职场文书
2014基层党员干部学习全国两会心得体会
2014/03/17 职场文书
优秀教导主任事迹材料
2014/05/09 职场文书
2015年中学元旦晚会活动方案
2014/12/09 职场文书
小时代观后感
2015/06/10 职场文书
初二英语教学反思
2016/02/15 职场文书
Python 多线程处理任务实例
2021/11/07 Python
SpringBoot整合Minio文件存储
2022/04/03 Java/Android