1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.ws.security.util;
19
20 import org.apache.ws.security.WSSecurityException;
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 public final class Base64 {
37
38 private static final int BASELENGTH = 128;
39 private static final int LOOKUPLENGTH = 64;
40 private static final int TWENTYFOURBITGROUP = 24;
41 private static final int EIGHTBIT = 8;
42 private static final int SIXTEENBIT = 16;
43 private static final int FOURBYTE = 4;
44 private static final int SIGN = -128;
45 private static final char PAD = '=';
46 private static final byte[] BASE_64_ALPHABET = new byte[BASELENGTH];
47 private static final char[] LOOKUP_BASE_64_ALPHABET = new char[LOOKUPLENGTH];
48
49 static {
50
51 for (int i = 0; i < BASELENGTH; ++i) {
52 BASE_64_ALPHABET[i] = -1;
53 }
54 for (int i = 'Z'; i >= 'A'; i--) {
55 BASE_64_ALPHABET[i] = (byte) (i - 'A');
56 }
57 for (int i = 'z'; i >= 'a'; i--) {
58 BASE_64_ALPHABET[i] = (byte) (i - 'a' + 26);
59 }
60
61 for (int i = '9'; i >= '0'; i--) {
62 BASE_64_ALPHABET[i] = (byte) (i - '0' + 52);
63 }
64
65 BASE_64_ALPHABET['+'] = 62;
66 BASE_64_ALPHABET['/'] = 63;
67
68 for (int i = 0; i <= 25; i++) {
69 LOOKUP_BASE_64_ALPHABET[i] = (char) ('A' + i);
70 }
71
72 for (int i = 26, j = 0; i <= 51; i++, j++) {
73 LOOKUP_BASE_64_ALPHABET[i] = (char) ('a' + j);
74 }
75
76 for (int i = 52, j = 0; i <= 61; i++, j++) {
77 LOOKUP_BASE_64_ALPHABET[i] = (char) ('0' + j);
78 }
79 LOOKUP_BASE_64_ALPHABET[62] = (char) '+';
80 LOOKUP_BASE_64_ALPHABET[63] = (char) '/';
81
82 }
83
84 protected static boolean isWhiteSpace(char octect) {
85 return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
86 }
87
88 protected static boolean isPad(char octect) {
89 return (octect == PAD);
90 }
91
92 protected static boolean isData(char octect) {
93 return (octect < BASELENGTH && BASE_64_ALPHABET[octect] != -1);
94 }
95
96 protected static boolean isBase64(char octect) {
97 return (isWhiteSpace(octect) || isPad(octect) || isData(octect));
98 }
99
100
101
102
103
104
105
106
107 public static String encode(byte[] binaryData) {
108
109 if (binaryData == null) {
110 return null;
111 }
112
113 int lengthDataBits = binaryData.length * EIGHTBIT;
114 if (lengthDataBits == 0) {
115 return "";
116 }
117
118 int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
119 int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
120 int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1
121 : numberTriplets;
122 char encodedData[] = null;
123
124 encodedData = new char[numberQuartet * 4];
125
126 byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
127
128 int encodedIndex = 0;
129 int dataIndex = 0;
130
131 for (int i = 0; i < numberTriplets; i++) {
132 b1 = binaryData[dataIndex++];
133 b2 = binaryData[dataIndex++];
134 b3 = binaryData[dataIndex++];
135
136 l = (byte) (b2 & 0x0f);
137 k = (byte) (b1 & 0x03);
138
139 byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
140 : (byte) ((b1) >> 2 ^ 0xc0);
141
142 byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
143 : (byte) ((b2) >> 4 ^ 0xf0);
144 byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6)
145 : (byte) ((b3) >> 6 ^ 0xfc);
146
147 encodedData[encodedIndex++] = LOOKUP_BASE_64_ALPHABET[val1];
148 encodedData[encodedIndex++] = LOOKUP_BASE_64_ALPHABET[val2
149 | (k << 4)];
150 encodedData[encodedIndex++] = LOOKUP_BASE_64_ALPHABET[(l << 2)
151 | val3];
152 encodedData[encodedIndex++] = LOOKUP_BASE_64_ALPHABET[b3 & 0x3f];
153 }
154
155
156 if (fewerThan24bits == EIGHTBIT) {
157 b1 = binaryData[dataIndex];
158 k = (byte) (b1 & 0x03);
159
160 byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
161 : (byte) ((b1) >> 2 ^ 0xc0);
162 encodedData[encodedIndex++] = LOOKUP_BASE_64_ALPHABET[val1];
163 encodedData[encodedIndex++] = LOOKUP_BASE_64_ALPHABET[k << 4];
164 encodedData[encodedIndex++] = PAD;
165 encodedData[encodedIndex++] = PAD;
166 } else if (fewerThan24bits == SIXTEENBIT) {
167 b1 = binaryData[dataIndex];
168 b2 = binaryData[dataIndex + 1];
169 l = (byte) (b2 & 0x0f);
170 k = (byte) (b1 & 0x03);
171
172 byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
173 : (byte) ((b1) >> 2 ^ 0xc0);
174 byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
175 : (byte) ((b2) >> 4 ^ 0xf0);
176
177 encodedData[encodedIndex++] = LOOKUP_BASE_64_ALPHABET[val1];
178 encodedData[encodedIndex++] = LOOKUP_BASE_64_ALPHABET[val2
179 | (k << 4)];
180 encodedData[encodedIndex++] = LOOKUP_BASE_64_ALPHABET[l << 2];
181 encodedData[encodedIndex++] = PAD;
182 }
183
184 return new String(encodedData);
185 }
186
187
188
189
190
191
192
193
194 public static byte[] decode(String encoded) throws WSSecurityException {
195
196 if (encoded == null) {
197 return null;
198 }
199
200 char[] base64Data = encoded.toCharArray();
201
202 int len = removeWhiteSpace(base64Data);
203
204 if (len % FOURBYTE != 0) {
205 throw new WSSecurityException("decoding.divisible.four");
206 }
207
208 int numberQuadruple = (len / FOURBYTE);
209
210 if (numberQuadruple == 0) {
211 return new byte[0];
212 }
213
214 byte decodedData[] = null;
215 byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
216 char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
217
218 int i = 0;
219 int encodedIndex = 0;
220 int dataIndex = 0;
221 decodedData = new byte[(numberQuadruple) * 3];
222
223 for (; i < numberQuadruple - 1; i++) {
224
225 if (!isData((d1 = base64Data[dataIndex++]))
226 || !isData((d2 = base64Data[dataIndex++]))
227 || !isData((d3 = base64Data[dataIndex++]))
228 || !isData((d4 = base64Data[dataIndex++]))) {
229 throw new WSSecurityException("decoding.general");
230
231
232
233 }
234
235 b1 = BASE_64_ALPHABET[d1];
236 b2 = BASE_64_ALPHABET[d2];
237 b3 = BASE_64_ALPHABET[d3];
238 b4 = BASE_64_ALPHABET[d4];
239
240 decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
241 decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
242 decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
243 }
244
245 if (!isData((d1 = base64Data[dataIndex++]))
246 || !isData((d2 = base64Data[dataIndex++]))) {
247 throw new WSSecurityException("decoding.general");
248
249
250 }
251
252 b1 = BASE_64_ALPHABET[d1];
253 b2 = BASE_64_ALPHABET[d2];
254
255 d3 = base64Data[dataIndex++];
256 d4 = base64Data[dataIndex++];
257 if (!isData((d3)) || !isData((d4))) {
258 if (isPad(d3) && isPad(d4)) {
259 if ((b2 & 0xf) != 0) {
260 throw new WSSecurityException("decoding.general");
261 }
262 byte[] tmp = new byte[i * 3 + 1];
263 System.arraycopy(decodedData, 0, tmp, 0, i * 3);
264 tmp[encodedIndex] = (byte)(b1 << 2 | b2 >> 4);
265 return tmp;
266 } else if (!isPad(d3) && isPad(d4)) {
267 b3 = BASE_64_ALPHABET[d3];
268 if ((b3 & 0x3) != 0) {
269 throw new WSSecurityException("decoding.general");
270 }
271 byte[] tmp = new byte[i * 3 + 2];
272 System.arraycopy(decodedData, 0, tmp, 0, i * 3);
273 tmp[encodedIndex++] = (byte)(b1 << 2 | b2 >> 4);
274 tmp[encodedIndex] = (byte)(((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
275 return tmp;
276 } else {
277 throw new WSSecurityException("decoding.general");
278
279
280
281
282
283
284
285 }
286 } else {
287 b3 = BASE_64_ALPHABET[d3];
288 b4 = BASE_64_ALPHABET[d4];
289 decodedData[encodedIndex++] = (byte)(b1 << 2 | b2 >> 4);
290 decodedData[encodedIndex++] = (byte)(((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
291 decodedData[encodedIndex++] = (byte)(b3 << 6 | b4);
292 }
293
294 return decodedData;
295 }
296
297
298
299
300
301
302
303
304 protected static int removeWhiteSpace(char[] data) {
305 if (data == null) {
306 return 0;
307 }
308
309
310 int newSize = 0;
311 int len = data.length;
312 for (int i = 0; i < len; i++) {
313 if (!isWhiteSpace(data[i])) {
314 data[newSize++] = data[i];
315 }
316 }
317 return newSize;
318 }
319 }