php接口如何openssl_encrypt 使用 aes和des ,base64加密解密总结「建议收藏」

php接口如何openssl_encrypt 使用 aes和des ,base64加密解密总结

大家好,又见面了,我是全栈君。

一、DES介绍

DES 是对称性加密里面常见一种,全称为 Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法。密钥长度是64位(bit),超过位数密钥被忽略。所谓对称性加密加密和解密密钥相同对称性加密一般会按照固定长度,把待加密字符串分成块,不足一整块或者刚好最后有特殊填充字符。

  • 跨语言做 DES 加密解密经常会出现问题,往往是填充方式不对、编码不一致或者加密解密模式没有对应上造成。
  • 常见的填充模式有: pkcs5、pkcs7、iso10126、ansix923、zero。
  • 加密模式有:DES-ECB、DES-CBC、DES-CTR、DES-OFB、DES-CFB。

加密用到的方法:

openssl_encrypt($data, $method, $password, $options, $iv)

参数说明:

  1. $data 加密明文
  2. $method 加密方法

    • DES-ECB
    • DES-CBC
    • DES-CTR
    • DES-OFB
    • DES-CFB
  3. $passwd 加密密钥[密码]
  4. $options 数据格式选项(可选)【选项有:】

    • 0
    • OPENSSL_RAW_DATA=1
    • OPENSSL_ZERO_PADDING=2
    • OPENSSL_NO_PADDING=3
  5. $iv 密初始化向量(可选)
  • 需要注意:如果method为DES-ECB,则method为DES−ECB,则iv无需填写

二、解密用到的方法:

openssl_decrypt($data, $method, $password, $options, $iv)

参数说明:

  1. $data 要解密的数据
  2. 其他参数同加密方法

三、用法案例:

参数:

   $data = '1234567887654321';//加密明文
   $method = 'DES-ECB';//加密方法
   $passwd = '12344321';//加密密钥
   $options = 0;//数据格式选项(可选)
   $iv = '';//加密初始化向量(可选)

(1) 默认填充方式:

    • 加密:

      $result = openssl_encrypt($data, $method, $passwd, $options);
      var_dump($result);

      结果:

      string(32) "kQYOdswcm9I5elv2wdJucplqAgqDNqXg"
  • 解密

    $result = 'kQYOdswcm9I5elv2wdJucplqAgqDNqXg';
    var_dump(openssl_decrypt($result, $method, $passwd, 0));

    结果:

    string(16) "1234567887654321"

(2) OPENSSL_RAW_DATA方式【会用PKCS#7进行补位】

  • 加密

    $result = openssl_encrypt($data, $method, $passwd, OPENSSL_RAW_DATA);
    var_dump($result);

    结果:

    string(24) "�v���9z[���nr�j �6��"

    我们可以看到结果是乱码的,这时我们需要base64一下

    $result = openssl_encrypt($data, $method, $passwd, OPENSSL_RAW_DATA);
    var_dump(base64_encode($result));

    这时结果是

    string(32) "kQYOdswcm9I5elv2wdJucplqAgqDNqXg"
  • 解密

    $result = openssl_encrypt($data, $method, $passwd, OPENSSL_RAW_DATA);
    
    var_dump(openssl_decrypt($result, $method, $passwd,OPENSSL_RAW_DATA));

    结果:

    string(16) "1234567887654321"

    我们可以看到:默认填充方式与OPENSSL_RAW_DATA,这两种方式加密结果是一样的

(3) OPENSSL_ZERO_PADDING方式

看字面意思,是用0填充,但是测试并不起作用

  • 加密

    $result = openssl_encrypt($data, $method, $passwd, OPENSSL_ZERO_PADDING);
    var_dump($result);

    结果:

    string(24) "kQYOdswcm9I5elv2wdJucg=="
  • 解密:

    $result = openssl_encrypt($data, $method, $passwd, OPENSSL_ZERO_PADDING);
    var_dump(openssl_decrypt($result, $method, $passwd,OPENSSL_ZERO_PADDING));

    结果:

    string(16) "1234567887654321"

(4) OPENSSL_NO_PADDING【不填充,需要手动填充】

  • 在openssl_encrypt前加上填充过程
  • 加密

      $str_padded = $data;
      if (strlen($str_padded) % 16) {
          $str_padded = str_pad($str_padded,strlen($str_padded) + 16 - strlen($str_padded) % 16, "\0");
      }
      $result = openssl_encrypt($str_padded, $method, $passwd, OPENSSL_NO_PADDING);
      var_dump($result);
      echo '<br>';
      var_dump( base64_encode($result));

    结果:

    string(16) "�v���9z[���nr" 
    string(24) "kQYOdswcm9I5elv2wdJucg=="

    我们可以看到结果是加密的乱码,需要用base64一下,就可以看到结果了

  • 解密:

     //加密begin
      $str_padded = $data;
      if (strlen($str_padded) % 16) {
          $str_padded = str_pad($str_padded,strlen($str_padded) + 16 - strlen($str_padded) % 16, "\0");
      }
      $result = openssl_encrypt($str_padded, $method, $passwd, OPENSSL_NO_PADDING);
      //加密end
     //解密begin
     $str = base64_encode($result);
     $m = openssl_decrypt( base64_decode($str) , $method, $passwd, OPENSSL_NO_PADDING);
     var_dump( rtrim( rtrim( $m,chr(0) ), chr(7) ) );
     //解密 end

    结果:

    string(16) "1234567887654321"

** 结尾要去除填充字符’0’和’a’。
‘a’是为了兼容用OPENSSL_RAW_DATA加密的结果。 **

 

补码原理

在对称加密中,可以概分为两种模式加密,流加密以及块加密,当我们使用块加密(也就是分组加密)的时候,例如AES、DES,每次是对固定大小的分组数据进行处理。但是大多数需要加密的数据并不是固定大小的倍数长度。例如AES数据块为128位,也就是16字节长度,而需要加密的长度可能为15、26等等。为了解决这个问题,我们就需要对数据进行填补操作,将数据补齐至对应块长度。

接下来呢讲一下关于数据填充ANSIX923ISO10126PKCS7以及Zero具体的补码原理。

注,补码原理来自于文章Padding (cryptography),读中文的小伙伴们可以查看这篇 关于PKCS5Padding与PKCS7Padding的区别.

  • ANSIX923 填充方式

    ANSIX923 在填充时首先获取需要填充的字节长度 = (块长度 – (数据长度 % 块长度)), 在填充字节序列中最后一个字节填充为需要填充的字节长度值, 填充字节中其余字节均填充数字零.
    例:

    假定块长度为8 ,数据长度为 10,则填充字节数等于 6,数据等于 FF FF FF FF FF FF FF FF FF DD:
    数据: FF FF FF FF FF FF FF FF FF
    X923 填充后: FF FF FF FF FF FF FF FF | FF DD 00 00 00 00 00 06
    
  • ISO10126 填充方式

    ISO10126 在填充时首先获取需要填充的字节长度 = (块长度 – (数据长度 % 块长度)), 在填充字节序列中最后一个字节填充为需要填充的字节长度值, 填充字节中其余字节均填充随机数值.
    例:

    假定块长度为 16,数据长度为 9,则填充字节数等于 7,数据等于 FF FF FF FF FF FF FF FF FF :
    
    | FF FF FF FF FF FF FF FF FF 73 68 C4 81 A6 23 07 |
    
  • PKCS7 填充方式

    PKCS7 在填充时首先获取需要填充的字节长度 = (块长度 – (数据长度 % 块长度)), 在填充字节序列中所有字节填充为需要填充的字节长度值
    例:

    假定块长度为 8,数据长度为 3,则填充字节数等于 5,数据等于 FF FF FF :
    | FF FF FF 05 05 05 05 05 |
    
  • Zero 填充方式

    Zero 在填充时首先获取需要填充的字节长度 = (块长度 – (数据长度 % 块长度)), 在填充字节序列中所有字节填充为0x00,零填充在数据最后字节为零的时候可能不可逆
    例:

    假定块长度为 8,数据长度为 2,则填充字节数等于 6,数据等于 FF FF  :
    | FF FF 00 00 00 00 00 00 |
    

特定的,为了使算法可以逆向去除多余的填充字符,所以当数据长度恰好等于块长度的时候,需要补足块长度的字节.例如块长度为8,数据长度为8,则填充字节数等于8.

 

php7 openssl_decrypt AES的ECB与CBC加解密

 

php7.2版本用openssl_encrypt代替mcrypt_encrypt,导致以往自己写的Aes加密类不能用。

    这次项目客户端用的是 AES-128-ECB 加密,我用在线AES工具来测试,发现自己写的加解密方法得到的值不一样。而最终发现是加密的key不是16位长,导致ios客户端与服务器php的加解密不一致。后商讨key为16位长,遂问题解决。下面是 AES-128-ECB 加密类;

class Aes
{
    //密钥 须是16位
    public $key ;

    /**
     * 解密字符串
     * @param string $data 字符串
     * @return string
     */
    public function __construct()
    {
    	$this->key = '1234567890123456';
    }

    public  function decode($str)
    {
        return openssl_decrypt(base64_decode($str),"AES-128-ECB",$this->key,OPENSSL_RAW_DATA);
    }

    /**
     * 加密字符串
     * @param string $data 字符串
     * @return string
     */
    public  function encode($str)
    {
        return base64_encode(openssl_encrypt($str,"AES-128-ECB",$this->key,OPENSSL_RAW_DATA));
    }

}

若你是采用CBC加密,则还需排序$iv偏移量,如下面是AES-128-CBC加解密类:

class Aes
{
    //密钥 须是16位
    public $key ;

    //偏移量
    public $iv = '1234567890123456';

    /**
     * 解密字符串
     * @param string $data 字符串
     * @return string
     */
    public function __construct()
    {
    	$this->key = '1234567890123456';
    }

    public  function decode($str)
    {
        return openssl_decrypt(base64_decode($str),"AES-128-CBC",$this->key,OPENSSL_RAW_DATA, $this->iv);
    }

    /**
     * 加密字符串
     * @param string $data 字符串
     * @return string
     */
    public  function encode($str)
    {
        return base64_encode(openssl_encrypt($str,"AES-128-CBC",$this->key,OPENSSL_RAW_DATA, $this->iv));
    }

}

参考:  https://www.jianshu.com/p/7b6f5aaa7680

 https://my.oschina.net/u/3403514/blog/1809008

参考:https://segmentfault.com/a/1190000016804661

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/111596.html原文链接:https://javaforall.net

(0)
上一篇 2022年2月18日 下午12:00
下一篇 2022年2月18日 下午1:00


相关推荐

  • 【喂饭级教程】逆天开源工具解放Claude Code模型:丝滑高效使用指南,带你轻松上手!

    【喂饭级教程】逆天开源工具解放Claude Code模型:丝滑高效使用指南,带你轻松上手!

    2026年3月16日
    2
  • 奔图m7160dw驱动_奔图打印机m7100dn

    奔图m7160dw驱动_奔图打印机m7100dn奔图M7100dW打印机驱动是专门为奔图旗下的M7100dW型号打印机打造的驱动程序。它能够为你解决打印机常见的无法扫描、无法识别等问题。他是连接打印机与电脑的桥梁,让你更好的操作这款的打印机。【打印机特色】1、操作便捷,乐在其中ECOSYSP2135dn外观小巧,空间适应度很高,可以更好地满足用户办公空间布置的需要。而且外形美观,放置在办公桌上能够与办公家具很好地融合在一起,营造出和谐的办公室…

    2022年8月30日
    5
  • 前端报错400

    前端报错400前端报错400看控制台报错:Resolved[org.springframework.web.method.annotation.MethodArgumentTypeMismatchException:Failedtoconvertvalueoftype’java.lang.String’torequiredtype’java.util.Date’;nestede…

    2022年6月11日
    87
  • 实验5 振幅调制(集成乘法器幅度调制电路)

    实验5 振幅调制(集成乘法器幅度调制电路)目录 5 1 振荡调制的基本工作原理一 振幅调制和调幅波 1 普通调幅波 AM 1 调幅波的表达式 波形 2 调幅波的频谱 2 抑制载波双边带调幅 DSB 3 抑制载波单边带调幅 SSB 二 普通调幅波的产生电路三 抑制载波调幅的产生电路 5 2 振幅调制实验电路 5 1 振荡调制的基本工作原理根据电磁波理论知道 只有频率较高的振荡才能被天线有效地辐射 但是人的讲话声音变换为相应电信号的频率较低 不适于直接从天线上辐射 因此 为了传递信息 就必须将要传递的信息 记载 到高频振荡上去 这一 记载 过程称为调

    2026年3月16日
    2
  • 算法 – 堆排序(C#)

    算法 – 堆排序(C#)分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net/**堆排序是一种选择排序,时间复杂度为O(nlog&lt;sub&gt;2&lt;/sub&gt;n)。**堆排序的特点是:*在排序过程中,将待排序数组看成是一棵完全二叉树的顺序存储结构,*利用完全二叉树中父结点和…

    2022年7月12日
    20
  • 向量点乘 和 叉乘

    向量点乘 和 叉乘向量点乘点乘结果是一个标量 并满足交换律向量 a ax ay 向量 b bx by a b ax bx ay by a b cosA A 为两向量的夹角 几何意义 点乘结果描述了两个向量的 相似 程度 点乘结果越大 两向量越相近 点乘对零向量的解释是 零向量和其它任意向量都垂直 a b0 0 方

    2026年3月17日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号