Last active
March 16, 2022 13:54
-
-
Save siddharth/b114b4415b6791a23ac8196c5a5ef8be to your computer and use it in GitHub Desktop.
Replicating / Implementing Java's AES/CBC/PKCS5Padding encryption in PHP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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