Below is the encryption method written in java, which I am trying to convert in php.
public static String encryptWithAesCtrNoPadding(final String key, final String value) throws IOException { try { byte[] encKey = Arrays.copyOf(key.getBytes("UTF-8"), 16); SecretKeySpec secretKey = new SecretKeySpec(encKey, "AES"); Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(new byte[16])); return Hex.encodeHexString(cipher.doFinal(value.getBytes("UTF-8"))); } catch (Exception ex) { throw new IOException(ex.getMessage()); } }
I tried several ways explained online but encrypted values from both the functions are not matching.
Below is the closest solution I got so far, but not getting the required output.
<?php function do_encryption(String $key, String $value) { $iv = "0000000000000000"; //base64_encode(openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-128-cbc'))); $encodedEncryptedData = bin2hex(openssl_encrypt($value, "AES-128-CTR", $key, OPENSSL_RAW_DATA, substr(($iv) , 0, 16))); } do_encryption("secret", "1234567890"); ?>
Any help in resolving this is highly appreciated. Thanks!
Advertisement
Answer
Java’s AES CTR implementation and PHP OpenSSL’s AES CTR implementations gives the same ciphertext when feed with the same data (encryption key, initialization vector and plaintext).
Below you find both programs using an UNSECURE fixed IV (for demonstration purposes) – never ever use a fixed IV in real programs!
The result on Java-side is:
ciphertext (hex): 8cddfd68b61265f7d9bb36a058e9405ad15c7797a322ef8c4e4788b5c31508aec8917f7c17234e757d7e38
and the same result on PHP-side:
ciphertext (hex): 8cddfd68b61265f7d9bb36a058e9405ad15c7797a322ef8c4e4788b5c31508aec8917f7c17234e757d7e38
Security warning: the following codes use a static IV and static (hardcoded) key and are for educational purpose only:
Java:
import org.apache.commons.codec.binary.Hex; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.IOException; import java.util.Arrays; public class Main { public static void main(String[] args) throws IOException { String encryptionKey = "1234567890123456"; String plaintext = "The quick brown fox jumps over the lazy dog"; String ciphertext = encryptWithAesCtrNoPadding(encryptionKey, plaintext); System.out.println("ciphertext (hex): " + ciphertext); // result: 8cddfd68b61265f7d9bb36a058e9405ad15c7797a322ef8c4e4788b5c31508aec8917f7c17234e757d7e38 } public static String encryptWithAesCtrNoPadding(final String key, final String value) throws IOException { try { byte[] encKey = Arrays.copyOf(key.getBytes("UTF-8"), 16); SecretKeySpec secretKey = new SecretKeySpec(encKey, "AES"); Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); // ### security warning: never use a STATIC IV ### cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(new byte[16])); return Hex.encodeHexString(cipher.doFinal(value.getBytes("UTF-8"))); } catch (Exception ex) { throw new IOException(ex.getMessage()); } } }
PHP:
<?php function do_encryption(String $key, String $value) { // ### security warning: never use a STATIC IV ### $fixedIv = "x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00"; //$iv = "0000000000000000"; //base64_encode(openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-128-cbc'))); $encodedEncryptedData = bin2hex(openssl_encrypt($value, "AES-128-CTR", $key, OPENSSL_RAW_DATA, substr(($fixedIv) , 0, 16))); return $encodedEncryptedData; } $encryptionKey = "1234567890123456"; $plaintext = "The quick brown fox jumps over the lazy dog"; $ciphertext = do_encryption($encryptionKey, $plaintext); echo 'ciphertext (hex): ' . $ciphertext; // result 8cddfd68b61265f7d9bb36a058e9405ad15c7797a322ef8c4e4788b5c31508aec8917f7c17234e757d7e38 // java 8cddfd68b61265f7d9bb36a058e9405ad15c7797a322ef8c4e4788b5c31508aec8917f7c17234e757d7e38 ?>