有效的解决方案:在php中使用base32编码

时间:2013-05-07 10:30:46

标签: php url encoding parameters decoding

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

10000解码:

base32:2.3273秒

base64:0.0062秒

我使用的base32类是:

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

有什么方法更简单吗?

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

如果您有更好的小写编码替代方案,我也很乐意听到它们。

3 个答案:

答案 0 :(得分:6)

对于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%。

答案 1 :(得分:5)

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

使用大小写的alpabet [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 |                  |                

答案 2 :(得分: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;
}