Ported to javascript from http://code.activestate.com/recipes/325204-passwd-file-compatible-1-md5-crypt/
function md5crypt(password, salt, magic) {
  var rearranged = '',
      mixin, final, m, v, i;

  m = crypto.createHash('md5');
  m.update(password + magic + salt);
  mixin = crypto.createHash('md5').update(password + salt + password).digest("binary");

  for (i = 0; i < password.length; i++) {
    m.update(mixin[i % 16]);
  }

  // Weird shit..
  for (i = password.length; i > 0; i >>= 1) {
    if (i & 1) {
      m.update('\x00');
    } else {
      m.update(password[0]);
    }
  }

  final = m.digest("binary");

  // Slow it down there...
  for (i = 0; i < 1000; i ++) {
    m = crypto.createHash('md5');

    if (i & 1) {
      m.update(password);
    } else {
      m.update(final);
    }

    if (i % 3) {
      m.update(salt);
    }

    if (i % 7) {
      m.update(password);
    }

    if (i & 1) {
      m.update(final);
    } else {
      m.update(password);
    }

    final = m.digest("binary");
  }


  for (i = 0; i < TUPLES.length; i++) {
    v = final.charCodeAt(TUPLES[i][0]) << 16 | final.charCodeAt(TUPLES[i][1]) << 8 | final.charCodeAt(TUPLES[i][2]);
    rearranged += ITOA64[v & 0x3f]; v >>= 6;
    rearranged += ITOA64[v & 0x3f]; v >>= 6;
    rearranged += ITOA64[v & 0x3f]; v >>= 6;
    rearranged += ITOA64[v & 0x3f]; v >>= 6;
  }

  v = final.charCodeAt(11);
  rearranged += ITOA64[v & 0x3f]; v >>= 6;
  rearranged += ITOA64[v & 0x3f]; v >>= 6;

  return magic + salt + '$' + rearranged;
}