【问题标题】:convert base64 to base62 (without special characters)将 base64 转换为 base62(无特殊字符)
【发布时间】:2013-08-04 16:42:39
【问题描述】:

我想在 URL 中传递一个河豚加密字符串,并且想像 base64 一样对其进行编码,但没有任何特殊字符,像 base62 这样的东西会很棒(0-9a-zA-Z)。所以我要做的是使用base64_encode转换河豚加密字符串,并将base64转换为base62。

我知道如何使 base64 url​​ 安全的解决方案,但我真的不希望字符串中有任何特殊字符。 convert_base() 只适用于 36 的基数,数学扩展可以转换到 62 的基数。

有人知道如何使用 PHP 将 base64 字符串转换为 base62 吗?

【问题讨论】:

    标签: php base64 converter base62


    【解决方案1】:
    function base62encode($data) {
        $outstring = '';
        $l = strlen($data);
        for ($i = 0; $i < $l; $i += 8) {
            $chunk = substr($data, $i, 8);
            $outlen = ceil((strlen($chunk) * 8)/6); //8bit/char in, 6bits/char out, round up
            $x = bin2hex($chunk);  //gmp won't convert from binary, so go via hex
            $w = gmp_strval(gmp_init(ltrim($x, '0'), 16), 62); //gmp doesn't like leading 0s
            $pad = str_pad($w, $outlen, '0', STR_PAD_LEFT);
            $outstring .= $pad;
        }
        return $outstring;
    }
    
    function base62decode($data) {
        $outstring = '';
        $l = strlen($data);
        for ($i = 0; $i < $l; $i += 11) {
            $chunk = substr($data, $i, 11);
            $outlen = floor((strlen($chunk) * 6)/8); //6bit/char in, 8bits/char out, round down
            $y = gmp_strval(gmp_init(ltrim($chunk, '0'), 62), 16); //gmp doesn't like leading 0s
            $pad = str_pad($y, $outlen * 2, '0', STR_PAD_LEFT); //double output length as as we're going via hex (4bits/char)
            $outstring .= pack('H*', $pad); //same as hex2bin
        }
        return $outstring;
    }
    
    $str62 = base62_encode(base64_decode($str64)) // $str64 = our string base64 encoded
    

    所有学分都转到Marcus Bointon

    【讨论】:

    • 太好了,我忘记了 bin2hex!非常感谢!
    • 不幸的是,如果您没有安装所需的功能,则会引发致命错误。像 gmp_strval
    【解决方案2】:

    在不使用 GPM 的情况下,以下内容应该可以在 Base85 上正常工作,不会有太多麻烦。令人惊讶的是,这似乎比 GPM 稍快,可能是因为它没有先转到十六进制。

    <?php
    
    /**
    * Devide a large number represented as a binary string in the specified base
    * and return the remainder.
    * 
    * @param string &$binary
    * @param int $base
    * @param int $start
    */
    function divmod(&$binary, $base, $divisor, $start = 0)
    {
        /** @var int $size */
        $size = strlen($binary);
    
        // Do long division from most to least significant byte, keep remainder.
        $remainder = 0;
        for ($i = $start; $i < $size; $i++) {
            // Get the byte value, 0-255 inclusive.
            $digit = ord($binary[$i]);
    
            // Shift the remainder left by base N bits, append the last byte.
            $temp = ($remainder * $base) + $digit;
    
            // Calculate the value for the current byte.
            $binary[$i] = chr($temp / $divisor);
    
            // Carry the remainder to the next byte.
            $remainder = $temp % $divisor;
        }
    
        return $remainder;
    }
    
    /**
    * Produce a base62 encoded string from a large binary number.
    * 
    * @param string $binary
    * return string
    */
    function encodeBase62($binary)
    {
        $charMap = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $base = strlen($charMap);
    
        $size = strlen($binary);
        $start = $size - strlen(ltrim($binary, "\0"));
    
        $encoded = "";
        for ($i = $start; $i < $size; ) {
            // Do long division from most to least significant byte, keep remainder.
            $idx = divmod($binary, 256, $base, $i);
    
            $encoded = $charMap[$idx] . $encoded;
    
            if (ord($binary[$i]) == 0) {
                $i++; // Skip leading zeros produced by the long division.
            }
        }
    
        $encoded = str_pad($encoded, $start, "0", STR_PAD_LEFT);
    
        return $encoded;
    }
    
    /**
    * Produce a large binary number from a base62 encoded string.
    * 
    * @param string $ascii
    * return string
    */
    function decodeBase62($ascii)
    {
        $charMap = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $base = strlen($charMap);
    
        $size = strlen($ascii);
        $start = $size - strlen(ltrim($ascii, "0"));
    
        // Convert the ascii representation to binary string.
        $binary = "";
        for ($i = $start; $i < $size; $i++) {
            $byte = strpos($charMap, $ascii[$i]);
            if ($byte === false) {
                throw new OutOfBoundsException("Invlaid encoding at offset '{$ascii[$i]}'");
            }
    
            $binary .= chr($byte);
        }
    
        $decode = "";
        for ($i = 0; $i < $size; ) {
            // Do long division from most to least significant byte, keep remainder.
            $idx = divmod($binary, $base, 256, $i);
    
            $decode = chr($idx) . $decode;
    
            if (ord($binary[$i]) == 0) {
                $i++; // Skip leading zeros produced by the long division.
            }
        }
    
        $decode = ltrim($decode, "\0");
        $decode = str_pad($decode, $start, "\0", STR_PAD_LEFT);
    
        return $decode;
    }
    
    $data = pack("N*", 1234567890);
    //$data = pack("C*", 0x49, 0x96, 0x02, 0xD2);
    var_dump(unpack("N1", $data));
    
    $base62 = encodeBase62($data);
    var_dump( $base62 ); // "1ly7vk"
    
    $decoded = decodeBase62($base62);
    var_dump(unpack("N1", $decoded)); // 1234567890
    
    var_dump( strcmp($decoded, $data) === 0 ); // true
    

    【讨论】:

      【解决方案3】:

      以下似乎工作正常,根本不使用 base64:

      gmp_strval( gmp_init( bin2hex('myencryptedstring'), 16), 62);
      

      【讨论】:

        猜你喜欢
        • 2023-04-08
        • 2013-03-08
        • 1970-01-01
        • 2015-02-20
        • 2019-02-17
        • 2013-05-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多