AES/CBC/PKCS5Padding 加密 java 到 php,在 Java 中的数组中使用 IV 值 - 如何将代码从 Java 转换为 PHP?
AES/CBC/PKCS5Padding encryption java to php with IV values in array in Java - how to convert the code from Java to PHP?
我需要能够在 php 中加密和解密。我有需要转换为 Java 的示例 Java 代码,我在下面给出了它。尽我所能搜索,我无法找到一个将 iv 值作为数组给出的实例(我认为)。请参阅下面的 Java 代码
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.net.URL;
import java.net.URLEncoder;
import java.net.URLDecoder;
public class SecurityTest {
private static byte[] sharedkey = "A1234&ABCDE/98745#000078".getBytes();
private static byte[] sharedvector = {8, 7, 5, 6, 4, 1, 2, 3, 18, 17, 15, 16, 14, 11, 12, 13};
private static String decyptString ;
public static void main(String args[])
{
SecurityTest test = new SecurityTest();
System.out.println("Before assignment :"+sharedkey);
System.out.println("IV Value is :"+sharedvector);
sharedkey = "A1234&ABCDE/98745#000078".getBytes();
System.out.println("API Doc Key :"+sharedkey);
decyptString = "f5s0RMaYtr4WQseVR9E%2F3A%3D%3D";
String text = "Hello World";
System.out.println("This is a hello world encryption effort");
test.EncryptButton("Hello World");
test.DecryptButton(decyptString);
}
private void EncryptButton(String actualTxt){
try{
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sharedkey, "AES"), new IvParameterSpec(sharedvector));
byte[] encrypted = c.doFinal(actualTxt.getBytes("UTF-8"));
String strret = Base64.getEncoder().encodeToString(encrypted);
strret = strret.replace("\n", "");
System.out.println("Encoded String :"+strret);
System.out.println("URL Encoded :"+URLEncoder.encode(strret,"UTF-8"));
}catch(Exception e){
e.printStackTrace();
}
}
private void DecryptButton(String encryptedString){
try{
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sharedkey, "AES"), new IvParameterSpec(sharedvector));
// byte[] decrypted = c.doFinal(Base64.getDecoder().decode(URLDecoder.decode(encryptedString,"UTF-8")));
byte[] decrypted = c.doFinal(Base64.getDecoder().decode(URLDecoder.decode(encryptedString,"UTF-8")));
System.out.println(new String(decrypted, "UTF-8"));
}catch(Exception e){
e.printStackTrace();
}
}
}
The Java output is
This is a hello world encryption effort
Encoded String :f5s0RMaYtr4WQseVR9E/3A==
URL Encoded :f5s0RMaYtr4WQseVR9E%2F3A%3D%3D
我已经看到示例,其中 PHP 中的加密是使用 openssl 完成的,但 IV 值与此处给出的不同,如数组。 IV 值位于字节数组 sharedvector 中。
这是我在 PHP
中编写等价物时需要帮助的部分
private static byte[] sharedvector = {8, 7, 5, 6, 4, 1, 2, 3, 18, 17, 15, 16, 14, 11, 12, 13};
如何在 PHP 中写入此 IV?
我的PHP代码如下:
$method = "AES-256-CBC";
$plaintext="Hello World";
$key="A1234&ABCDE/98745#000078";
$sharedvector = "\x08\x07\x05\x06\x04\x01\x02\x03\x12\x11\x0f\x10\x0e\x0b\x0c\x0d";
$sharedvectorHex = unpack('H*', $sharedvector);
$encrypted = base64_encode(openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $sharedvectorHex[1]));
echo "encrypted is ".$encrypted;
我收到以下错误。
openssl_encrypt(): IV passed is 32 bytes long which is longer than the 16 expected by selected cipher, truncating
有人能给我指出正确的方向吗?
谢谢。
按照您的代码构建字节数组使用 十进制 值,这些值已转换为 hex 字符串表示形式,如下所示:
byte[] sharedvector = {8, 7, 5, 6, 4, 1, 2, 3, 18, 17, 15, 16, 14, 11, 12, 13};
System.out.println("\nsharedvector (Java): " + bytesToHex(sharedvector));
// byte array to hexstring method:
private static String bytesToHex(byte[] bytes) {
StringBuffer result = new StringBuffer();
for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
return result.toString();
}
结果:
sharedvector (Java): 080705060401020312110f100e0b0c0d
PHP 中的相同工作流程 - 请记住,Java 中的十进制值是手动转换为十六进制值的:
$sharedvector = "\x08\x07\x05\x06\x04\x01\x02\x03\x12\x11\x0f\x10\x0e\x0b\x0c\x0d";
$sharedvectorHex = unpack('H*', $sharedvector);
echo "sharedvector (PHP): " . $sharedvectorHex[1];
结果:
sharedvector (PHP) : 080705060401020312110f100e0b0c0d
当然,您可以使用 PHP 函数将十进制值转换为十六进制值,但我懒得为 16 字节的静态值实现它:-)
Function in PHP:
dechex ( int $number ) : string
编辑 - PHP 完整工作示例的解决方案:
这个答案遵循简单的规则“永远不要相信任何东西”(我在开玩笑):-)。在 Java 方面,您使用字符串作为加密密钥的来源
通过“.getBytes()”编码为字节数组。打印出密钥的长度将呈现给我们“24”,这是一个密钥的长度
AES-CBC-192 加密:
System.out.println("sharedKey length: " + sharedkey.length);
sharedKey length: 24
鉴于此,我将您的 PHP-code 更改为“AES-192-CBC”,您可以直接使用 $sharedvector。 Java 和 PHP 的加密字符串相同:f5s0RMaYtr4WQseVR9E/3A==
。为了确保一切正常,我还在 PHP 中添加了解密部分。
<?php
//
$method = "AES-192-CBC";
$plaintext = "Hello World";
$key = "A1234&ABCDE/98745#000078";
$sharedvector = "\x08\x07\x05\x06\x04\x01\x02\x03\x12\x11\x0f\x10\x0e\x0b\x0c\x0d";
$encrypted = base64_encode(openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $sharedvector));
echo "encrypted is " . $encrypted . "<br>";
$decrypted = openssl_decrypt(base64_decode($encrypted), $method, $key, OPENSSL_RAW_DATA, $sharedvector);
echo "decrypted is " . $decrypted;
/* output
encrypted is f5s0RMaYtr4WQseVR9E/3A==
decrypted is Hello World
*/
?>
我误解了数据的用途,抱歉。
使用像
这样的函数
function hexToStr($hex){
// Remove spaces if the hex string has spaces
$hex = str_replace(' ', '', $hex);
return hex2bin($hex);
}
在您的 PHP 代码中调用:
$method = "AES-256-CBC";
$plaintext = "Hello World";
$key = "A1234&ABCDE/98745#000078";
$sharedvector = "8 7 5 6 4 1 2 3 18 17 15 16 14 11 12 13";
$iv = hexToStr($sharedvector);
$encrypted = base64_encode(openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv));
echo "encrypted is " . $encrypted;
导致有效加密:
encrypted is Pi1TfbyAcEOxvfzFMItPLA==
我需要能够在 php 中加密和解密。我有需要转换为 Java 的示例 Java 代码,我在下面给出了它。尽我所能搜索,我无法找到一个将 iv 值作为数组给出的实例(我认为)。请参阅下面的 Java 代码
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.net.URL;
import java.net.URLEncoder;
import java.net.URLDecoder;
public class SecurityTest {
private static byte[] sharedkey = "A1234&ABCDE/98745#000078".getBytes();
private static byte[] sharedvector = {8, 7, 5, 6, 4, 1, 2, 3, 18, 17, 15, 16, 14, 11, 12, 13};
private static String decyptString ;
public static void main(String args[])
{
SecurityTest test = new SecurityTest();
System.out.println("Before assignment :"+sharedkey);
System.out.println("IV Value is :"+sharedvector);
sharedkey = "A1234&ABCDE/98745#000078".getBytes();
System.out.println("API Doc Key :"+sharedkey);
decyptString = "f5s0RMaYtr4WQseVR9E%2F3A%3D%3D";
String text = "Hello World";
System.out.println("This is a hello world encryption effort");
test.EncryptButton("Hello World");
test.DecryptButton(decyptString);
}
private void EncryptButton(String actualTxt){
try{
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sharedkey, "AES"), new IvParameterSpec(sharedvector));
byte[] encrypted = c.doFinal(actualTxt.getBytes("UTF-8"));
String strret = Base64.getEncoder().encodeToString(encrypted);
strret = strret.replace("\n", "");
System.out.println("Encoded String :"+strret);
System.out.println("URL Encoded :"+URLEncoder.encode(strret,"UTF-8"));
}catch(Exception e){
e.printStackTrace();
}
}
private void DecryptButton(String encryptedString){
try{
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sharedkey, "AES"), new IvParameterSpec(sharedvector));
// byte[] decrypted = c.doFinal(Base64.getDecoder().decode(URLDecoder.decode(encryptedString,"UTF-8")));
byte[] decrypted = c.doFinal(Base64.getDecoder().decode(URLDecoder.decode(encryptedString,"UTF-8")));
System.out.println(new String(decrypted, "UTF-8"));
}catch(Exception e){
e.printStackTrace();
}
}
}
The Java output is
This is a hello world encryption effortEncoded String :f5s0RMaYtr4WQseVR9E/3A==
URL Encoded :f5s0RMaYtr4WQseVR9E%2F3A%3D%3D
我已经看到示例,其中 PHP 中的加密是使用 openssl 完成的,但 IV 值与此处给出的不同,如数组。 IV 值位于字节数组 sharedvector 中。 这是我在 PHP
中编写等价物时需要帮助的部分private static byte[] sharedvector = {8, 7, 5, 6, 4, 1, 2, 3, 18, 17, 15, 16, 14, 11, 12, 13};
如何在 PHP 中写入此 IV?
我的PHP代码如下:
$method = "AES-256-CBC";
$plaintext="Hello World";
$key="A1234&ABCDE/98745#000078";
$sharedvector = "\x08\x07\x05\x06\x04\x01\x02\x03\x12\x11\x0f\x10\x0e\x0b\x0c\x0d";
$sharedvectorHex = unpack('H*', $sharedvector);
$encrypted = base64_encode(openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $sharedvectorHex[1]));
echo "encrypted is ".$encrypted;
我收到以下错误。
openssl_encrypt(): IV passed is 32 bytes long which is longer than the 16 expected by selected cipher, truncating
有人能给我指出正确的方向吗?
谢谢。
按照您的代码构建字节数组使用 十进制 值,这些值已转换为 hex 字符串表示形式,如下所示:
byte[] sharedvector = {8, 7, 5, 6, 4, 1, 2, 3, 18, 17, 15, 16, 14, 11, 12, 13};
System.out.println("\nsharedvector (Java): " + bytesToHex(sharedvector));
// byte array to hexstring method:
private static String bytesToHex(byte[] bytes) {
StringBuffer result = new StringBuffer();
for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
return result.toString();
}
结果:
sharedvector (Java): 080705060401020312110f100e0b0c0d
PHP 中的相同工作流程 - 请记住,Java 中的十进制值是手动转换为十六进制值的:
$sharedvector = "\x08\x07\x05\x06\x04\x01\x02\x03\x12\x11\x0f\x10\x0e\x0b\x0c\x0d";
$sharedvectorHex = unpack('H*', $sharedvector);
echo "sharedvector (PHP): " . $sharedvectorHex[1];
结果:
sharedvector (PHP) : 080705060401020312110f100e0b0c0d
当然,您可以使用 PHP 函数将十进制值转换为十六进制值,但我懒得为 16 字节的静态值实现它:-)
Function in PHP:
dechex ( int $number ) : string
编辑 - PHP 完整工作示例的解决方案:
这个答案遵循简单的规则“永远不要相信任何东西”(我在开玩笑):-)。在 Java 方面,您使用字符串作为加密密钥的来源 通过“.getBytes()”编码为字节数组。打印出密钥的长度将呈现给我们“24”,这是一个密钥的长度 AES-CBC-192 加密:
System.out.println("sharedKey length: " + sharedkey.length);
sharedKey length: 24
鉴于此,我将您的 PHP-code 更改为“AES-192-CBC”,您可以直接使用 $sharedvector。 Java 和 PHP 的加密字符串相同:f5s0RMaYtr4WQseVR9E/3A==
。为了确保一切正常,我还在 PHP 中添加了解密部分。
<?php
//
$method = "AES-192-CBC";
$plaintext = "Hello World";
$key = "A1234&ABCDE/98745#000078";
$sharedvector = "\x08\x07\x05\x06\x04\x01\x02\x03\x12\x11\x0f\x10\x0e\x0b\x0c\x0d";
$encrypted = base64_encode(openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $sharedvector));
echo "encrypted is " . $encrypted . "<br>";
$decrypted = openssl_decrypt(base64_decode($encrypted), $method, $key, OPENSSL_RAW_DATA, $sharedvector);
echo "decrypted is " . $decrypted;
/* output
encrypted is f5s0RMaYtr4WQseVR9E/3A==
decrypted is Hello World
*/
?>
我误解了数据的用途,抱歉。
使用像
这样的函数function hexToStr($hex){
// Remove spaces if the hex string has spaces
$hex = str_replace(' ', '', $hex);
return hex2bin($hex);
}
在您的 PHP 代码中调用:
$method = "AES-256-CBC";
$plaintext = "Hello World";
$key = "A1234&ABCDE/98745#000078";
$sharedvector = "8 7 5 6 4 1 2 3 18 17 15 16 14 11 12 13";
$iv = hexToStr($sharedvector);
$encrypted = base64_encode(openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv));
echo "encrypted is " . $encrypted;
导致有效加密:
encrypted is Pi1TfbyAcEOxvfzFMItPLA==