java/AES/GCM/NOPadding解密/php实现求助

1. 运行环境

操作系统:winodws

PHP 版本:php8.0

2). java解密代码:

//package org.jeecg.common.util;

//import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.security.Security;
import java.util.Base64;
import java.util.Collection;
import java.util.Map;

/**
 */
public class AesUtil {
    private static final String DEFAULT_ENCODING = "UTF-8";
    private static final String DEFAULT_CIPHERGCM_ALGORITHM = "AES/GCM/NOPadding";
    private static final String IV = "0123456789ABCDEF";

    public static void main(String[] args) {
        String data ="JgtXJttQbvu7P6gB3tjHyiCoXhMrbZBkrUP_AWlp-8u6ycNV2pttDFwiCYoKHDohjKqksgiwGiYQGxn-ZCJ14HTTR2cOcIjZ7KX-KcVwp6LpvYfSE7tKB9gh4aUHs-tJaJ62TUZbyQ_AOkyk8p94OeHnY19gOY1wLhdHhy3JHhdSiQEhsxm2aFgAouy3Od6rnM5miOvFpVyeiRSB8Dcy6A3h-y0DpWgyxs5pRVoSOLaniX0olp0ZRkiCv58oXzw55XX4F4W3YfNmFNz0qu63i5gdOOfocTMXpX8U45Di_pBEv3ww48dsWLw2ZCEe-blsUe--fKmsNkrk";
        String key="XS3exkfPb1uh1c47";
        try {
            String oldData = decryptFromBase64(data,key);
            System.out.println(oldData);
        }catch (Exception e){
            System.out.println("错误:"+e.getMessage());
        }
    }

    /**
     * 解密
     *
     * @param data 待解密内容
     * @param key  解密密钥
     * @return
     */
    public static byte[] decrypt(byte[] data, byte[] key) {
        notEmpty(data, "data");
        notEmpty(key, "key");
        if (key.length != 16) {
            throw new RuntimeException("Invalid AES key length (must be 16 bytes)");
        }
        if (Security.getProvider("BC") == null) {
            Security.addProvider(new BouncyCastleProvider());
        }
        try {
            SecretKeySpec seckey = new SecretKeySpec(key, "AES");
            IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes(DEFAULT_ENCODING));
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHERGCM_ALGORITHM, "BC");
            cipher.init(Cipher.DECRYPT_MODE, seckey, ivspec);
            return cipher.doFinal(data);
        } catch (Exception e) {
            System.out.println(new String(e.getMessage()));
            throw new RuntimeException("decrypt fail!", e);
        }
    }

//    static {
//        Security.addProvider(new BouncyCastleProvider());
//    }
//       static{
//         if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null){
//            System.out.println("security provider BC not found");
//            Security.addProvider(new BouncyCastleProvider());
//        }
//       }
    public static String decryptFromBase64(String data, String key) throws UnsupportedEncodingException{
        byte[] originalData = Base64.getUrlDecoder().decode(data);
//        System.out.println(new String(originalData));
        byte[] valueByte = decrypt(originalData, key.getBytes(DEFAULT_ENCODING));
        return new String(valueByte, DEFAULT_ENCODING);
    }

    public static void notEmpty(Object obj, String message) {
        if (obj == null){
            throw new IllegalArgumentException(message + " must be specified");
        }
        if (obj instanceof String && obj.toString().trim().length()==0){
            throw new IllegalArgumentException(message + " must be specified");
        }
        if (obj.getClass().isArray() && Array.getLength(obj)==0){
            throw new IllegalArgumentException(message + " must be specified");
        }
        if (obj instanceof Collection && ((Collection)obj).isEmpty()){
            throw new IllegalArgumentException(message + " must be specified");
        }
        if (obj instanceof Map && ((Map)obj).isEmpty()){
            throw new IllegalArgumentException(message + " must be specified");
        }
    }

}

测试正确解出json数据;

3). php解码

$key = 'XS3exkfPb1uh1c47';
            $sStr = 'JgtXJttQbvu7P6gB3tjHyiCoXhMrbZBkrUP_AWlp-8u6ycNV2pttDFwiCYoKHDohjKqksgiwGiYQGxn-ZCJ14HTTR2cOcIjZ7KX-KcVwp6LpvYfSE7tKB9gh4aUHs-tJaJ62TUZbyQ_AOkyk8p94OeHnY19gOY1wLhdHhy3JHhdSiQEhsxm2aFgAouy3Od6rnM5miOvFpVyeiRSB8Dcy6A3h-y0DpWgyxs5pRVoSOLaniX0olp0ZRkiCv58oXzw55XX4F4W3YfNmFNz0qu63i5gdOOfocTMXpX8U45Di_pBEv3ww48dsWLw2ZCEe-blsUe--fKmsNkrk';
            $sStr = strtr($sStr, '_-', '/+');
            $sStr = base64_decode($sStr);
            $iv = '0123456789ABCDEF';//创建指定长度的向量
            $tag = '';
            $da = openssl_decrypt($sStr, 'aes-128-gcm', $key, OPENSSL_RAW_DATA, $iv,$tag);
            \dump($da);

解码失败,用了其它的aes-256-ctr/ aes-128-ctr 等都无效,麻烦懂java与php解密互通的高手给个指导一下,谢谢

4).排查过程

通过新建java加密代码与php加密测试,发现php总是少后面16位,应解密也是那16位的关键,

加密字符:

lw112190测试信息{id:1,test:2,cd:3}

php代码:

$str = 'lw112190测试信息{id:1,test:2,cd:3}';
            $key = 'XS3exkfPb1uh1c47';
            $iv = '0123456789ABCDEF';//创建指定长度的向量
            $tag = '';
            $pass = openssl_encrypt($str, "aes-128-gcm", $key, OPENSSL_RAW_DATA, $iv, $tag);
            $base64 = base64_encode($pass);
            \dump($base64);

结果值:```
MV4FeI0EdfFtpgGMH28ZRK1sss83Js4w6QPnSDh5oI33iJ0Uy5M=

java加密代码:
```java
       String key="XS3exkfPb1uh1c47";
        String encrypt = encrypt("lw112190测试信息{id:1,test:2,cd:3}",key);
        System.out.println(encrypt);


public static String encrypt(String value,String key) {
        try {
            IvParameterSpec iv = new IvParameterSpec(IV.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
            if (Security.getProvider("BC") == null) {
                Security.addProvider(new BouncyCastleProvider());
            }
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHERGCM_ALGORITHM,"BC");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

            byte[] encrypted = cipher.doFinal(value.getBytes());
            return Base64.getUrlEncoder().encodeToString(encrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

结果值:MV4FeI0EdfFtpgGMH28ZRK1sss83Js4w6QPnSDh5oI33iJ0Uy5PxzwQ53WIhJJwaJcYvp7zP java加密前要多出一个16位字符串,由于不清楚java的加密原理,有知道的看一下代码麻烦帮看看另一个16位字符串是什么,特别感谢。高手位有空解解。

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
最佳答案
1年前 评论
xini2603 (楼主) 1年前
xini2603 (楼主) 1年前
讨论数量: 13

可以看下这个 博客:关于php rsa加密处理 不确定能不能帮到你

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

用chatGtp查了下 哈哈哈

下面是使用 PHP 实现的代码:

<?php
require_once('vendor/autoload.php');
use phpseclib\Crypt\AES;

class AesUtil {

    private const DEFAULT_ENCODING = "UTF-8";
    private const DEFAULT_CIPHERGCM_ALGORITHM = "AES/GCM/NOPADDING";
    private const IV = "0123456789ABCDEF";

    public static function decrypt($data, $key) {
        self::notEmpty($data, "data");
        self::notEmpty($key, "key");
        if (strlen($key) != 16) {
            throw new Exception("Invalid AES key length (must be 16 bytes)");
        }
        $cipher = new AES(AES::MODE_GCM, AES::DIR_DECRYPT);
        $cipher->setKey($key);
        $cipher->setIV(self::IV);
        $cipher->setTag($data, -16);
        $cipher->setAAD(self::IV);
        $ciphertext = substr($data, 0, -16);
        return $cipher->decrypt($ciphertext);
    }

    public static function decryptFromBase64($data, $key) {
        $originalData = base64_decode($data);
        $valueByte = self::decrypt($originalData, $key);
        return mb_convert_encoding($valueByte, self::DEFAULT_ENCODING);
    }

    private static function notEmpty($obj, $message) {
        if (is_null($obj)) {
            throw new Exception($message . " must be specified");
        }
        if (is_string($obj) && trim($obj) === '') {
            throw new Exception($message . " must be specified");
        }
        if (is_array($obj) && count($obj) === 0) {
            throw new Exception($message . " must be specified");
        }
        if (is_object($obj) && count(get_object_vars($obj)) === 0) {
            throw new Exception($message . " must be specified");
        }
    }
}

$data = "JgtXJttQbvu7P6gB3tjHyiCoXhMrbZBkrUP_AWlp-8u6ycNV2pttDFwiCYoKHDohjKqksgiwGiYQGxn-ZCJ14HTTR2cOcIjZ7KX-KcVwp6LpvYfSE7tKB9gh4aUHs-tJaJ62TUZbyQ_AOkyk8p94OeHnY19gOY1wLhdHhy3JHhdSiQEhsxm2aFgAouy3Od6rnM5miOvFpVyeiRSB8Dcy6A3h-y0DpWgyxs5pRVoSOLaniX0olp0ZRkiCv58oXzw55XX4F4W3YfNmFNz0qu63i5gdOOfocTMXpX8U45Di_pBEv3ww48dsWLw2ZCEe-blsUe--fKmsNkrk";
$key = "XS3exkfPb1uh1c47";

try {
    $oldData = AesUtil::decryptFromBase64($data, $key);
    echo $oldData;
} catch (Exception $e) {
    echo "错误: " . $e->getMessage();
}
?> 
请注意,在上面的代码中,我使用了phpseclib库提供的AES加密解密功能,需要使用Composer安装。你需要在你的
1年前 评论
xini2603 (楼主) 1年前
哪吒的狗腿子 (作者) 1年前
xini2603 (楼主) 1年前

file

1年前 评论
xini2603 (楼主) 1年前
<?php

class AesUtil {
    const DEFAULT_ENCODING = 'UTF-8';
    const DEFAULT_CIPHERGCM_ALGORITHM = 'AES/GCM/NOPadding';
    const IV = '0123456789ABCDEF';

    /**
     * 解密
     *
     * @param $data 待解密内容
     * @param $key  解密密钥
     * @return string 解密后的字符串
     * @throws Exception
     */
    public static function decryptFromBase64($data, $key) {
        self::notEmpty($data, 'data');
        self::notEmpty($key, 'key');
        if (strlen($key) != 16) {
            throw new RuntimeException('Invalid AES key length (must be 16 bytes)');
        }
        if (!in_array('gcm', openssl_get_cipher_methods())) {
            throw new RuntimeException('GCM cipher is not available in your PHP installation');
        }
        try {
            $originalData = base64_decode($data, true);
            $valueByte = openssl_decrypt($originalData, self::DEFAULT_CIPHERGCM_ALGORITHM, $key, OPENSSL_RAW_DATA, self::IV);
            return $valueByte;
        } catch (Exception $e) {
            throw new RuntimeException('decrypt fail!', $e->getCode(), $e);
        }
    }

    public static function notEmpty($obj, $message) {
        if (is_null($obj)) {
            throw new InvalidArgumentException($message . ' must be specified');
        }
        if (is_string($obj) && trim($obj) === '') {
            throw new InvalidArgumentException($message . ' must be specified');
        }
        if (is_array($obj) && count($obj) === 0) {
            throw new InvalidArgumentException($message . ' must be specified');
        }
        if (is_object($obj) && count(get_object_vars($obj)) === 0) {
            throw new InvalidArgumentException($message . ' must be specified');
        }
    }
}

$data = "JgtXJttQbvu7P6gB3tjHyiCoXhMrbZBkrUP_AWlp-8u6ycNV2pttDFwiCYoKHDohjKqksgiwGiYQGxn-ZCJ14HTTR2cOcIjZ7KX-KcVwp6LpvYfSE7tKB9gh4aUHs-tJaJ62TUZbyQ_AOkyk8p94OeHnY19gOY1wLhdHhy3JHhdSiQEhsxm2aFgAouy3Od6rnM5miOvFpVyeiRSB8Dcy6A3h-y0DpWgyxs5pRVoSOLaniX0olp0ZRkiCv58oXzw55XX4F4W3YfNmFNz0qu63i5gdOOfocTMXpX8U45Di_pBEv3ww48dsWLw2ZCEe-blsUe--fKmsNkrk";
$key = "XS3exkfPb1uh1c47";

try {
    $oldData = AesUtil::decryptFromBase64($data, $key);
    echo $oldData . "\n";
} catch (Exception $e) {
    echo "错误:" . $e->getMessage() . "\n";
}
1年前 评论
xini2603 (楼主) 1年前

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