- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我用PHP加密用AES/GCM和JAVA通信,但是不行。代码是这样的。不知道哪里错了?
<?php
$key = "123456789012345678901234567890";
$plaintext = "aaaaaaa";
$encryptStr = aesGcmEncrypt($plaintext, $key);
echo "加密后:" . $encryptStr;
function aesGcmEncrypt($plaintext, $key)
{
$ivlen = openssl_cipher_iv_length($cipher = "aes-128-gcm");
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, OPENSSL_NO_PADDING, $iv, $tag);
$ciphertext = base64_encode($iv . $ciphertext_raw . $tag);
return $ciphertext;
}
function decrypt($str, $key)
{
$encrypt = base64_decode($str);
$ivlen = openssl_cipher_iv_length($cipher = "aes-128-gcm");
$tag_length = 16;
$iv = substr($encrypt, 0, $ivlen);
$tag = substr($encrypt, -$tag_length);
$ciphertext = substr($encrypt, $ivlen, -$tag_length);
$ciphertext_raw = openssl_decrypt($ciphertext, $cipher, $key, OPENSSL_NO_PADDING, $iv, $tag);
return $ciphertext_raw;
}
这是java代码。
private static String aesGcmEncrypt(String content, byte[] key) {
try {
System.out.println(content);
System.out.println(content.getBytes(UTF_8).length);
// 根据指定算法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);
String ss = Base64.getEncoder().encodeToString(message);
return ss;
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
| BadPaddingException e) {
return null;
}
}
JAVA代码不能修改,因为不是我的,必须适应java代码。
最佳答案
这两个代码的行为可能与您预期的不同。
在 Java 代码中根本没有使用填充,尽管指定了 PKCS5Padding
(在 Java 中是 PKCS7Padding 的同义词)。 SunJCE 提供程序为 GCM 禁用指定的 PKCS5Padding
并应用 NoPadding
。这很有用,因为 GCM 是一种不需要填充的流密码模式。
应该提到的是,该行为取决于版本。只有较早的 JDK 版本(例如 8、11、12)接受 GCM 的 PKCS5Padding
并将其作为 NoPadding
运行。相比之下,更高的 JDK 版本(例如 14、15)会引发异常。此外,其他提供者的行为可能有所不同。
在 PHP 代码中,密文由 openssl_encrypt
作为原始数据返回,因此只进行一次 Base64 编码(即在与 IV 和标签连接后),这是应该的。因此,代码的行为就像设置了标志 OPENSSL_RAW_DATA
一样。这是因为使用了 OPENSSL_NO_PADDING
(值为3),它实际上只是为非对称加密定义的,而不是为对称加密定义的,因此根本不应该在这里应用。对称加密的标志是 OPENSSL_RAW_DATA
(值为 1)和 OPENSSL_ZERO_PADDING
(值为 2),因此 OPENSSL_NO_PADDING
等价于 OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
,从而隐式设置 OPENSSL_RAW_DATA
。
请注意,OPENSSL_ZERO_PADDING
不会启用零填充,但会禁用默认的 PKCS7 填充。与 SunJCE Provider 类似,openssl 也隐式禁用 GCM 的默认 PKCS7 填充,即无论是否设置 OPENSSL_ZERO_PADDING
,GCM 都不使用填充。
总之,可以说填充和标志被排除为错误的原因:在两个代码中都没有应用填充,在 PHP 代码中设置了 OPENSSL_RAW_DATA
。
不幸的是,您没有描述错误,所以只能猜测。问题可能是由不兼容的 key 引起的,因为这两个代码都可以在我的机器上运行并且兼容。
正如评论中已经提到的,对于 AES-128/192/256,必须使用 16/24/32 字节的 key 。在 Java 代码中, key 的长度决定了 AES 变体,例如长度为16 字节意味着 AES-128。在 PHP 代码中,必须明确指定 AES 变体,例如aes-128-gcm
。太长的键被简单地切断,太短的键用 0 值填充。
例如,如果在 Java 代码中使用 16 字节的 key 进行加密(AES-128),在 PHP 代码中使用 aes-128-gcm
并应用相同的 key 进行解密,则解密成功。
如有其他问题,请贴出使用的Java版本、错误信息以及完整的样本数据,即 key 、明文和密文。
样本数据:
Plaintext (UTF8): The quick brown fox jumps over the lazy dog
Key (UTF8): 0123456789012345
Java 代码提供(在 JDK 11 下)以下密文(由于随机生成的 IV,每个加密当然不同):
Ciphertext (Base64): 8DcD/QwKeFG1u2N1ve3mtsX1Lq7js33ESTigT2GH6Lrqrckh5I4qzkJMG3rnuJ9CSFZ1jai8LTChe3tuIJSMLmMTbUQ9mB0=
IV (hex): f03703fd0c0a7851b5bb6375
这个密文可以通过 PHP
decrypt
方法使用
aes-128-cbc
和上面的 key 解密:
print(decrypt("8DcD/QwKeFG1u2N1ve3mtsX1Lq7js33ESTigT2GH6Lrqrckh5I4qzkJMG3rnuJ9CSFZ1jai8LTChe3tuIJSMLmMTbUQ9mB0=", "0123456789012345") . "\n");
因此
aesGcmEncrypt
返回相同的密文,如果
aes-128-cbc
,上面的 key 和相同的 IV 被使用(对于后者,PHP 代码中随机生成的 IV 必须替换为 Java 代码中生成的 IV,当然仅用于此测试) :
$iv = hex2bin('f03703fd0c0a7851b5bb6375'); // IV to use in aesGcmEncrypt
print(aesGcmEncrypt("The quick brown fox jumps over the lazy dog", "0123456789012345") . "\n");
关于java - 我如何加密和解密在 PHP 和 JAVA 之间使用 AES/GCM/,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65178776/
我在 JavaScript 文件中运行 PHP,例如...... var = '';). 我需要使用 JavaScript 来扫描字符串中的 PHP 定界符(打开和关闭 PHP 的 )。 我已经知道使
我希望能够做这样的事情: php --determine-oldest-supported-php-version test.php 并得到这个输出: 7.2 也就是说,php 二进制检查 test.
我正在开发一个目前不使用任何框架的大型 php 站点。我的大问题是,随着时间的推移慢慢尝试将框架融入应用程序是否可取,例如在创建的新部件和更新的旧部件中? 比如所有的页面都是直接通过url服务的,有几
下面是我的源代码,我想在同一页面顶部的另一个 php 脚本中使用位于底部 php 脚本的变量 $r1。我需要一个简单的解决方案来解决这个问题。我想在代码中存在的更新查询中使用该变量。 $name)
我正在制作一个网站,根据不同的情况进行大量 PHP 重定向。就像这样...... header("Location: somesite.com/redirectedpage.php"); 为了安全起见
我有一个旧网站,我的 php 标签从 因为短标签已经显示出安全问题,并且在未来的版本中将不被支持。 关于php - 如何避免在 php 文件中写入
我有一个用 PHP 编写的配置文件,如下所示, 所以我想用PHP开发一个接口(interface),它可以编辑文件值,如$WEBPATH , $ACCOUNTPATH和 const值(value)观
我试图制作一个登录页面来学习基本的PHP,首先我希望我的独立PHP文件存储HTML文件的输入(带有表单),但是当我按下按钮时(触发POST到PHP脚本) )我一直收到令人不愉快的错误。 我已经搜索了S
我正在寻找一种让 PHP 以一种形式打印任意数组的方法,我可以将该数组作为赋值包含在我的(测试)代码中。 print_r 产生例如: Array ( [0] => qsr-part:1285 [1]
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: What is the max key size for an array in PHP? 正如标题所说,我想知道
我正在寻找一种让 PHP 以一种形式打印任意数组的方法,我可以将该数组作为赋值包含在我的(测试)代码中。 print_r 产生例如: Array ( [0] => qsr-part:1285 [1]
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
我在 MySQL 数据库中有一个表,其中存储餐厅在每个工作日和时段提供的菜单。 表结构如下: i_type i_name i_cost i_day i_start i_
我有两页。 test1.php 和 test2.php。 我想做的就是在 test1.php 上点击提交,并将 test2.php 显示在 div 中。这实际上工作正常,但我需要向 test2.php
我得到了这个代码。我想通过textarea更新mysql。我在textarea中回显我的MySQL,但我不知道如何更新它,我应该把所有东西都放进去吗,因为_GET模式没有给我任何东西,我也尝试_GET
首先,我是 php 的新手,所以我仍在努力学习。我在 Wordpress 上创建了一个表单,我想将值插入一个表(data_test 表,我已经管理了),然后从 data_test 表中获取所有列(id
我有以下函数可以清理用户或网址的输入: function SanitizeString($var) { $var=stripslashes($var); $va
我有一个 html 页面,它使用 php 文件查询数据库,然后让用户登录,否则拒绝访问。我遇到的问题是它只是重定向到 php 文件的 url,并且从不对发生的事情提供反馈。这是我第一次使用 html、
我有一个页面充满了指向 pdf 的链接,我想跟踪哪些链接被单击。我以为我可以做如下的事情,但遇到了问题: query($sql); if($result){
我正在使用 从外部文本文件加载 HTML/PHP 代码 $f = fopen($filename, "r"); while ($line = fgets($f, 4096)) { print $l
我是一名优秀的程序员,十分优秀!