PHP aes-128-gcm加密方式

需求背景:在做游戏防沉迷操作中,需要先做前置的接口验证过程,在文档中示例中,给出的是java代码

/**
     * <p>@title aesGcmEncrypt</p>
     * <p>@description Aes-Gcm加密</p>
     *
     * @param content 待加密文本
     * @param key     密钥
     * @return java.lang.String
     */
    private static String aesGcmEncrypt(String content, byte[] key) {
        try {
            // 根据指定算法ALGORITHM自成密码器
            Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5Padding");
            SecretKeySpec skey = new SecretKeySpec(key, "AES");
            cipher.init(Cipher.ENCRYPT_MODE, skey);
            //获取向量
            byte[] ivb = cipher.getIV();
            byte[] encodedByteArray = cipher.doFinal(content.getBytes(UTF_8));
            byte[] message = new byte[ivb.length + encodedByteArray.length];
            System.arraycopy(ivb, 0, message, 0, ivb.length);
            System.arraycopy(encodedByteArray, 0, message, ivb.length, encodedByteArray.length);
            return Base64.getEncoder().encodeToString(message);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
                | BadPaddingException e) {
            //建议自行调整为日志输出或抛出异常
            return null;
        }
    }

    /**
     * <p>@title aesGcmDecrypt</p>
     * <p>@description Aes-Gcm解密</p>
     *
     * @param content 带解密文本
     * @param key     密钥
     * @return java.lang.String
     */
    private static String aesGcmDecrypt(String content, byte[] key) {
        try {
            // 根据指定算法ALGORITHM自成密码器
            Cipher decryptCipher = Cipher.getInstance("AES/GCM/NoPadding");
            SecretKeySpec skey = new SecretKeySpec(key, "AES");
            byte[] encodedArrayWithIv = Base64.getDecoder().decode(content);
            GCMParameterSpec decryptSpec = new GCMParameterSpec(128, encodedArrayWithIv, 0, 12);
            decryptCipher.init(Cipher.DECRYPT_MODE, skey, decryptSpec);
            byte[] b = decryptCipher.doFinal(encodedArrayWithIv, 12, encodedArrayWithIv.length - 12);
            return new String(b, UTF_8);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
                | BadPaddingException | InvalidAlgorithmParameterException e) {
            //建议自行调整为日志输出或抛出异常
            return null;
        }
    }

 

本人不是很懂java所以这个代码也是看的云里雾里的,然后我就用PHP的 openssl_encrypt()方法做了相同的加密方式(本方法支持PHP7.1+)

如下

private function aesGcm($data)
    {

        $key = self::SECRETKEY;
      
        $cipher = "aes-128-gcm";
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = openssl_random_pseudo_bytes($ivlen);
        $encrypt = openssl_encrypt($data, $cipher, $key, OPENSSL_RAW_DATA,$iv,$tag);
        return base64_encode(($iv.$encrypt.$tag));
    }

然后测试网站一直提示测试无法通过。

通过一系列操作终于发现 需要将$key转成ASC||。

最后的代码PHP代码段:

private function aesGcm($data)
    {

        $key = self::SECRETKEY;
        $key = hex2bin($key);
        $cipher = "aes-128-gcm";
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = openssl_random_pseudo_bytes($ivlen);
        $encrypt = openssl_encrypt($data, $cipher, $key, OPENSSL_RAW_DATA,$iv,$tag);
        return base64_encode(($iv.$encrypt.$tag));
    }

 

PHP7.1以下的请参考 :https://github.com/Spomky-Labs/php-aes-gcm

public function aesGcmEncrypt($string)
    {
        $cipher = strtolower('AES-128-GCM');
        if(is_array($string)) $string = json_encode($string);
        //二进制key
        $skey = hex2bin($this->secretKey);
        //二进制iv
        $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));
        require APPPATH . 'vendor/autoload.php';
        list($content, $tag) = AESGCM::encrypt($skey, $iv, $string);
        //如果环境是php7.1+,直接使用下面的方式
//         $tag = NULL;
//         $content = openssl_encrypt($string, $cipher, $skey,OPENSSL_RAW_DATA,$iv,$tag);
        $str = bin2hex($iv) .  bin2hex($content) . bin2hex($tag);
        return base64_encode(hex2bin($str));
    }

如有不懂 请加QQ群一起讨论 :789235512

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 37
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值