gpt4 book ai didi

java - 我如何加密和解密在 PHP 和 JAVA 之间使用 AES/GCM/

转载 作者:行者123 更新时间:2023-12-03 18:59:35 27 4
gpt4 key购买 nike

我用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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com