- 1 year ago 302
PHP Question

Encrypt a timestamp in PHP and decrypt in Java

I need to encrypt a unix timestamp to make a call to a third party API. In their documentation they specify I must use:

  • Algorithm: 128-bit AES, Mode: CBC

  • Padding: PKCS5Padding

  • Initialization Vector: "0000000000000000"

And then they give an example:

Clients must test their implementation using the timestamp 1464284796, the initialization vector: '0000000000000000' and the secret key b35901b480ca658c8be4341eefe21a80 which resulting in the base64 auth_token 6BH3hg1cqQJOK6sG8gw7Xw==

They even give sample code to generate the encrypted timestamp, problem is that they're using Java and we're using PHP. Everything I try in PHP does not match the expected output, which is 6BH3hg1cqQJOK6sG8gw7Xw== .

Here's their Java sample:

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
class Encryptor {
private String initialVector;
private static final String TRANFORMATION = "AES/CBC/PKCS5Padding";
private static final String ALGORITHM = "AES";
String encrypt(SecretKeySpec key, long timestamp) throws Exception {
byte[] encryptedBytes =
return Base64.encodeBase64String(encryptedBytes);
private Cipher getEncryptingCipher(SecretKeySpec key) throws
NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException,
InvalidAlgorithmParameterException {
Cipher encryptingCipher = Cipher.getInstance(TRANFORMATION);
encryptingCipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(initialVector.getBytes()));
return encryptingCipher;
private SecretKeySpec getSecretKeySpec(String key) throws DecoderException {
byte[] keyBytes = Hex.decodeHex(key.toCharArray());
return new SecretKeySpec(keyBytes, ALGORITHM);
void setInitialVector(String initialVector) {
this.initialVector = initialVector;


Encryptor encryptor = new Encryptor();
//Expensive operation so only performed once, re-use the key spec instance
SecretKeySpec keySpec =
long timestamp = System.currentTimeMillis() / 1000;
String authToken = encryptor.encrypt(keySpec, timestamp);

My attempts in PHP:

[acool@acool ~]$ php -a
Interactive shell

php > echo openssl_encrypt( '1464284796','AES-128-CBC','b35901b480ca658c8be4341eefe21a80',null,'0000000000000000');
php >

And then:


function encrypt($message, $initialVector, $secretKey) {
return base64_encode(

function encrypt_something($input)
$size = mcrypt_get_block_size('rijndael-128', 'cbc');
$input = pkcs5_pad($input, $size);

$key = 'b35901b480ca658c8be4341eefe21a80';
$td = mcrypt_module_open('rijndael-128', '', 'cbc', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, '0000000000000000');
$data = mcrypt_generic($td, $input);
$data = base64_encode($data);
return $data;

function pkcs5_pad ($text, $blocksize)
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);

function pkcs5_unpad($text)
$pad = ord($text{strlen($text)-1});
if ($pad > strlen($text)) return false;
if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
return substr($text, 0, -1 * $pad);

echo encrypt_something('1464284796');

//echo encrypt('1464284796','0000000000000000','b35901b480ca658c8be4341eefe21a80');

[acool@acool ~]$ php -f api.php

Honestly, I don't have much idea of what I'm doing, specifically in JAVA. I don't even know how to run the sample code.


Third party reached out to us with a revision of their sample:

Note: clients must test their implementation using the timestamp
1464284796, the initialization vector: '0000000000000000' and the
secret key b35901b480ca658c8be4341eefe21a80 which resulting in the
base64 auth_token ZnNmKbcdxRrYTDBgQKI9aQ==

The solution is to revome

$ts = '1464284796';
$key = "b35901b480ca658c8be4341eefe21a80";
$authToken = openssl_encrypt( $ts, 'AES-128-CBC', hextobin($key), null, '0000000000000000');

function hextobin($hexstr)
$n = strlen($hexstr);
$sbin ="";
$i =0;
$a =substr($hexstr,$i,2);
$c = pack("H*",$a);
if ($i==0){$sbin=$c;}
else {$sbin.=$c;}
return $sbin;

Answer Source

Numbers are not simply decimal strings. You have to encode them to a binary representation. This can be done with pack. Since Longs.toByteArray(timestamp) encodes the timestamp in 64-bit big-endian notation, you have to match this encoding:

$ts = "\0\0\0\0" . pack('N', '1464284796');
echo openssl_encrypt( $ts, 'AES-128-CBC', hex2bin('b35901b480ca658c8be4341eefe21a80'), 
        null, '0000000000000000'));
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download