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