我正在尝试使用Crockford Base32 Algorithm对字符串进行编码。
不幸的是,我当前的代码只接受数值作为输入。我曾想过将 ASCII 字符转换为十进制或八进制,但随后的串联010
和100
导致10100
无法解码。有什么方法可以做到这一点我不知道吗?
我正在尝试使用Crockford Base32 Algorithm对字符串进行编码。
不幸的是,我当前的代码只接受数值作为输入。我曾想过将 ASCII 字符转换为十进制或八进制,但随后的串联010
和100
导致10100
无法解码。有什么方法可以做到这一点我不知道吗?
我相信这应该是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 );
}
请注意,由于 PHPbase_convert()
函数中的已知限制(或者可以说是错误),这些函数只会返回正确的结果,这些值可以由 PHP 的内部数字类型(可能是 double)准确表示。我们可以希望这将在未来的一些 PHP 版本中得到修复,但与此同时,您始终可以使用这个插件替代base_convert()
.
编辑:计算可选校验位的最简单方法可能是这样的:
function crockford_check( $base10 ) {
return substr( "0123456789ABCDEFGHJKMNPQRSTVWXYZ*~$=U", $base10 % 37, 1 );
}
或者,对于大量:
function crockford_check( $base10 ) {
return substr( "0123456789ABCDEFGHJKMNPQRSTVWXYZ*~$=U", bcmod( $base10, 37 ), 1 );
}
然后我们可以像这样使用它:
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;
}
注意:(2014 年 7 月 18 日)上述代码的原始版本在 Crockford 字母字符串中存在错误,因此它们读取...WZYZ
而不是...WXYZ
,导致某些数字编码和解码不正确。此错误现已修复,codepad.org 版本现在包含一个基本的自检例程来验证这一点。感谢James Firth发现并修复了它。