zoukankan      html  css  js  c++  java
  • Base64加密转换原理与代码实现

    一、Base64实现转换原理

      它是用64个可打印字符表示二进制所有数据方法。由于2的6次方等于64,所以可以用每6个位元(bit)为一个单元,对应某个可打印字符。我们知道三个字节(byte)有24个位元,就可以刚好对应于4个Base64单元,即3个字节需要用4个Base64的可打印字符来表示。

      · 可打印符号:

      在Base64中的可打印字符包括字母A-Z、a-z、数字0-9 ,这样共有62个字符,此外两个可打印符号在不同的系统中一般有所不同。但是,我们经常所说的Base64另外2个字符是:“+/”。这64个字符,所对应表如下:

    编号字符 编号字符 编号字符 编号字符
    0 A 16 Q 32 g 48 w
    1 B 17 R 33 h 49 x
    2 C 18 S 34 i 50 y
    3 D 19 T 35 j 51 z
    4 E 20 U 36 k 52 0
    5 F 21 V 37 l 53 1
    6 G 22 W 38 m 54 2
    7 H 23 X 39 n 55 3
    8 I 24 Y 40 o 56 4
    9 J 25 Z 41 p 57 5
    10 K 26 a 42 q 58 6
    11 L 27 b 43 r 59 7
    12 M 28 c 44 s 60 8
    13 N 29 d 45 t 61 9
    14 O 30 e 46 u 62 +
    15 P 31 f 47 v 63 /

      

      仔细思考一下,你会很快发现,一个问题,就是每次转换的字节数不一定就是24的整数倍,会出现有多余不足六位的情况,在base64中处理的方法是加零凑够六位,但是这样一来在解码的时候就会出现多余的位  这该怎么办呢? base64想到了一个很好的解决办法。这个办法就是在 base64凑零的同时,还要满足凑出来的位数是8的倍数,不然就加一个或者两个特殊的六位  =  符号。为什么是一个或者两个=符号呢? 因为多个8位转为6位 只会出现 剩余 2位,4位的情况,剩余2位 只需要一个 表示六位的 =  便可变为8的整数;而剩余4位 需要两个表示6位的 = 便可以变成16 是8的整数。然后在解密的时候不解析 =即可。

         之所以位的总数需要凑成8的倍数,是因为base64主要用于加密后的数据传送,而在传送机制中都认为传送的最小单位是按照字节算的,所以不能出现不是位总数不是8的倍数的情况,在接收到数据后,按顺序将6位的base64直接按照顺序解密成字节就完成解密了。

    · 转换过程:

        ① 将三个byte(字节)的数据,先后放入一个24bit(位)的缓冲区中,先来的byte占高位。数据不足 3 byte的话,于缓冲区中剩下的bit用0补足。

        ② 然后,每次取出6个bit,按照其值选择 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ 中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。

           ③    如果最后剩下两个输入数据,在编码结果后加1个“=”;

          如果最后剩下一个输入数据,编码结果后加2个“=”;

          如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。

       编码后的数据比原始数据略长,为原来的4/3。

    文本 M a n
    ASCII编码 77 97 110
    二进制位 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 0
    索引 19 22 5 46
    Base64编码 T W F u

         M的Ascii码是77,前六位对应值为19,对应base64字符是T,如此类推。其它字符编码就可以自动转换得到!我们看看另外不是刚好是3个字节的情况!

    文本(1 Byte) A    
    二进制位 0 1 0 0 0 0 0 1                                
    二进制位(补0) 0 1 0 0 0 0 0 1 0 0 0 0                        
    Base64编码 Q Q = =
    文本(2 Byte) B C  
    二进制位 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1     x x x x x x
    二进制位(补0) 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 0 0 x x x x x x
    Base64编码 Q k M  =

    二、Base64转换代码实现

     1 public class Base64Util {
     2     private static final char last2byte = (char) Integer.parseInt("00000011", 2);
     3     private static final char last4byte = (char) Integer.parseInt("00001111", 2);
     4     private static final char last6byte = (char) Integer.parseInt("00111111", 2);
     5     private static final char lead6byte = (char) Integer.parseInt("11111100", 2);
     6     private static final char lead4byte = (char) Integer.parseInt("11110000", 2);
     7     private static final char lead2byte = (char) Integer.parseInt("11000000", 2);
     8     private static final char[] encodeTable = new char[]
     9             {
    10                     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
    11                     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
    12                     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
    13                     'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
    14             };
    15 
    16     public Base64Util() {
    17     }
    18 
    19     public static String encode(byte[] from) {
    20         StringBuilder to = new StringBuilder((int) ((double) from.length * 1.34D) + 3);
    21         int num = 0;
    22         char currentByte = 0;
    23 
    24         int i;
    25         for (i = 0; i < from.length; ++i) {
    26             for (num %= 8; num < 8; num += 6) {
    27                 switch (num) {
    28                     case 0:
    29                         currentByte = (char) (from[i] & lead6byte);
    30                         currentByte = (char) (currentByte >>> 2);
    31                     case 1:
    32                     case 3:
    33                     case 5:
    34                     default:
    35                         break;
    36                     case 2:
    37                         currentByte = (char) (from[i] & last6byte);
    38                         break;
    39                     case 4:
    40                         currentByte = (char) (from[i] & last4byte);
    41                         currentByte = (char) (currentByte << 2);
    42                         if (i + 1 < from.length) {
    43                             currentByte = (char) (currentByte | (from[i + 1] & lead2byte) >>> 6);
    44                         }
    45                         break;
    46                     case 6:
    47                         currentByte = (char) (from[i] & last2byte);
    48                         currentByte = (char) (currentByte << 4);
    49                         if (i + 1 < from.length) {
    50                             currentByte = (char) (currentByte | (from[i + 1] & lead4byte) >>> 4);
    51                         }
    52                 }
    53 
    54                 to.append(encodeTable[currentByte]);
    55             }
    56         }
    57 
    58         if (to.length() % 4 != 0) {
    59             for (i = 4 - to.length() % 4; i > 0; --i) {
    60                 to.append("=");
    61             }
    62         }
    63 
    64         return to.toString();
    65     }
    66 }
    View Code
  • 相关阅读:
    Linux 系统使用eclipse时顶部菜单栏不见解决办法
    DES 文件加密解密
    Java 做CRC -CCITT x16+x12+x5+1(0x1021),初值为0x0000 校验
    字节流排序低字节在前高字节在后
    burpsuite暴力破解之四种方式
    网络安全之信息收集部分内容
    渗透测试步骤
    PHP与Mysql之间的纠缠(超详细)
    MySQL知识汇总
    PHP文件上传、错误处理
  • 原文地址:https://www.cnblogs.com/jxust-jiege666/p/8590116.html
Copyright © 2011-2022 走看看