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位字符串是什么,特别感谢。高手位有空解解。
www.saoniuhuo.com/question/detail-... 看看这个