懒羊羊
2024-01-31 e57a8990ae56f657a59c435a0613c5f7a8728003
提交 | 用户 | 时间
e57a89 1 package com.jcdm.common.utils.sign;
2
3 /**
4  * Base64工具类
5  * 
6  * @author jc
7  */
8 public final class Base64
9 {
10     static private final int     BASELENGTH           = 128;
11     static private final int     LOOKUPLENGTH         = 64;
12     static private final int     TWENTYFOURBITGROUP   = 24;
13     static private final int     EIGHTBIT             = 8;
14     static private final int     SIXTEENBIT           = 16;
15     static private final int     FOURBYTE             = 4;
16     static private final int     SIGN                 = -128;
17     static private final char    PAD                  = '=';
18     static final private byte[]  base64Alphabet       = new byte[BASELENGTH];
19     static final private char[]  lookUpBase64Alphabet = new char[LOOKUPLENGTH];
20
21     static
22     {
23         for (int i = 0; i < BASELENGTH; ++i)
24         {
25             base64Alphabet[i] = -1;
26         }
27         for (int i = 'Z'; i >= 'A'; i--)
28         {
29             base64Alphabet[i] = (byte) (i - 'A');
30         }
31         for (int i = 'z'; i >= 'a'; i--)
32         {
33             base64Alphabet[i] = (byte) (i - 'a' + 26);
34         }
35
36         for (int i = '9'; i >= '0'; i--)
37         {
38             base64Alphabet[i] = (byte) (i - '0' + 52);
39         }
40
41         base64Alphabet['+'] = 62;
42         base64Alphabet['/'] = 63;
43
44         for (int i = 0; i <= 25; i++)
45         {
46             lookUpBase64Alphabet[i] = (char) ('A' + i);
47         }
48
49         for (int i = 26, j = 0; i <= 51; i++, j++)
50         {
51             lookUpBase64Alphabet[i] = (char) ('a' + j);
52         }
53
54         for (int i = 52, j = 0; i <= 61; i++, j++)
55         {
56             lookUpBase64Alphabet[i] = (char) ('0' + j);
57         }
58         lookUpBase64Alphabet[62] = (char) '+';
59         lookUpBase64Alphabet[63] = (char) '/';
60     }
61
62     private static boolean isWhiteSpace(char octect)
63     {
64         return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
65     }
66
67     private static boolean isPad(char octect)
68     {
69         return (octect == PAD);
70     }
71
72     private static boolean isData(char octect)
73     {
74         return (octect < BASELENGTH && base64Alphabet[octect] != -1);
75     }
76
77     /**
78      * Encodes hex octects into Base64
79      *
80      * @param binaryData Array containing binaryData
81      * @return Encoded Base64 array
82      */
83     public static String encode(byte[] binaryData)
84     {
85         if (binaryData == null)
86         {
87             return null;
88         }
89
90         int lengthDataBits = binaryData.length * EIGHTBIT;
91         if (lengthDataBits == 0)
92         {
93             return "";
94         }
95
96         int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
97         int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
98         int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
99         char encodedData[] = null;
100
101         encodedData = new char[numberQuartet * 4];
102
103         byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
104
105         int encodedIndex = 0;
106         int dataIndex = 0;
107
108         for (int i = 0; i < numberTriplets; i++)
109         {
110             b1 = binaryData[dataIndex++];
111             b2 = binaryData[dataIndex++];
112             b3 = binaryData[dataIndex++];
113
114             l = (byte) (b2 & 0x0f);
115             k = (byte) (b1 & 0x03);
116
117             byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
118             byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
119             byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
120
121             encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
122             encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
123             encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
124             encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
125         }
126
127         // form integral number of 6-bit groups
128         if (fewerThan24bits == EIGHTBIT)
129         {
130             b1 = binaryData[dataIndex];
131             k = (byte) (b1 & 0x03);
132             byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
133             encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
134             encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
135             encodedData[encodedIndex++] = PAD;
136             encodedData[encodedIndex++] = PAD;
137         }
138         else if (fewerThan24bits == SIXTEENBIT)
139         {
140             b1 = binaryData[dataIndex];
141             b2 = binaryData[dataIndex + 1];
142             l = (byte) (b2 & 0x0f);
143             k = (byte) (b1 & 0x03);
144
145             byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
146             byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
147
148             encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
149             encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
150             encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
151             encodedData[encodedIndex++] = PAD;
152         }
153         return new String(encodedData);
154     }
155
156     /**
157      * Decodes Base64 data into octects
158      *
159      * @param encoded string containing Base64 data
160      * @return Array containind decoded data.
161      */
162     public static byte[] decode(String encoded)
163     {
164         if (encoded == null)
165         {
166             return null;
167         }
168
169         char[] base64Data = encoded.toCharArray();
170         // remove white spaces
171         int len = removeWhiteSpace(base64Data);
172
173         if (len % FOURBYTE != 0)
174         {
175             return null;// should be divisible by four
176         }
177
178         int numberQuadruple = (len / FOURBYTE);
179
180         if (numberQuadruple == 0)
181         {
182             return new byte[0];
183         }
184
185         byte decodedData[] = null;
186         byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
187         char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
188
189         int i = 0;
190         int encodedIndex = 0;
191         int dataIndex = 0;
192         decodedData = new byte[(numberQuadruple) * 3];
193
194         for (; i < numberQuadruple - 1; i++)
195         {
196
197             if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
198                     || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++])))
199             {
200                 return null;
201             } // if found "no data" just return null
202
203             b1 = base64Alphabet[d1];
204             b2 = base64Alphabet[d2];
205             b3 = base64Alphabet[d3];
206             b4 = base64Alphabet[d4];
207
208             decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
209             decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
210             decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
211         }
212
213         if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])))
214         {
215             return null;// if found "no data" just return null
216         }
217
218         b1 = base64Alphabet[d1];
219         b2 = base64Alphabet[d2];
220
221         d3 = base64Data[dataIndex++];
222         d4 = base64Data[dataIndex++];
223         if (!isData((d3)) || !isData((d4)))
224         {// Check if they are PAD characters
225             if (isPad(d3) && isPad(d4))
226             {
227                 if ((b2 & 0xf) != 0)// last 4 bits should be zero
228                 {
229                     return null;
230                 }
231                 byte[] tmp = new byte[i * 3 + 1];
232                 System.arraycopy(decodedData, 0, tmp, 0, i * 3);
233                 tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
234                 return tmp;
235             }
236             else if (!isPad(d3) && isPad(d4))
237             {
238                 b3 = base64Alphabet[d3];
239                 if ((b3 & 0x3) != 0)// last 2 bits should be zero
240                 {
241                     return null;
242                 }
243                 byte[] tmp = new byte[i * 3 + 2];
244                 System.arraycopy(decodedData, 0, tmp, 0, i * 3);
245                 tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
246                 tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
247                 return tmp;
248             }
249             else
250             {
251                 return null;
252             }
253         }
254         else
255         { // No PAD e.g 3cQl
256             b3 = base64Alphabet[d3];
257             b4 = base64Alphabet[d4];
258             decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
259             decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
260             decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
261
262         }
263         return decodedData;
264     }
265
266     /**
267      * remove WhiteSpace from MIME containing encoded Base64 data.
268      *
269      * @param data the byte array of base64 data (with WS)
270      * @return the new length
271      */
272     private static int removeWhiteSpace(char[] data)
273     {
274         if (data == null)
275         {
276             return 0;
277         }
278
279         // count characters that's not whitespace
280         int newSize = 0;
281         int len = data.length;
282         for (int i = 0; i < len; i++)
283         {
284             if (!isWhiteSpace(data[i]))
285             {
286                 data[newSize++] = data[i];
287             }
288         }
289         return newSize;
290     }
291 }