Base64 另一种解码方法

Base64 的另一种解码方法

常规的方法一般有设定一个 127 字节的反向转换表. 这种查表法网上有很多,这里不再讲述.
下面将要使用的是另一种方法, 只需要使用18字节的反向驱动表.我不知道还有没有其他
人想到, 不过即然我了解了, 也让大家分享一下这个想法.

第一步. 观察
    Base64 编码里面只会出现以下的字符集:
    A to Z, a to Z, 0 to 9, +, -, =
    至于 = 是属于PADDING 字符,出现的话必然会在最后出现,所以我们先不考虑它.
    好的, 我们利用ASCII 标准码表可以知道下面的事实.

    A to Z: 65 to 90,  二进制即( 01000001 to 01011010 )
    a to z: 97 to 122, 二进制即( 01100001 to 01111010 )
    0 to 9: 48 to 57, 二进制即(  00110000 to 00111001 )
    +: 43 二进制即(  00101011 )
    -: 47 二进制即(  00101111 )
   
    上面的二进制有个特性,你注意到了吗? 对,请注意高4位.
    0 to 9: 高4位为 0011 ( 3 )
    a to z: 高4位为 0110 和 0111 ( 6, 7 )
    A to Z: 高4位为 0100 和 0101 ( 4, 5 )
    + , - : 高4位为 0010 ( 2 )
 
    根据BASE64编码表,我们必须根据编码还原出在表中的序号.
    A to Z: 需要减去 65
    a to z: 需要减去 71
    0 to 9: 需要加上 4
    + :需要加上 19
    - :需要加上 19 - 3 = 16

   设定一个加减驱动表,根据它们的高4位来得到应该加减的值, 索引即是高4位减去2.于是,它们可能的取值就是:
    0,1,2,3,4,5

   于是有: { 19, 4, -65, -65, -71, -71 }

   好了,还有一个麻烦就是 +,- 虽然在同一组,但是 - 需要在加上 19后再减去3 修正.所以我们不得不再次来考虑这个问题.
   +,- 两个符号的第2位是有区别的, 所以我们制定了一个附加条件转换序列来根据第2位来得到一个修正值. 当然, 除了+,- 以外
   其他的组根本不需要, 附加修正值为0.所以我们有了根据第2位来加载的附加修正表:
   { 0,-3},{0,0},{0,0},{0,0},{0,0},{0,0}

   将两张表结合起来,有了反向转换表:
   char Base64Code_RevTbl[6][3] = {{ 19,0,-3},{4,0,0},{-65,0,0},{-65,0,0},{-97,0,0},{-97,0,0}}
  

第二步, 使用
   如何使用上面的反向转换表呢? 编码后的BASE64 是4的倍数. 假定有4个字节的已经编码的BASE64码.我们需要将其转换出来.
( 注意,这里不考虑这4个字节中最后二个字符可能是=符号的问题,因为那个问题比效简单,而且与当前的话题不相关 )


   我们假定有下面的定义:
   char r0,r1,r2,r3
   sp[] 为输入的BASE64编码字.

   r0 = ( sp[ 0 ] >> 4 ) & 15 - 2; r1 = ( sp[ 1 ] >> 4 ) & 15 - 2; 
   r2 = ( sp[ 2 ] >> 4 ) & 15 - 2; r3 = ( sp[ 3 ] >> 4 ) & 15 - 2;
   r0 = sp[ 0 ] + Base64Code_RevTbl[ r0 ][ 0 ] + Base64Code_RevTbl[ r0 ][ (( sp[ 0 ] >> 2 ) & 1 ) + 1 ];
   r1 = sp[ 1 ] + Base64Code_RevTbl[ r1 ][ 0 ] + Base64Code_RevTbl[ r1 ][ (( sp[ 0 ] >> 2 ) & 1 ) + 1 ];
   r2 = sp[ 2 ] + Base64Code_RevTbl[ r2 ][ 0 ] + Base64Code_RevTbl[ r2 ][ (( sp[ 0 ] >> 2 ) & 1 ) + 1 ];
   r3 = sp[ 3 ] + Base64Code_RevTbl[ r3 ][ 0 ] + Base64Code_RevTbl[ r3 ][ (( sp[ 0 ] >> 2 ) & 1 ) + 1 ];
  
   明显的,为了得到序号, 我们进行了三次加法. 如上面的 r0:
    r0 = ( sp[ 0 ] >> 4 ) & 15; 我们得到了sp[0]所属的组.
    sp[0] + Base64Code_RevTbl[ r0 ][ 0 ] 得到了没有修正的序号, 如果 sp[0]是 +或者-符号的话,序号会出错. , 我们再加上修正值,
    Base64Code_RevTbl[ r0 ][ (( sp[ 0 ] >> 2 ) & 1 ) + 1 ] 根据符号的第2位来得到符号修正值, ((sp[0]>>2)&1)+1 的结果只可能是 1
或者2. 我们就根据它所属的组r0,再得到修正值.

   从反向转换表来说,只有当符号为-时,才会有附加值-3的出现,其他均为0.

   既然序号得到了, 那么, 下面最简单的事就是将4个序号合并成三个字节了.

   题外话: 对于=符号,其实不必担心,根据源数据的最后2个字节,只会有三种情况出现。
   第一种情况:没有=符号。这种情况下,r0,r1,r2,r3都是正确的。只需要将它们组成三个字节即可。
   第二种情况:有一个=符号。这种情况下,r3就是错误的。只需要使用 r0,r1,r2产生二个字节即可。
   第三种情况:有二个=符号。哦太好了,只需要使用 r0,r1产生一个字节即可。
   其他情况:....源数据都是错误的。

   而根据 r0,r1,r2,r3 产生三个字节的方法也简单,如下:

   dp[ 0 ] = ( r0 << 2 ) | (( r1 >> 4 ) & 0x03 );
   dp[ 1 ] = ( r1 << 4 ) | (( r2 >> 2 ) & 0x0f );
   dp[ 2 ] = ( r2 << 6 ) | r3;

   

 


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值