简体   繁体   English

在PHP中实现Crockford Base32编码

[英]Implementing the Crockford Base32 encoding in PHP

I'm trying to encode a string using the Crockford Base32 Algorithm . 我正在尝试使用Crockford Base32算法对字符串进行编码。

Unfortunately, my current code only accepts numeric values as input. 不幸的是, 我当前的代码只接受数值作为输入。 I thought of converting the ASCII characters to Decimal or Octal, but then the concatenation of 010 and 100 results in 10100 which makes it impossible to decode this. 我想到将ASCII字符转换为十进制或八进制,但是然后010100的串联导致10100 ,这使得无法对此进行解码。 Is there some way to do this I am not aware of? 有没有办法做到这一点,我不知道?

I believe this should be a more efficient implementation of Crockford Base32 encoding : 我相信这应该是一个更有效的Crockford Base32编码实现

function crockford_encode( $base10 ) {
    return strtr( base_convert( $base10, 10, 32 ),
                  "abcdefghijklmnopqrstuv",
                  "ABCDEFGHJKMNPQRSTVWXYZ" );
}

function crockford_decode( $base32 ) {
    $base32 = strtr( strtoupper( $base32 ), 
                     "ABCDEFGHJKMNPQRSTVWXYZILO",
                     "abcdefghijklmnopqrstuv110" );
    return base_convert( $base32, 32, 10 );
}

( demo on codepad.org ) 在codepad.org上演示

Note that, due to known limitations (or, arguably, bugs) in PHP's base_convert() function, these functions will only return correct results for values that can be accurately represented by PHP's internal numeric type (probably double). 请注意,由于PHP的base_convert()函数中的已知限制(或者,可以说是错误),这些函数只会返回正确的结果,这些值可以由PHP的内部数字类型(可能是double)准确表示。 We can hope that this will be fixed in some future PHP version, but in the mean time, you could always use this drop-in replacement for base_convert() . 我们希望这将在未来的PHP版本中得到修复,但与此同时,您可以随时使用base_convert() - base_convert()替代品


Edit: The easiest way to compute the optional check digit is probably simply like this: 编辑:计算可选校验位的最简单方法可能就是这样:

function crockford_check( $base10 ) {
    return substr( "0123456789ABCDEFGHJKMNPQRSTVWXYZ*~$=U", $base10 % 37, 1 );
}

or, for large numbers: 或者,对于大数字:

function crockford_check( $base10 ) {
    return substr( "0123456789ABCDEFGHJKMNPQRSTVWXYZ*~$=U", bcmod( $base10, 37 ), 1 );
}

We can then use it like this: 然后我们可以像这样使用它:

function crockford_encode_check( $base10 ) {
    return crockford_encode( $base10 ) . crockford_check( $base10 );
}

function crockford_decode_check( $base32 ) {
    $base10 = crockford_decode( substr( $base32, 0, -1 ) );
    if ( strtoupper( substr( $base32, -1 ) ) != crockford_check( $base10 ) ) {
        return null;  // wrong checksum
    }
    return $base10;
}

( demo on codepad.org ) 在codepad.org上演示

Note: (July 18, 2014) The original version of the code above had a bug in the Crockford alphabet strings, such that they read ...WZYZ instead of ...WXYZ , causing some numbers to be encoded and decoded incorrectly. 注意: (2014年7月18日)上面代码的原始版本在Crockford字母表字符串中有一个错误,因此它们读取...WZYZ而不是...WXYZ ,导致某些数字被编码和解码不正确。 This bug has now been fixed, and the codepad.org versions now include a basic self-test routine to verify this. 这个bug现在已得到修复,而codepad.org版本现在包含一个基本的自测例程来验证这一点。 Thanks to James Firth for spotting the bug and fixing it. 感谢James Firth发现了这个漏洞并修复它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM