AES加解密在php接口请求过程中的应用示例

在php请求接口的时候,我们经常需要考虑的一个问题就是数据的安全性,因为数据传输过程中很有可能会被用fillder这样的抓包工具进行截获。一种比较好的解决方案就是在客户端请求发起之前先对要请求的数据进行加密,服务端api接收到请求数据后再对数据进行解密处理,返回结果给客户端的时候也对要返回的数据进行加密,客户端接收到返回数据的时候再解密。因此整个api请求过程中数据的安全性有了一定程度的提高。

今天结合一个简单的demo给大家分享一下AES加解密技术在php接口请求中的应用。

首先,准备一个AES加解密的基础类:

<?php

/**
 * 加密基础类
 */

class Crypt_AES
{
  protected $_cipher = "rijndael-128";
  protected $_mode = "cbc";
  protected $_key;
  protected $_iv = null;
  protected $_descriptor = null;

  /**
   * 是否按照PKCS #7 的标准进行填充
   * 为否默认将填充“\0”补位
   * @var boolean
   */
  protected $_PKCS7 = false;

  /**
   * 构造函数,对于密钥key应区分2进制字符串和16进制的。
   * 如需兼容PKCS#7标准,应选项设置开启PKCS7,默认关闭
   * @param string $key
   * @param mixed $iv   向量值
   * @param array $options
   */
  public function __construct($key = null, $iv = null, $options = null)
  {
    if (null !== $key) {
      $this->setKey($key);
    }

    if (null !== $iv) {
      $this->setIv($iv);
    }

    if (null !== $options) {
      if (isset($options['chipher'])) {
        $this->setCipher($options['chipher']);
      }

      if (isset($options['PKCS7'])) {
        $this->isPKCS7Padding($options['PKCS7']);
      }

      if (isset($options['mode'])) {
        $this->setMode($options['mode']);
      }
    }
  }

  /**
   * PKCS#7状态查看,传入Boolean值进行设置
   * @param boolean $flag
   * @return boolean
   */
  public function isPKCS7Padding($flag = null)
  {
    if (null === $flag) {
      return $this->_PKCS7;
    }
    $this->_PKCS7 = (bool) $flag;
  }

  /**
   * 开启加密算法
   * @param string $algorithm_directory locate the encryption
   * @param string $mode_directory
   * @return Crypt_AES
   */
  public function _openMode($algorithm_directory = "" , $mode_directory = "")
  {
    $this->_descriptor = mcrypt_module_open($this->_cipher,
                        $algorithm_directory,
                        $this->_mode,
                        $mode_directory);
    return $this;
  }

  public function getDescriptor()
  {
    if (null === $this->_descriptor) {
      $this->_openMode();
    }
    return $this->_descriptor;
  }

  protected function _genericInit()
  {
    return mcrypt_generic_init($this->getDescriptor(), $this->getKey(), $this->getIv());
  }

  protected function _genericDeinit()
  {
    return mcrypt_generic_deinit($this->getDescriptor());
  }

  public function getMode()
  {
    return $this->_mode;
  }

  public function setMode($mode)
  {
    $this->_mode = $mode;
    return $this;
  }

  public function getCipher()
  {
    return $this->_cipher;
  }

  public function setCipher($cipher)
  {
    $this->_cipher = $cipher;
    return $this;
  }
  /**
   * 获得key
   * @return string
   */
  public function getKey()
  {
    return $this->_key;
  }

  /**
   * 设置可以
   * @param string $key
   */
  public function setKey($key)
  {
    $this->_key = $key;
    return $this;
  }  

  /**
   * 获得加密向量块,如果其为null时将追加当前Descriptor的IV大小长度
   *
   * @return string
   */
  public function getIv()
  {
    if (null === $this->_iv && in_array($this->_mode, array( "cbc", "cfb", "ofb", ))) {
      $size = mcrypt_enc_get_iv_size($this->getDescriptor());
      $this->_iv = str_pad("", 16, "\0");
    }
    return $this->_iv;
  }

  /**
   * 获得向量块
   *
   * @param string $iv
   * @return Crypt_AES $this
   */
  public function setIv($iv)
  {
    $this->_iv = $iv;
    return $this;
  }  

  /**
   * 加密
   * @param string $str 被加密文本
   * @return string
   */
  public function encrypt($str){
    $td = $this->getDescriptor();
    $this->_genericInit();
    $bin = mcrypt_generic($td, $this->padding($str));
    $this->_genericDeinit();

    return $bin;
  }

  public function padding($dat)
  {
    if ($this->isPKCS7Padding()) {
      $block = mcrypt_enc_get_block_size($this->getDescriptor());

      $len = strlen($dat);
      $padding = $block - ($len % $block);
      $dat .= str_repeat(chr($padding),$padding);
    }

    return $dat;
  }

  public function unpadding($str)
  {
    if ($this->isPKCS7Padding()) {
      $pad = ord($str[($len = strlen($str)) - 1]);
      $str = substr($str, 0, strlen($str) - $pad);
    }
    return $str;
  }

  /**
   * 解密
   * @param string $str
   * @return string
   */
  public function decrypt($str){
    $td = $this->getDescriptor();

    $this->_genericInit();
    $text = mdecrypt_generic($td, $str);
    $this->_genericDeinit();

    return $this->unpadding($text);
  }

  /**
   * 16进制转成2进制数据
   * @param string $hexdata 16进制字符串
   * @return string
   */
  public static function hex2bin($hexdata)
  {
    return pack("H*" , $hexdata);
  }

  /**
   * 字符串转十六进制
   * @param string $hexdata 16进制字符串
   * @return string
   */
  public static function strToHex($string)
  {
    $hex='';
    for($i=0;$i<strlen($string);$i++)
      $hex.=dechex(ord($string[$i]));
    $hex=strtoupper($hex);
    return $hex;
  }

  /**
   * 十六进制转字符串
   * @param string $hexdata 16进制字符串
   * @return string
   */
  function hexToStr($hex)
  {
    $string='';
    for($i=0;$i<strlen($hex)-1;$i+=2)
      $string.=chr(hexdec($hex[$i].$hex[$i+1]));
    return $string;
  }
}

客户端请求部分:

<?php 

include 'AES.php';

$md5Key = 'ThisIsAMd5Key';               // 对应服务端:$md5key = 'ThisIsAMd5Key';
$aesKey = Crypt_AES::strToHex('1qa2ws4rf3edzxcv');   // 对应服务端:$aesKey = '3171613277733472663365647A786376';
$aesKey = Crypt_AES::hex2bin($aesKey);
$aesIV = Crypt_AES::strToHex('dfg452ws');       // 对应服务端:$aesIV = '6466673435327773';
$aes = new Crypt_AES($aesKey,$aesIV,array('PKCS7'=>true, 'mode'=>'cbc'));

// var_dump($aes);

$data['name'] = 'idoubi';
$data['sex']= 'male';
$data['age'] = 23;
$data['signature'] = '白天我是一个程序员,晚上我就是一个有梦想的演员。';

$content = base64_encode($aes->encrypt(json_encode($data)));
$content = urlencode($content);
$sign = md5($content.$md5Key);

$url = 'http://localhost/aesdemo/api.php';
$params = "version=1.0&sign=$sign&content=$content";

// 请求接口
post($url, $params);

/**
 * 接口请求函数
 */
function post($url, $params) {
  $curlPost= $params;
  $ch = curl_init();   //初始化curl
  curl_setopt($ch, CURLOPT_URL, $url);  //提交到指定网页
  curl_setopt($ch, CURLOPT_HEADER, 0);  //设置header
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);  //要求结果为字符串且输出到屏幕上
  curl_setopt($ch, CURLOPT_POST, 1);  //post提交方式
  curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost);
  $result = curl_exec($ch);//运行curl
  curl_close($ch);
  var_dump(json_decode($result, true));
}

接口处理逻辑:

<?php 

include 'AES.php';

$data = $_POST; // 接口请求得到的数据
$content = $data['content'];
$sign = $data['sign'];

$aesKey = '3171613277733472663365647A786376';
$aesIV = '6466673435327773';
$md5key = 'ThisIsAMd5Key';

// 校验数据
if(strcasecmp(md5(urlencode($content).$md5key),$sign) == 0) {
  // 数据校验成功
  $key = Crypt_AES::hex2bin($aesKey);
  $aes = new Crypt_AES($key, $aesIV, array('PKCS7'=>true, 'mode'=>'cbc'));

  $decrypt = $aes->decrypt(base64_decode($content));
  if (!$decrypt) {   // 解密失败
    echo json_encode('can not decrypt the data');
  } else {
    echo json_encode($decrypt);   // 解密成功
  }
} else{
  echo json_encode('data is not integrity');    // 数据校验失败
}

上述接口请求过程中定义了三个加解密需要用到的参数:$aesKey、$aesIV、$md5key,在实际应用过程中,只要与客户端用户约定好这三个参数,客户端程序员利用这几个参数对要请求的数据进行加密后再请求接口,服务端程序员在接收到数据后利用同样的加解密参数对数据进行解密,整个api请求过程中的数据就很安全了。

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

(0)

相关推荐

  • php中AES加密解密的例子小结

    aesDemo.php: 例子, 复制代码 代码如下: <?phprequire_once('./AES.php');//$aes = new AES();$aes = new AES(true);// 把加密后的字符串按十六进制进行存储//$aes = new AES(true,true);// 带有调试信息且加密字符串按十六进制存储$key = "this is a 32 byte key";// 密钥$keys = $aes->makeKey($key);$encod

  • php写的AES加密解密类分享

    今天写了一个php的AES加密类.适用于Yii的扩展. 如果不用在Yii框架中,把代码中Yii::app()->params['encryptKey'] 换成你对应的默认key就可以了. 类代码: <?php /** * php AES加解密类 * 如果要与java共用,则密钥长度应该为16位长度 * 因为java只支持128位加密,所以php也用128位加密,可以与java互转. * 同时AES的标准也是128位.只是RIJNDAEL算法可以支持128,192和256位加密. * java

  • AES加解密在php接口请求过程中的应用示例

    在php请求接口的时候,我们经常需要考虑的一个问题就是数据的安全性,因为数据传输过程中很有可能会被用fillder这样的抓包工具进行截获.一种比较好的解决方案就是在客户端请求发起之前先对要请求的数据进行加密,服务端api接收到请求数据后再对数据进行解密处理,返回结果给客户端的时候也对要返回的数据进行加密,客户端接收到返回数据的时候再解密.因此整个api请求过程中数据的安全性有了一定程度的提高. 今天结合一个简单的demo给大家分享一下AES加解密技术在php接口请求中的应用. 首先,准备一个AE

  • nodejs aes 加解密实例

    如下所示: 'use strict'; const crypto = require('crypto'); /** * AES加密的配置 * 1.密钥 * 2.偏移向量 * 3.算法模式CBC * 4.补全值 */ var AES_conf = { key: getSecretKey(), //密钥 iv: '1012132405963708', //偏移向量 padding: 'PKCS7Padding' //补全值 } /** * 读取密钥key * 更具当前客户端的版本vid.平台plat

  • Rust实现AES加解密详解

    目录 一.选择使用 rust-crypto 二.Cargo.toml 文件 三.工具类 1.加密 2.解密 3.测试样例 一.选择使用 rust-crypto rust-crypto 官方相关站点 crates.io https://crates.io/crates/rust-crypto repository https://github.com/DaGenix/rust-crypto documentation (以0.2.36为例) https://docs.rs/rust-crypto/

  • Ajax请求过程中下载文件在FireFox(火狐)浏览器下的兼容问题

    需求很简单,点击一个文件链接下载该文件,同时向后台发送请求.需求很常见,用户点击下载后通常要进行下载量的统计,统计的话可以利用 script标签 或者 img标签(图片ping) 的跨域能力,将它们的 src 属性指向统计地址,但是这次用了 ajax 进行统计,遂出现了这个问题. demo 代码如下: <a id="a" href="http://c758482.r82.cf2.rackcdn.com/Sublime Text 2.0.2 x64 Setup.exe&q

  • 为vue-router懒加载时下载js的过程中添加loading提示避免无响应问题

    用过vue-router都知道它可以实现模块js的懒加载,即只有当需要时才去加载对应模块的js脚本文件,以加速主页的显示.比如只有第一次用户点击某个"用户信息"按钮或菜单时,才下载"用户信息"这个模块的js组件. 懒加载的实现,依赖与webpack下AMD模式require函数的功能.webpack会将异步require的文件生成一个独立的js文件,调用时异步下载这个js且在完成后再执行它.开发项目中实现的关键代码是: const basicInfo = { pat

  • android中AES加解密的使用方法

    今天在android项目中使用AES对数据进行加解密,遇到了很多问题,网上也找了很多资料,也不行.不过最后还是让我给搞出来了,这里把这个记录下来,不要让别人走我的弯路,因为网上绝大多数的例子都是行不通的.好了,接下来开始讲解 1.Aes工具类 package com.example.cheng.aesencrypt; import android.text.TextUtils; import java.security.NoSuchAlgorithmException; import java.

  • Ajax在请求过程中显示进度的简单实现

    Ajax在Web应用中使用得越来越频繁.在进行Ajax调用过程中一般都具有这样的做法:显示一个GIF图片动画表明后台正在工作,同时阻止用户操作本页面(比如Ajax请求通过某个按钮触发,用户不能频繁点击该按钮产生多个并发Ajax请求):调用完成后,图片消失,当前页面运行重新编辑.以下图为例,页面中通过一个Load链接以Ajax请求的方式加载数据(左).当用户点击该链接之后,Ajax请求开始,GIF图片显示"Loading"状态,同时当前页面被"罩住"防止用户继续点击L

  • PHP 7.1中AES加解密方法mcrypt_module_open()的替换方案

    前言 mcrypt 扩展已经过时了大约10年,并且用起来很复杂.因此它被废弃并且被 OpenSSL 所取代. 从PHP 7.2起它将被从核心代码中移除并且移到PECL中. PHP手册在7.1迁移页面给出了替代方案,就是用OpenSSL取代MCrypt. 示例代码 /** * [AesSecurity aes加密,支持PHP7.1] */ class AesSecurity { /** * [encrypt aes加密] * @param [type] $input [要加密的数据] * @par

  • qq登录,新浪微博登录接口申请过程中遇到的问题

    1,qq登录接口申请 申请地址是:http://connect.opensns.qq.com/,登录进去后,点击右上方的登录.然后填写信息就行了. 我遇到的问题是在域名审核时,域名审核就是不通过,没办法我就发邮件给qq互联的客服,邮件地址是connect@qq.com.qq还是挺给力的2,3个工作日就能给你审核通过. 审核通过后,开发接口并上线,在登录http://connect.opensns.qq.com/,申请上线,如果不申请上线的话,登录个数有限制. 2,新浪微博接口申请 申请地址是:h

  • postman数据加解密实现APP登入接口模拟请求

    目录 主要使用到的Postman功能 数据加解密 各种参数设置 真正发送的数据: 请求处理脚本[Pro-request Script] 响应处理脚本[Tests] 结果的样子 主要使用到的Postman功能 环境变量:只要新建就好了,操作都是在代码中处理的. 日志查看:菜单位置:View → show postman console ,显示这个窗口视图就可以了 请求时执行的脚本:Pre-request Script 标签页,使用语言javascript, 通常作为加密. 接受返回时执行的脚本:T

随机推荐