views:

200

answers:

3

Hello!

Can you tell me how the invert function for the following PHP function is?

<?php
function id2secure($old_number) {
 $alphabet_en = '1357902468acegikmoqsuwybdfhjlnprtvxz-_';
 $new_number = '';
 while ($old_number > 0) {
  $rest = $old_number%38;
  if ($rest >= 38) { return FALSE; }
  $new_number .= $alphabet_en[$rest];
  $old_number = floor($old_number/38);
 }
 $new_number = strrev($new_number);
 return $new_number;
}
echo id2secure(172293);
?>

Thank you very much in advance!

+1  A: 

Haven't tested this code, but it might work:

<?php function secure2id($sr)
{
  $s = strrev($sr);
  $alpha = '1357902468acegikmoqsuwybdfhjlnprtvxz';
  $alpha2num = array();
  $n = strlen($alpha);
  for($i = 0; $i < $n; $i++)
  {
    $alpha2num[$alpha[$i]] = $i;
  }
  $rez = 0;
  $n = strlen($s);
  $b = 1;
  for($i = 0; $i < $n; $i++)
  {
    $rez += $b * $alpha2num[$s[$i]];
    $b *= 38;
  }
  return $rez;
} ?>

`

MathGladiator
Thank you. I've tested it: There's only one mistake. You have to write $b *= 38 instead of $b += 38.
A: 

Are you asking how to convert base 38 to base 10? The numerical algorithm is this:

  1. Let N be the new number in base 10. Set N to zero to start with.
  2. Let X be the original number in base 38.
  3. Multiply N by 38.
  4. Let D be the most significant (leftmost) digit of X.
  5. Let T be the value of D in base 10.
  6. Add T to N.
  7. Remove D from X (so the number X is now 1 digit shorter).
  8. If X is empty, goto 10.
  9. Goto 3.
  10. Return N, which is now the fully converted base 10 number.

Now that you understand the math, it should be fairly straightforward to convert these steps to a PHP function.

bobbymcr
+1  A: 

This is secure :) Took me a few minutes to crack it. Here you go,

function secure2id($new_number) {
        $alphabet_en = '1357902468acegikmoqsuwybdfhjlnprtvxz';
        $old_number = 0;
        $new_number = strrev($new_number);
        $len=strlen($new_number);
        $n=0;
        $base=1;
        while($n<$len){
            $c=$new_number[$n];
            $index = strpos($alphabet_en, $c);
            if ($index === false)
                 break;
            $old_number += $base * $index;
            $base *= 38;
            $n++;
        }
        return $old_number;
}
ZZ Coder
Thank you very much! This works if you add the - and the _ at the end of $alphabet_en.
I thought the missing alphabet was a security feature :)
ZZ Coder
No, it wasn't :) Your function is 2.4 times as fast as ZenGeneral's.
Are you sure it's faster? ZenGeneral's has a pre-built lookup table. If you have bigger numbers, his should be faster.
ZZ Coder
Yes, I've been surprised about this, too. I've tested both functions with numbers up to 1,000,000,000. And your function is faster. :)