2012-12-28 32 views
3

我试图使用Crockford Base32 Algorithm编码一个字符串。在PHP中实现Crockford Base32编码

不幸的是,my current code只接受数值作为输入。我想将ASCII字符转换为十进制或八进制,但是010100的连接结果为10100,这使得无法对此进行解码。有没有办法做到这一点我不知道?

+1

文档正在向函数传递一个字符串? 'Crockford :: encode('519571');' – BenM

+1

如果你看看源代码,这些将被转换为整数 – Stefan

+0

我做了一个(非常糟糕的)Base32库,你可以试试:https://github.com/NTICompass/PHP -Base32 –

回答

8

我相信这应该是一个更有效的实现的Crockford Base32 encoding

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

需要注意的是,由于PHP的base_convert()功能已知的限制(或者,可以说,漏洞),这些函数只会返回正确的结果,以便可以用PHP的内部数值类型(可能是双精度值)准确表示值。我们希望这将在未来的某个PHP版本中得到解决,但同时,您可以始终使用this drop-in replacement for base_convert()


编辑:计算可选校验数位最简单的方法可能是只是这样的:

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

,或者对于大量:

function crockford_check($base10) { 
    return substr("ABCDEFGHJKMNPQRSTVWXYZ*~$=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; 
} 

demo on codepad.org

注:(2014年7月18日)代码的最初版本以上曾在克罗克福德字母串的错误,这样他们阅读...WZYZ代替...WXYZ,导致一些号码是编码和解码不正确。这个bug现在已经被修复了,codepad.org版本现在包含一个基本的自测例程来验证这个。感谢James Firth发现错误并修复它。

+0

这将是完美的,谢谢。 – Stefan

+0

我需要在这里稍微休息一下,但我会在今天晚些时候看到有关实施支票数字的情况。 –

+0

无论如何我现在都要睡觉,但是谢谢! – Stefan