Search code examples
phpmathradixgmp

Why can't I pass sha1 output to gmp_init()?


I was checking out the binary parameter of sha1 today and I was not able to convert the resulting binary string to a base 62 representation.

$str = 'mystring';
echo gmp_strval(gmp_init(sha1($str), 16), 62), PHP_EOL;      // Works
echo gmp_strval(gmp_init(sha1($str, true), 2), 62), PHP_EOL; // Fails
// Same with base_convert()...
echo base_convert(sha1($str), 16, 32), PHP_EOL;              // Works
echo base_convert(sha1($str, true), 2, 32), PHP_EOL;         // Fails

Result:

MNun4i9wmY2M2sBvnq5Z8jDi7nk
0
jjhukjbflgg000000000000000000000
0

I'm wondering if it is because the gmp_init() and base_convert() functions requires an integer or string and this is perhaps just binary data.


Solution

  • @mario comment is correct, to convert from a binary string representation to base 2, you must do:

    $base2 = array_map('decbin', array_map('ord', str_split(sha1($str, true))));
    

    Or from the hexadecimal digest:

    $base2 = array_map('decbin', array_map('hexdec', str_split(sha1($str), 2)));
    

    Then all you need to do is zero-pad each $base2 value to 8 bits and implode it's contents.


    It's also worth noticing that your base_convert call will overflow, so don't rely on it.

    One other (rather important) thing is that the charset gmp uses for base > 10 is actually:

    0123456789A..Za..z
    

    Contrary to what the base_convert and hash functions use of:

    0123456789a..f[g..zA..Z]
    

    I suggest you use strtoupper to encode the hash and strtr to decode it, like this.