PHP 实现 AES-128-CBC-PKCS5Padding 加密

  • 最近在工作中负责对接 API,数据接⼝交互过程中,不可避免会有⼀些敏感数据的传输,为了使数据交互更加安全,因此对数据进行加密。对方的要求是对接口的业务数据进行 AES-128-CBC-PKCS5Padding 加密,然后再做 Base64编码将得到的最终字符串进行提交,也给到了加密方式对应的密钥(key)和初始化向量(偏移量)。

  • 首先看到这个加密方式之后,就在PHP函数库中进行寻找,看看有没有对应的加密函数,然而找了一圈下来,发现并没有,需要自己实现,后了解到可以用 mcrypt 函数扩展实现,但是 mcrypt函数 自 PHP 7.1.0 起就废弃了,强烈建议不要使用本函数,只好再寻找其他加密函数库,在手册的下方看到了 OpenSSL 函数,通过了解 openssl_encrypt(加密数据) 函数发现可以实现需求,openssl_encrypt 具体的使用方法请自行看手册,

  • 实现函数如下:

      function encrypt($input, $key, $iv){
          return base64_encode(openssl_encrypt($input, 'AES-128-CBC', $key, OPENSSL_RAW_DATA,$iv));
      }
    
      // 解密
      function decrypt($input, $key, $iv){
          return openssl_decrypt(base64_decode($input), 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
      }
    
      // 测试加密 (我这里用的是json字符串)
      $dataJson = '[{"Code": "123123", "Name": "Bob", "Address": "\u94f6\u5ddd\u5e02"}, {"Code": "464776", "Name": "Hello", "Address": "\u5317\u4eac\u5e02"}]';
      print_r(encrypt($dataJson, $key, $iv));
      //u9Bd8oHXDGvjZcTIX9HK1r1q+aSu+/48gsfoGVrxoScZuX8yaj/xco8F2yHt2T987JNHil9LwjAmu9o5NJaicWQDaiKwMD5o70k1A9bGjDd71xb4hXRx3ddZwI85oTQQEUQLadR5C759SdaN8AOxlzH+yGlAWTOaEleulKoRTwaknG1NCM/qIRQ8gI5lzv+D
    
      // 测试解密
      $strr = 'u9Bd8oHXDGvjZcTIX9HK1r1q+aSu+/48gsfoGVrxoScZuX8yaj/xco8F2yHt2T987JNHil9LwjAmu9o5NJaicWQDaiKwMD5o70k1A9bGjDd71xb4hXRx3ddZwI85oTQQEUQLadR5C759SdaN8AOxlzH+yGlAWTOaEleulKoRTwaknG1NCM/qIRQ8gI5lzv+D';
      print_r(decrypt($strr, $key, $iv));
      // [{"Code": "123123", "Name": "Bob", "Address": "\u94f6\u5ddd\u5e02"}, {"Code": "464776", "Name": "Hello", "Address": "\u5317\u4eac\u5e02"}]
  • 自测通过,一脸得意地坐等联调。然后开始写其他业务去了,过了几天,结果一联调发现我加密的对方无法解密,对方加密的我无法解密,加密算法不匹配(挠头中。经过Google搜索相关问题,发现一句话,大概的意思就是说,在废弃的 mcrypt加密库中,128实际上指的是块大小而不是密钥大小,但是在 openssl 中的 aes-128-cbc 的128 指的是密钥大小,也就是说,在使用有效的256位密钥时,它们都是aes-256,而如果要把 mcrypt 转为 openssl 的加密方式,mcrypt 的128 需要写成 openssl 的 256 ,于是抱着试试看的态度,更改了一下 aes-128-cbc 为 aes-256-cbc,然后进行调试,最后发现联调通过了。不过具体的技术细节原理还不是很明白,先这样子修改使用,以后有时间再研究吧。

> **解决的方案,是把加密方式 AES-128-CBC 替换成 AES-256-CBC**
本作品采用《CC 协议》,转载必须注明作者和本文链接
微信搜索:上帝喜爱笨人
讨论数量: 5

这么详细的避坑攻略,为嘛没人回复点赞呢? 我来个大大的👍

1年前 评论
Aliliin (楼主) 1年前

今天也碰到这个问题,问下PCKS5在哪里体现的?

1年前 评论
Aliliin (楼主) 1年前
在php 中 aes-128-cbc
  • AES: 分组长度是固定的128位.这个是重点AES块固定的就是128和后面的128没有关系
  • 128:指定的是密钥长度 128 16位的key 192: 24位的key 256 32位的key
  • cbc:密码分组链接模式
  • 根据官方文档说明 在加密的时候会他会自动处理key的位数。如果要对接别人的加密文档,需要根据key的长度来确定加密解密的方式。 file
8个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!