phpass的自定义base64编码器:它有名称/优势超过Base64吗?

6

phpassencode64()中使用了一种我不太熟悉的算法来进行base 64编码。而Base64Uuencode是将6个比特位成组线性拆分来生成每个8位字节,然后映射到可打印字符。而encode64则会重新排列这些比特位:

input bit location:    abcdefgh ijklmnop qrstuvwx
base64 bit location:   ..abcdef ..ghijkl ..mnopqr ..stuvwx
encode64 bit location: ..cdefgh ..mnopab ..wxijkl ..qrstuv

这个算法是否广为人知?除了向后兼容之外,为什么选择它而不是Base64?以下是我重写后的内容以澄清该算法:
function encode64($input, $bytesToProcess)
{
    // convert to array of ints
    for ($i = 0; $i < $bytesToProcess; $i++) {
        $bytes[] = ord($input[$i]);
    }

    $octets = array();
    $i = 0;
    do {
        $value = $bytes[$i++];
        $octets[] = $value & 0x3f;
        if ($i < $bytesToProcess) {
            $value |= $bytes[$i] << 8;
        }
        $octets[] = ($value >> 6) & 0x3f;
        if ($i++ >= $bytesToProcess) {
            break;
        }
        if ($i < $bytesToProcess) {
            $value |= $bytes[$i] << 16;
        }
        $octets[] = ($value >> 12) & 0x3f;
        if ($i++ >= $bytesToProcess) {
            break;
        }
        $octets[] = ($value >> 18) & 0x3f;
    } while ($i < $bytesToProcess);

    return array_map(function ($i) {
        return str_pad(base_convert($i, 10, 2), 6, '0', STR_PAD_LEFT);
    }, $octets);
}

var_export(encode64("Man", 3));

(更新以指明每个输入位移动的确切位置)


1
Drupal的端口将此描述为“*nix标准来自crypt()”。 - Steve Clay
谢谢您的提问!我尝试在Go中实现Drupal兼容的身份验证,并使用此包进行base64编码:https://golang.org/src/encoding/base64/base64.go 但是结果是创建并在Drupal中保存的哈希值不匹配。只有在重新实现Go的base64包时,我才像Drupals base64Encode()一样进行了奇怪的位移,哈希值才匹配。 问题是,为什么Drupal或phpass开发人员要以特殊方式进行base64编码。真的是错误吗?我将在Drupal Stackexchange上提出这个问题。 - Hermann Schwarz
2个回答

2

encode64() 看起来只是标准 base64 的实现,但计算的比特顺序相反,并使用了不同的字符集——如果你以正确的方式看,例如选取第一个字节的最后 6 位作为第一个输出字符。这可能只是一个错误;这样做没有安全或性能上的好处(相对于 PHP 原生的 base64_encode 存在一些性能缺陷)。


1
在我看来,它似乎在两端都进行了字节交换:反转3个输入字节的顺序,将它们分成6位块,然后反转输出字节的顺序。 - Simon
1
我认为这会产生相同的效果。无论如何,在某个过程中都需要进行反转。 - user149341

0

encode64使用的字符包括除a-zA-Z0-9之外的"."和"/"。Base64使用的是"+"和"/"。此外,在encode64中,"."和"/"分别映射到0和1,而在Base64中"+"和"/"则分别映射到62和63。

UUencode使用字母、数字和许多标点符号以便与不支持大写字母的系统兼容。

我不熟悉encode64。使用它的唯一原因就是如果在您使用的环境中不允许使用"+"。但是那样的话,您可以使用Base64并进行str_replace操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接