PHP实现AES加密并使用PKCS7填充

前言

如题,最近在寻找这个实现方案,但是找到的方案都是使用 Mcrypt。然而,Mcrypt 系列函数从 PHP 7.1.0 开始就被弃用了,而我又找不到其他方案。于是我就去查阅了 PKCS7 的具体填充方式,自行实现。

Mcrypt系列函数已被弃用

介绍

PKCS7 (公钥密码学标准第 7 号)
PKCS#7 定义于 RFC 5652 (征求意见草案第 5652 号)。

每个填充字节的值是用于填充的字节数,即是说,若需要填充 N 个字节,则每个填充字节值都是 N 。 填充的字节数取决于算法可以处理的最小数据块的字节数量。

01
02 02
03 03 03
04 04 04 04
05 05 05 05 05
etc.

例:下例中,块大小为 8 字节,需要填充 4 字节。

... | DD DD DD DD DD DD DD DD | DD DD DD DD 04 04 04 04 |

以上为摘录部分,原文: PKCS7 填充

了解其具体的填充方式后,就可以着手实现了。

实现

自行编写一个填充函数。

function padPkcs7($data, $blocksize = 16)
{
    $pad = $blocksize - (strlen($data) % $blocksize);
    return $data . str_repeat(chr($pad), $pad);
}

使用示例

$plaintext = "Hello world!";
$cipher_algo = 'aes-128-ecb';
$key = '0123456789abcdef';

// PKCS7 填充
$data = padPkcs7($plaintext);

$ciphertext = openssl_encrypt($data, $cipher_algo, $key, OPENSSL_DONT_ZERO_PAD_KEY | OPENSSL_ZERO_PADDING);

后记

在评论中又提到一种方案

$plaintext = "Hello world!";
$cipher_algo = 'aes-128-ecb';
$key = '0123456789abcdef';

$ciphertext = openssl_encrypt($plaintext, $cipher_algo, $key);

实测与上面的方法结果一样,但是不知道当时为什么没用这种方案...

本文链接:

https://blog.nkxingxh.top/archives/308/
1 + 1 =
5 评论
    qazFirefox Browser 123Windows 10
    3月8日 回复

    openssl_pkcs7_encrypt 不了解下吗?

      NKXingXhChrome 122Windows 10
      3月10日 回复

      @qaz 这个函数读取输入文件并使用 RC2 40 位的密码将之加密,而我需要的是AES加密。

        qazFirefox Browser 123Windows 10
        3月11日 回复

        @NKXingXh 是我没搞清你的PHP版本、openssl版本,是我先入为主了,想当然了。
        openssl_encrypt($plain, 'AES-128-ECB', $key, OPENSSL_RAW_DATA, $iv);

        ヾ(≧∇≦*)ゝ

          NKXingXhChrome 122Windows 10
          3月11日 回复

          @qaz 目前实测了这个 $ciphertext = openssl_encrypt($plaintext, $cipher_algo, $key); 确实是可以与文中的方法得到一样的结果,但是不知道当时试了挺多为什么没发现

        qazFirefox Browser 123Windows 10
        3月11日 回复

        @NKXingXh PHP_OPENSSL_CIPHER_DEFAULT = PHP_OPENSSL_CIPHER_AES_CBC

        ୧(๑•̀⌄•́๑)૭