Reputation:
I've been given a chunk of code which describes an "algorithm" for token generation. This code is written in Java and works as is correctly. The given Java code must remain exactly as is, however, my requirement is to have the same "algorithm" used within a PHP application and I'm having a hard time retrieving the same result.
Java code:
public static void main(String[] args)
throws
UnsupportedEncodingException,
NoSuchAlgorithmException {
// Let's stick to a fixed date for this SO question
//DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmm");
//dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
//String date = dateFormat.format(new Date());
String date = "201603251605";
String name = "some_dummy_data_one";
String size = "some_dummy_data_two";
// MD5 'name'
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(name.getBytes());
byte[] md5name = md5.digest();
// What happens here is beyond me - How would one translate this to PHP?
byte[] sizeBytes = (size + date).getBytes();
byte[] tokenBytes = new byte[md5name.length + sizeBytes.length];
System.arraycopy(sizeBytes, 0, tokenBytes, 0, sizeBytes.length);
System.arraycopy(md5name, 0, tokenBytes, sizeBytes.length, md5name.length);
// SHA256
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
sha256.update(tokenBytes);
byte[] tokenHash = sha256.digest();
System.out.println(Base64.getEncoder().encodeToString(tokenHash));
}
This prints:
LsPw/5/4uKmQfVaU1LRASxG89mgMt7OxX+h7JGRo1ZU=
Ultimately and ideally I'd love a quick way to just get the same result with PHP code, but I've the urge to understand what's going on instead of just reaching the desired result.
Now to attempt to display that I have at least done a little homework and I'm not just seeking someone to do my work for me, up until the MD5 conversion of the strings, I've managed to get an identical base64 encoded SHA256 string of a single string skipping the middle chunk of code containing the 'System.arrayCopy' bit:
Java code:
public static void main(String[] args)
throws
UnsupportedEncodingException,
NoSuchAlgorithmException {
String date = "201603251605";
// MD5 'name'
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(date.getBytes());
byte[] md5Date = md5.digest();
// SHA256
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
sha256.update(md5Date);
byte[] tokenHash = sha256.digest();
System.out.println(Base64.getEncoder().encodeToString(tokenHash));
}
PHP code:
private function generateToken() {
$md5Date = md5("201603251605", true);
$shaString = hash("sha256", $md5Date, true);
return base64_encode($shaString);
}
Java output:
mEkkRlBkwyoWFMsA+v/hP/m9sD6FdzM6LZHIORtr260=
PHP output:
mEkkRlBkwyoWFMsA+v/hP/m9sD6FdzM6LZHIORtr260=
So according to the above, my md5 and sha of a single string works fine, but that's not the problem. The problem is understanding what is happening when multiple strings are defined and are being mashed together in the Java code. Why does it seem overly complicated and is there a simple way of doing it in PHP?
Could somebody please explain what is happening in between the MD5 and SHA256 generation so that I can translate it to PHP code? I've attempted to read up on the Java System.arrayCopy documentation, but I feel as though I'm not experienced/smart enough to understand what is going on there. If there's a simple solution to this, I'd appreciate it very much.
Upvotes: 1
Views: 321
Reputation: 291
Sounds like you got the answer for how to do it in PHP. The java code does basically the same thing. Here's what it's doing...
// This concatenates size+date and the md5 hash, and then creates a SHA-256 hash from that value.
byte[] sizeBytes = (size + date).getBytes(); //Get byte array of size and date concatenation
byte[] tokenBytes = new byte[md5name.length + sizeBytes.length]; //Create the right size byte array to fit md5 and size+date
System.arraycopy(sizeBytes, 0, tokenBytes, 0, sizeBytes.length); // copies the size+date byte array into the first part of the token bytes byte array.
System.arraycopy(md5name, 0, tokenBytes, sizeBytes.length, md5name.length); //concatenates the md5 hash and size+bytes into the tokenBytes array
// SHA256
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");//Get the SHA-256 algorithm instance
sha256.update(tokenBytes); // give it a value to hash
byte[] tokenHash = sha256.digest(); // create SHA-256 hash from token bytes
Upvotes: 1
Reputation: 5876
You'll kick yourself when you realize how simple what it's actually doing is.
<?php
$date = "201603251605";
$name = "some_dummy_data_one";
$size = "some_dummy_data_two";
$md5_name = md5($name, true);
$token_bytes = $size.$date.$md5_name;
$token_hash = hash("sha256", $token_bytes, true);
echo base64_encode($token_hash);
arraycopy
is just a pretty confusing way of appending size
, date
and md5name
. Why the Java code is so complicated I have no idea.
Upvotes: 1