1

I'm working on an implementation of PHPass for Google Apps Script but am struggling with the Portable Hashes variable MD5 iterations.

The reason we're doing this is that we need to be able to automate regular password changes for a large number of WordPress sites. We need to generate hashes that can be inserted directly into the database. Therefore our implementation needs to be 100% compatible with the WordPress implementation of portable hashes (per wp-includes/class-phpass.php).

The crux of the issue lies in the MD5 iterations; computeDigest returns Byte[] whereas the input requires a String so the following code gives undesirable results as regards compatibility with PHPass:

function genHash_(passwd,settings) {
  var output = '';
  var salt = settings.slice(4,12);
  var count = 1 << itoa64_.indexOf(settings[3]);

  var hash = genMD5_(bin2String_(salt) + passwd);
  do {
    hash = genMD5_(bin2String(hash) + passwd);
  } while (--count);

  output = settings.slice(0,12);
  output += encode64_(hash,16);

  return output;
}

function genMD5_(input) {
  return Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, input);
}

function bin2String_(bin) {
  return String.fromCharCode.apply(String,bin);
}

In the PHP implementation (from wp-includes/class-phpass.php):

$hash = md5($salt . $password, TRUE);
do {
  $hash = md5($hash . $password, TRUE);
} while (--$count);

The TRUE causes md5 to return the result in a raw binary format. PHP Strings are 100% binary compatible so this 'just works'.

The problem with an Apps Script implementation appears to be that, however you dice it, the conversion to string from the output of computeDigest doesn't work. Even if you stuff a String using fromCharCode to get the hash, the converting back again with getCharAt yields different results thanks to the unicode conversions.

So I've more or less concluded that this is a limitation of computeDigest and would therefore require a change from Google. But on the off chance that someone has any ideas, I think it's worth asking the question.

Edit: It's been mentioned that this could be a duplicate of another question that relates to converting the output of computeDigest into a string. While this is similar, it's not a duplicate because the solution requires binary compatibility between the output and input of computeDigest.

Edit: I've looked at an approach using Blob.getDataAsString() suggested in this question but this suffers from a similar problem at the point of conversion.

Community
  • 1
  • 1
chrisbateskeegan
  • 1,013
  • 1
  • 11
  • 14
  • possible duplicate of [get back a string representation from computeDigest(algorithm, value) byte\[\]](http://stackoverflow.com/questions/16216868/get-back-a-string-representation-from-computedigestalgorithm-value-byte) – Zig Mandel May 22 '15 at 14:27
  • This isn't a duplicate because it relates to feeding back a binary compatible hash into the computeDigest function not just converting it into a String. – chrisbateskeegan May 22 '15 at 14:30
  • sorry, seemed very similar. does this other one help? http://stackoverflow.com/a/30373585/2213940 – Zig Mandel May 22 '15 at 14:31
  • Just given that a try and I thought it looked like it had good potential for a solution so thanks for that. Unfortunately it suffers from the same issue - failing to get a compatible hash. When the hash fails I then look at the output from the md5 at each iteration. I'm testing by converting the the output Byte[] to String and back again and comparing the results. The resulting byte array differs inasmuch as the negative numbers are wrong, which I'm assuming is as a result of the MSB being used as part of UTF-8 / Unicode encoding. I'm not an expert on that stuff by any means! – chrisbateskeegan May 22 '15 at 14:52
  • cant both links I provided be combined? deal with negative numbers using my "possible duplicate" linked answer, then use my other link (using blob) to convert to binary. not an expert either and not much time to look at it, but both answers rang a bell in my s.o. head index – Zig Mandel May 22 '15 at 14:59
  • Unfortunately not. Converting to a hex string (per the possible duplicate) isn't what's happening in the PHP implementation. The PHP implementation is just using a string as a Byte array - the md5(...,TRUE) returns raw numbers, not the hex string and it's that which is being fed into the next iteration. It's my view that there would need to be a variant of computeDigest that took a Byte[] as input is probably the only solution. The round trip to String and back in JS is the root cause. The optimist in me hopes I'm wrong though! – chrisbateskeegan May 22 '15 at 15:04
  • Id add all these stuff into your question so it better shows what you have tried and didnt work so far. – Zig Mandel May 22 '15 at 15:05

0 Answers0