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 相关文章推荐
Apache2 httpd.conf 中文版
Nov 17 PHP
PHP is_dir() 判断给定文件名是否是一个目录
May 10 PHP
用PHP将数据导入到Foxmail的实现代码
Sep 05 PHP
PHP开发不能违背的安全规则 过滤用户输入
May 01 PHP
数据库中排序的对比及使用条件详解
Feb 23 PHP
浅谈PHP变量作用域以及地址引用问题
Dec 27 PHP
修改destoon会员公司的伪静态中的com目录的方法
Aug 21 PHP
Yii中实现处理前后台登录的新方法
Dec 28 PHP
CI框架的安全性分析
May 18 PHP
Zend Framework数据库操作技巧总结
Feb 18 PHP
php5.x禁用eval的操作方法
Oct 19 PHP
php使用redis的几种常见操作方式和用法示例
Feb 20 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中的MVC模式运用技巧
2007/05/03 PHP
php缩放gif和png图透明背景变成黑色的解决方法
2014/10/14 PHP
PHP的运行机制与原理(底层)
2015/11/16 PHP
PHP使用socket发送HTTP请求的方法
2016/02/14 PHP
php获取文件后缀的9种方法
2016/03/22 PHP
swoole锁的机制代码实例讲解
2021/03/04 PHP
javascript 一个函数对同一元素的多个事件响应
2009/07/25 Javascript
根据身份证号自动输出相关信息(籍贯,出身日期,性别)
2013/11/15 Javascript
iframe子页面与父页面在同域或不同域下的js通信
2014/05/07 Javascript
jQuery实现自动切换播放的经典滑动门效果
2015/09/12 Javascript
基于canvas实现的绚丽圆圈效果完整实例
2016/01/26 Javascript
jquery使用Cookie和JSON记录用户最近浏览历史
2016/04/19 Javascript
浅谈jQuery this和$(this)的区别及获取$(this)子元素对象的方法
2016/11/29 Javascript
js实现数据导出为EXCEL(支持大量数据导出)
2020/03/31 Javascript
Element MessageBox弹框的具体使用
2020/07/27 Javascript
jQuery实现放大镜案例
2020/10/19 jQuery
[38:54]完美世界DOTA2联赛PWL S2 Rebirth vs LBZS 第一场 11.28
2020/12/01 DOTA
Python实现获取照片拍摄日期并重命名的方法
2017/09/30 Python
解决PyCharm不运行脚本,而是运行单元测试的问题
2019/01/17 Python
pytorch自定义二值化网络层方式
2020/01/07 Python
在pycharm中关掉ipython console/PyDev操作
2020/06/09 Python
关于webview适配H5上传照片或者视频文件的方法
2020/11/04 HTML / CSS
YesStyle美国/全球:购买亚洲时装、美容化妆品和生活百货
2017/01/16 全球购物
Topman美国官网:英国著名的国际平价时尚男装品牌
2017/12/22 全球购物
圣彼得堡鲜花配送:Semicvetic
2020/09/15 全球购物
Columbia Sportswear法国官网:全球户外品牌
2020/09/25 全球购物
中职生自荐信
2013/10/13 职场文书
2014年宣传部工作总结
2014/11/12 职场文书
二审答辩状范文
2015/05/22 职场文书
汉字听写大会观后感
2015/06/12 职场文书
2015年办税服务厅工作总结
2015/07/23 职场文书
2016年教师节感言
2015/12/09 职场文书
2016年学校“3.12”植树节活动总结
2016/03/16 职场文书
Nginx Rewrite使用场景及配置方法解析
2021/04/01 Servers
正则表达式拆分url实例代码
2022/02/24 Java/Android
使用Cargo工具高效创建Rust项目
2022/08/14 Javascript