【问题标题】:effective solution: base32 encoding in php有效的解决方案:php中的base32编码
【发布时间】:2026-02-16 20:35:01
【问题描述】:

我正在寻找 php 的 base32 函数/类。我发现的不同类和功能都非常无效。我运行了一个基准测试并得出以下结果:

10000 次解码:

base32:2.3273 秒

base64:0.0062 秒

我使用的base32类是:

http://www.php.net/manual/en/function.base-convert.php#102232

有没有更简单的方法?

我想使用 base32 的原因是它不区分大小写,因此我对某些系统(例如电子邮件系统)上总是转换为小写字母的 url 参数没有任何问题。

如果您有更好的小写编码替代方案,我也很想听听。

【问题讨论】:

    标签: php url encoding parameters decoding


    【解决方案1】:

    你可以试试我改编自bbarscrockford的这些功能:

    function crockford32_encode($data) {
        $chars = '0123456789abcdefghjkmnpqrstvwxyz';
        $mask = 0b11111;
    
        $dataSize = strlen($data);
        $res = '';
        $remainder = 0;
        $remainderSize = 0;
    
        for($i = 0; $i < $dataSize; $i++) {
            $b = ord($data[$i]);
            $remainder = ($remainder << 8) | $b;
            $remainderSize += 8;
            while($remainderSize > 4) {
                $remainderSize -= 5;
                $c = $remainder & ($mask << $remainderSize);
                $c >>= $remainderSize;
                $res .= $chars[$c];
            }
        }
        if($remainderSize > 0) {
            $remainder <<= (5 - $remainderSize);
            $c = $remainder & $mask;
            $res .= $chars[$c];
        }
    
        return $res;
    }
    
    function crockford32_decode($data) {
        $map = [
            '0' => 0,
            'O' => 0,
            'o' => 0,
            '1' => 1,
            'I' => 1,
            'i' => 1,
            'L' => 1,
            'l' => 1,
            '2' => 2,
            '3' => 3,
            '4' => 4,
            '5' => 5,
            '6' => 6,
            '7' => 7,
            '8' => 8,
            '9' => 9,
            'A' => 10,
            'a' => 10,
            'B' => 11,
            'b' => 11,
            'C' => 12,
            'c' => 12,
            'D' => 13,
            'd' => 13,
            'E' => 14,
            'e' => 14,
            'F' => 15,
            'f' => 15,
            'G' => 16,
            'g' => 16,
            'H' => 17,
            'h' => 17,
            'J' => 18,
            'j' => 18,
            'K' => 19,
            'k' => 19,
            'M' => 20,
            'm' => 20,
            'N' => 21,
            'n' => 21,
            'P' => 22,
            'p' => 22,
            'Q' => 23,
            'q' => 23,
            'R' => 24,
            'r' => 24,
            'S' => 25,
            's' => 25,
            'T' => 26,
            't' => 26,
            'V' => 27,
            'v' => 27,
            'W' => 28,
            'w' => 28,
            'X' => 29,
            'x' => 29,
            'Y' => 30,
            'y' => 30,
            'Z' => 31,
            'z' => 31,
        ];
    
        $data = strtolower($data);
        $dataSize = strlen($data);
        $buf = 0;
        $bufSize = 0;
        $res = '';
    
        for($i = 0; $i < $dataSize; $i++) {
            $c = $data[$i];
            if(!isset($map[$c])) {
                throw new \Exception("Unsupported character $c (0x".bin2hex($c).") at position $i");
            }
            $b = $map[$c];
            $buf = ($buf << 5) | $b;
            $bufSize += 5;
            if($bufSize > 7) {
                $bufSize -= 8;
                $b = ($buf & (0xff << $bufSize)) >> $bufSize;
                $res .= chr($b);
            }
        }
    
        return $res;
    }
    

    【讨论】:

      【解决方案2】:

      试试这个:https://github.com/bbars/utils/blob/master/php-base32-encode-decode/Base32.php

      使用不区分大小写的字母 [0-9, a-v] 并且比 Base2n(5) 运行得更快:

      size   | Base32::encode  | Base32::decode  | $base2n->encode  | $base2n->decode
      -------------------------------------------------------------------------------
      1      | 0.0000331401825 | 0.0000088214874 | 0.0002369880676  | 0.0001671314240
      2      | 0.0000050067902 | 0.0000040531158 | 0.0000100135803  | 0.0000081062317
      4      | 0.0000050067902 | 0.0000059604645 | 0.0000097751617  | 0.0000100135803
      8      | 0.0000078678131 | 0.0000100135803 | 0.0000131130219  | 0.0000140666962
      16     | 0.0000128746033 | 0.0000178813934 | 0.0000250339508  | 0.0000250339508
      32     | 0.0000238418579 | 0.0000319480896 | 0.0000441074371  | 0.0000472068787
      64     | 0.0001170635223 | 0.0000629425049 | 0.0000870227814  | 0.0000259876251
      128    | 0.0000879764557 | 0.0001208782196 | 0.0001959800720  | 0.0001759529114
      256    | 0.0001969337463 | 0.0002408027649 | 0.0004429817200  | 0.0003459453583
      512    | 0.0003631114960 | 0.0004880428314 | 0.0021460056305  | 0.0006039142609
      1024   | 0.0014970302582 | 0.0009729862213 | 0.0108621120453  | 0.0015850067139
      2048   | 0.0013530254364 | 0.0018491744995 | 0.0312080383301  | 0.0027630329132
      4096   | 0.0027470588684 | 0.0038080215454 | 0.1312029361725  | 0.0064430236816
      8192   | 0.0064270496368 | 0.0086290836334 | 0.5233020782471  | 0.0121779441833
      16384  | 0.0112588405609 | 0.0167109966278 | 2.0316259860992  | 0.0277659893036
      32768  | 0.0235319137573 | 0.0335960388184 | 11.6220989227295 | 0.0498571395874
      65536  | 0.0478749275208 | 0.0648550987244 |                  |                
      131072 | 0.1030550003052 | 0.1504058837891 |                  |                
      262144 | 0.1995100975037 | 0.2654621601105 |                  |                
      524288 | 0.3903131484985 | 0.5326008796692 |                  |                
      

      【讨论】:

      • 这不是base32,这是base32hex。 base32 使用所有字母并消除 0 和 1,因此仅使用 2 到 7 作为数字并以字母开头。
      • Iscariot,我已经根据 My1 的通知更新了我的实现
      • Crockford base32 版本:gist.github.com/joelharkes/82ac4eb0fd8226649a6118562e3817c4 适合那些正在寻找的人
      • 如果您在谈论替代字母表,我的实现还包含子 Base32hex 类,正如 My1 和 Case 所提到的。
      【解决方案3】:

      对于 PHP 中的 Base32,你可以在这里尝试我的实现:

      https://github.com/ademarre/binary-to-text-php

      复制自 README 文件中的 Base32 示例:

      // RFC 4648 base32 alphabet; case-insensitive
      $base32 = new Base2n(5, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', FALSE, TRUE, TRUE);
      $encoded = $base32->encode('encode this');
      // MVXGG33EMUQHI2DJOM======
      

      它并不慢,它可能会或可能不会比您基准测试的类快,但它不会像base64_encode() 这样的内置 PHP 函数那么快。如果这对您很重要,并且您并不真正关心 Base32 编码,那么您应该只使用十六进制。您可以使用原生 PHP 函数对十六进制进行编码,并且不区分大小写。

      $encoded = bin2hex('encode this'); // 656e636f64652074686973
      $decoded = pack('H*', $encoded);   // encode this
      
      // Alternatively, as of PHP 5.4...
      $decoded = hex2bin($encoded);      // encode this
      

      十六进制的缺点是与 Base32 相比存在更多的数据膨胀。十六进制将数据膨胀 100%,而 Base32 将数据膨胀约 60%。

      【讨论】:

        最近更新 更多