使用 PHP OpenSSL 将 Java AES/ECB/PKCS7Padding/ 代码转换为 PHP
Converting Java AES/ECB/PKCS7Padding/ code to PHP using PHP OpenSSL
我想使用带有 ECB 和 PKCS7Padding 的 AES 256 位加密算法来加密字符串。我浏览了很多网站,但其中 none 个网站是合适的。
我有 Java 使用 AES/ECB/PKCS7Padding 方法加密字符串的代码。
输入:'mystring'
输出:sWVnDZ0dwiTYoK4ixtURdA==
我想在 PHP 中使用 OpenSSL 这个算法,我尝试了很多解决方案,但其中 none 对我有用。
请帮我解决问题
JAVA 代码
package com.test.utils;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import java.security.Key;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Crypto {
private final String ALGORITHM = "AES/ECB/PKCS7Padding";
private byte[] keyValue;
public Crypto(String token) {
keyValue = token.getBytes();
}
public Crypto() {
keyValue= new byte[]{1, 2, 3, 4, 5, 6, 7,8,9, 10, 11, 12,13, 14, 15, 16};
}
public String encrypt(String valueToEnc) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM, "BC");
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encValue = c.doFinal(valueToEnc.getBytes("UTF8"));
return Base64.encode(encValue);
}
public String decrypt(String encryptedValue) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM, "BC");
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = Base64.decode(encryptedValue);
byte[] decValue = c.doFinal(decordedValue);
return new String(decValue);
}
private Key generateKey() throws Exception {
return new SecretKeySpec(keyValue, ALGORITHM);
}
}
我尝试在 php 中使用 OpenSSL
<?php
$data = "mystring";
$method = "AES-256-ECB";
$ivSize = openssl_cipher_iv_length($method);
$iv = [1, 2, 3, 4, 5, 6, 7,8,9, 10, 11, 12,13, 14, 15, 16];
$packed = call_user_func_array("pack", array_merge(array("c*"), $iv));
$output_utf8 = mb_convert_encoding($packed, 'utf-8');
$encrypted = openssl_encrypt($data,$method,$output_utf8,OPENSSL_RAW_DATA);
echo strlen('sWVnDZ0dwiTYoK4ixtURdA==');
echo "<br>";
echo "Expected Answer : sWVnDZ0dwiTYoK4ixtURdA==<br><br>";
echo strlen(base64_encode($encrypted));
echo "<br>";
echo "Answer : ".base64_encode($encrypted);
?>
预期答案:sWVnDZ0dwiTYoK4ixtURdA==
实际答案:7e5sKRCi21xzcwo6+ZOfaA==
这里有两个问题。
首先,在Java中,使用的AES变体(128、192或256)由密钥的长度决定。这里您使用的是 16 字节或 128 位密钥,因此您使用的是 AES-128。
在 PHP 中,您直接指定了 AES 变体,并且指定了 AES-256。 PHP 将简单地用空字节扩展密钥,直到它达到所需的长度。如果要匹配 Java 代码,则应指定 AES-128-ECB
。
其次,您需要小心处理密钥的方式。在您的 PHP 代码中,您实际上使用的是所有空字节的键,因为 pack
无法按照您期望的方式处理字符串。您可以简单地使用 implode
将数组转换为字符串:
$encrypted = openssl_encrypt($data, $method, implode($iv), OPENSSL_RAW_DATA);
我想使用带有 ECB 和 PKCS7Padding 的 AES 256 位加密算法来加密字符串。我浏览了很多网站,但其中 none 个网站是合适的。
我有 Java 使用 AES/ECB/PKCS7Padding 方法加密字符串的代码。
输入:'mystring' 输出:sWVnDZ0dwiTYoK4ixtURdA==
我想在 PHP 中使用 OpenSSL 这个算法,我尝试了很多解决方案,但其中 none 对我有用。
请帮我解决问题
JAVA 代码
package com.test.utils;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import java.security.Key;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Crypto {
private final String ALGORITHM = "AES/ECB/PKCS7Padding";
private byte[] keyValue;
public Crypto(String token) {
keyValue = token.getBytes();
}
public Crypto() {
keyValue= new byte[]{1, 2, 3, 4, 5, 6, 7,8,9, 10, 11, 12,13, 14, 15, 16};
}
public String encrypt(String valueToEnc) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM, "BC");
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encValue = c.doFinal(valueToEnc.getBytes("UTF8"));
return Base64.encode(encValue);
}
public String decrypt(String encryptedValue) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM, "BC");
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = Base64.decode(encryptedValue);
byte[] decValue = c.doFinal(decordedValue);
return new String(decValue);
}
private Key generateKey() throws Exception {
return new SecretKeySpec(keyValue, ALGORITHM);
}
}
我尝试在 php 中使用 OpenSSL
<?php
$data = "mystring";
$method = "AES-256-ECB";
$ivSize = openssl_cipher_iv_length($method);
$iv = [1, 2, 3, 4, 5, 6, 7,8,9, 10, 11, 12,13, 14, 15, 16];
$packed = call_user_func_array("pack", array_merge(array("c*"), $iv));
$output_utf8 = mb_convert_encoding($packed, 'utf-8');
$encrypted = openssl_encrypt($data,$method,$output_utf8,OPENSSL_RAW_DATA);
echo strlen('sWVnDZ0dwiTYoK4ixtURdA==');
echo "<br>";
echo "Expected Answer : sWVnDZ0dwiTYoK4ixtURdA==<br><br>";
echo strlen(base64_encode($encrypted));
echo "<br>";
echo "Answer : ".base64_encode($encrypted);
?>
预期答案:sWVnDZ0dwiTYoK4ixtURdA==
实际答案:7e5sKRCi21xzcwo6+ZOfaA==
这里有两个问题。
首先,在Java中,使用的AES变体(128、192或256)由密钥的长度决定。这里您使用的是 16 字节或 128 位密钥,因此您使用的是 AES-128。
在 PHP 中,您直接指定了 AES 变体,并且指定了 AES-256。 PHP 将简单地用空字节扩展密钥,直到它达到所需的长度。如果要匹配 Java 代码,则应指定 AES-128-ECB
。
其次,您需要小心处理密钥的方式。在您的 PHP 代码中,您实际上使用的是所有空字节的键,因为 pack
无法按照您期望的方式处理字符串。您可以简单地使用 implode
将数组转换为字符串:
$encrypted = openssl_encrypt($data, $method, implode($iv), OPENSSL_RAW_DATA);