I need to be able to encrypt and decrypt in php. I have the Sample Java code which needs to be converted to Java, and I have given below. As much as I have searched, I am not able to find a single instance where an iv value is given as an array(I think). Please see Java code below
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
I have seen samples where encryption in PHP is done using openssl, but the IV values are not as what is given here, like an array. The IV values are in the byte array sharedvector. This is the part where I need help in writing the equivalent in PHP
private static byte[] sharedvector = {8, 7, 5, 6, 4, 1, 2, 3, 18, 17, 15, 16, 14, 11, 12, 13};
How do I write this IV in PHP ?
The PHP Code that I have is listed below:
$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;
I am getting the following error.
openssl_encrypt(): IV passed is 32 bytes long which is longer than the 16 expected by selected cipher, truncating
Can someone please point me in the right direction?
Thanks.
Building an byte array as written in your code uses decimal values that got converted to a hexstring representation as follows:
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();
}
Result:
sharedvector (Java): 080705060401020312110f100e0b0c0d
Same workflow in PHP - please keep in mind that the decimal values in Java are converted to hex values manually:
$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];
Result:
sharedvector (PHP) : 080705060401020312110f100e0b0c0d
Of course you can convert the decimal values to hexvalues with a PHP-function but I'm to lazy to implement this for a static value of 16 bytes :-)
Function in PHP:
dechex ( int $number ) : string
Edit - solution with PHP full working sample:
This answer follows the simple rule "never trust anything" (I'm joking) :-). On Java side you are using a string as source for the encryption key that is encoded to a byte array via ".getBytes()". Printing out the length of the key will present us "24" and that's the key length for an AES-CBC-192 encryption:
System.out.println("sharedKey length: " + sharedkey.length);
sharedKey length: 24
With that given I changed your PHP-code to "AES-192-CBC" and you can use the $sharedvector directly as it is. The encrypted string is the same for Java and PHP: f5s0RMaYtr4WQseVR9E/3A==
. Just to be sure everything is working I added the decryption part in PHP as well.
<?php
// https://stackoverflow.com/questions/62449449/aes-cbc-pkcs5padding-encryption-java-to-php-with-iv-values-in-array-in-java-ho/62454297#62454297
$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
*/
?>