在编写解码小工具的过程中,我发现自动识别密文模式时,正则表达式匹配的方式比计算长度等方式效果更显著,因此搜集了一些资料,发现零散在github的各个角落,并且十分不完整。收集到一起写一篇随笔,总结一下Base家族编码的正则表达式匹配。
1、Base64
将编码分割为每六个二进制位一组进行编码,一个字节为八个二进制位,故无论如何应用0补齐至其最小公倍数24以方便解码操作,将000000编码为‘=’,这就是为什么Base64的末尾可能有一到两个‘=’的原因。
编码表包括A-Za-z0-9和符号‘+’,‘/‘,且由于补齐机制,其出现时必然以24/6=4个为一组。
2、Base32
将编码分割为每五个二进制位一组进行编码,故无论如何应用0补齐至其最小公倍数40以方便解码操作,将00000编码为‘=’,故Base32的末尾可能有:
- 0个’=‘:40/40
- 1个’=‘:32/40
- 3个’=‘:24/40
- 4个’=‘:16/40
- 6个’=‘:8/40
编码表包括A-Z2-7,且由于补齐机制,其出现时必然以40/5=8个为一组。
3、Base16
Base16就是hex,其表达式由0-9和A-F组成,且必然以两个一组出现。
4、Base58
不同于以上部分,58不再是2的整幂次,但是其加密本质依然是相同的:进制转换。将原二进制转化成十进制再转成58进制,然后根据编码表编码每一位。
编码表在Base64的基础上去掉了两个符号和易于混淆的四个字符’0‘,’I‘,’l‘,’O‘。
5、Base85
Base85的编码逻辑类似于Base58,而其编码表则是考虑了在ascii码的可见字符集中去掉了最靠后的一小部分。(从33-117)
下面是实际的正则表达式,以python的字典形式给出:
1 Pattern ={"Base64":"^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$", 2 "Base32":"^([A-Z2-7]{8})*(([A-Z2-7]{8})|([A-Z2-7]{7}=)|([A-Z2-7]{5}===)|([A-Z2-7]{4}====)|([A-Z2-7]{2}======))$", 3 "Base16":"^([A-F0-9]{2})*$", 4 "Base58":"^[A-HJ-NP-Za-km-z1-9]*$", 5 "Base85":"^[!\"#\$%&‘\(\)\*\+,-\./0-9:;<=>\?@A-Z\[\\\]\^_`a-u]*$"}