Skip to content

Instantly share code, notes, and snippets.

@siddharth
Last active March 16, 2022 13:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save siddharth/b114b4415b6791a23ac8196c5a5ef8be to your computer and use it in GitHub Desktop.
Save siddharth/b114b4415b6791a23ac8196c5a5ef8be to your computer and use it in GitHub Desktop.
Replicating / Implementing Java's AES/CBC/PKCS5Padding encryption in PHP
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import java.io.ByteArrayOutputStream;
public class ChecksumGen {
public static void main(final String[] args) {
String data = "INPUTDATA";
String secretKey = "0000000000000000000000000000000000000000000000000000000000000000";
byte[] iv = new byte[16];
try {
byte[] hashedData = getDigest(data);
byte[] key = hexStringToByteArray(secretKey);
byte[] checksum = encrypt(key, hashedData, iv);
showB64("key ", key);
showB64("iv ", iv);
showB64("hashedData ", hashedData);
showB64("checksum ", checksum);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public static byte[] getDigest(String checkSumInput) {
try {
MessageDigest localMessageDigest = MessageDigest.getInstance("SHA-256");
byte[] checkSumInputBytes = checkSumInput.getBytes("UTF-8");
localMessageDigest.update(checkSumInputBytes);
byte[] digest = localMessageDigest.digest();
return digest;
} catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {
throw new RuntimeException(ex);
}
}
public static byte[] hexStringToByteArray(String s) {
byte[] b = new byte[s.length() / 2];
for (int i = 0; i < b.length; i++) {
int index = i * 2;
int v = Integer.parseInt(s.substring(index, index + 2), 16);
b[i] = (byte) v;
}
return b;
}
public static byte[] encrypt(byte[] key,byte[] data, byte[] iv)throws Exception{
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher acipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
acipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,ivSpec);
byte[] arrayOfByte1 = acipher.doFinal(data);
return arrayOfByte1;
}
public static void showB64(String label, byte[] rawData) {
System.out.println(label + ":" + Base64.getEncoder().encodeToString(rawData));
}
}
/* Sample output :
key :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
iv :AAAAAAAAAAAAAAAAAAAAAA==
hashedData :ZAgNCUfIbdT9EjdkCb3XDNpMFGV34rXNjcTOQ9cdZ3w=
checksum :9NS/ZKMscpa4V7i2YQQPoycxCwbL1BlK3h9O/1ujoD1iYgjE8tZx+JRGflw5WikH
*/
<?php
/*
Following notes are from my research regarding padding (text not mine).
Read to understand the confusion between PKCS7 (default padding) and
PKCS5 (which we are trying to achieve here) :
OPENSSL_ZERO_PADDING has a direct impact on the OpenSSL context. EVP_CIPHER_CTX_set_padding() enables or disables padding (enabled by default). So, OPENSSL_ZERO_PADDING disables padding for the context, which means that you will have to manually apply your own padding out to the block size. Without using OPENSSL_ZERO_PADDING, you will automatically get PKCS#7 padding.
OPENSSL_RAW_DATA does not affect the OpenSSL context but has an impact on the format of the data returned to the caller. When OPENSSL_RAW_DATA is specified, the returned data is returned as-is. When it is not specified, Base64 encoded data is returned to the caller.
*/
$data = "INPUTDATA";
$hashedData = hash("sha256", $data, true);
$secretKey = "0000000000000000000000000000000000000000000000000000000000000000";
$ivStr = "00000000000000000000000000000000";
$key = pack('H*', $secretKey);
$iv = pack('H*', $ivStr);
$inputData = pkcs5_pad($hashedData, 16);
showB64('key', $key);
showB64('iv', $iv);
showB64('hashedData', $hashedData);
showB64('inputData', $inputData);
$checksum = encrypt($key, $inputData, $iv);
showB64('checksum', $checksum);
function encrypt($key,$data,$iv){
$cipher = 'AES-256-CBC';
$options = OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING;
$raw = openssl_encrypt(
$data,
$cipher,
$key,
$options,
$iv
);
return $raw;
}
function pkcs5_pad($text, $blocksize){
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
function showB64($label, $rawData) {
echo "{$label} :".base64_encode($rawData)."\n";
}
/* Sample output :
key :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
iv :AAAAAAAAAAAAAAAAAAAAAA==
hashedData :ZAgNCUfIbdT9EjdkCb3XDNpMFGV34rXNjcTOQ9cdZ3w=
inputData :ZAgNCUfIbdT9EjdkCb3XDNpMFGV34rXNjcTOQ9cdZ3wQEBAQEBAQEBAQEBAQEBAQ
checksum :9NS/ZKMscpa4V7i2YQQPoycxCwbL1BlK3h9O/1ujoD1iYgjE8tZx+JRGflw5WikH
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment