1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.net.util;
19
20 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertFalse;
23 import static org.junit.jupiter.api.Assertions.assertNotNull;
24 import static org.junit.jupiter.api.Assertions.assertNull;
25 import static org.junit.jupiter.api.Assertions.assertSame;
26 import static org.junit.jupiter.api.Assertions.assertThrows;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28
29 import java.math.BigInteger;
30 import java.nio.charset.StandardCharsets;
31 import java.util.Base64.Decoder;
32 import java.util.Base64.Encoder;
33
34 import org.apache.commons.lang3.ArrayFill;
35 import org.apache.commons.lang3.ArrayUtils;
36 import org.junit.jupiter.api.Test;
37
38 @SuppressWarnings({ "deprecation" })
39 class Base64Test {
40
41 private static String toString(final byte[] encodedData) {
42 return encodedData != null ? new String(encodedData, StandardCharsets.UTF_8) : null;
43 }
44
45 private void checkDecoders(final String expected, final byte[] actual) {
46 final byte[] decoded = Base64.decodeBase64(actual);
47 assertEquals(expected, toString(decoded));
48 assertEquals(expected, toString(actual != null ? getJreDecoder().decode(actual) : null));
49 assertEquals(expected, toString(new Base64().decode(actual)));
50 }
51
52 private void checkDecoders(final String expected, final String actual) {
53 final byte[] decoded = Base64.decodeBase64(actual);
54 assertEquals(expected, new String(decoded));
55 assertEquals(expected, toString(decoded));
56 assertEquals(expected, toString(actual != null ? getJreDecoder().decode(actual) : null));
57 assertEquals(expected, toString(new Base64().decode(actual)));
58 }
59
60 private Decoder getJreDecoder() {
61 return java.util.Base64.getDecoder();
62 }
63
64 private Encoder getJreEncoder() {
65 return java.util.Base64.getEncoder();
66 }
67
68 private Encoder getJreMimeEncoder() {
69 return java.util.Base64.getMimeEncoder();
70 }
71
72 private Encoder getJreMimeEncoder(final int lineLength, final byte[] lineSeparator) {
73 return java.util.Base64.getMimeEncoder(lineLength, lineSeparator);
74 }
75
76 private Encoder getJreUrlEncoder() {
77 return java.util.Base64.getUrlEncoder();
78 }
79
80 @Test
81 void testBase64() {
82 final Base64 b64 = new Base64();
83 assertFalse(b64.isUrlSafe());
84 }
85
86 @Test
87 void testBase64Boolean() {
88 final Base64 b64 = new Base64(true);
89 assertTrue(b64.isUrlSafe());
90 assertArrayEquals(new byte[] {}, b64.getLineSeparator());
91 }
92
93 @Test
94 void testBase64Int() {
95 Base64 b64;
96 b64 = new Base64(8);
97 assertFalse(b64.isUrlSafe());
98 assertEquals(8, b64.getLineLength());
99 b64 = new Base64(11);
100 assertEquals(8, b64.getLineLength());
101 }
102
103 @Test
104 void testBase64IntByteArray() {
105 final Base64 b64;
106 b64 = new Base64(8, new byte[] {});
107 assertFalse(b64.isUrlSafe());
108 assertArrayEquals(new byte[] {}, b64.getLineSeparator());
109 final String stringToEncode = "<<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>>";
110 final byte[] encodedData = new Base64(Base64.CHUNK_SIZE, Base64.CHUNK_SEPARATOR).encode(stringToEncode.getBytes());
111 assertEquals("PDw/Pz8+Pjw8Pz8/Pj48PD8/Pz4+PDw/Pz8+Pjw8Pz8/Pj48PD8/Pz4+PDw/Pz8+Pjw8Pz8/Pj48\r\nPD8/Pz4+PDw/Pz8+Pjw8Pz8/Pj4=\r\n", toString(encodedData));
112 assertEquals(getJreMimeEncoder().encodeToString(stringToEncode.getBytes()) + "\r\n", toString(encodedData));
113 assertEquals("PDw/Pz8+Pjw8Pz8/Pj48PD8/Pz4+PDw/Pz8+Pjw8Pz8/Pj48PD8/Pz4+PDw/Pz8+Pjw8Pz8/Pj48~PD8/Pz4+PDw/Pz8+Pjw8Pz8/Pj4=~",
114 toString(new Base64(Base64.CHUNK_SIZE, "~".getBytes()).encode(stringToEncode.getBytes())));
115 assertEquals(getJreMimeEncoder(Base64.CHUNK_SIZE, "~".getBytes()).encodeToString(stringToEncode.getBytes()) + "~",
116 toString(new Base64(Base64.CHUNK_SIZE, "~".getBytes()).encode(stringToEncode.getBytes())));
117 assertEquals(getJreMimeEncoder(Base64.CHUNK_SIZE - 2, "~~".getBytes()).encodeToString(stringToEncode.getBytes()) + "~~",
118 toString(new Base64(Base64.CHUNK_SIZE - 2, "~~".getBytes()).encode(stringToEncode.getBytes())));
119 assertEquals(getJreMimeEncoder(Base64.CHUNK_SIZE + 2, "~~~".getBytes()).encodeToString(stringToEncode.getBytes()) + "~~~",
120 toString(new Base64(Base64.CHUNK_SIZE + 2, "~~~".getBytes()).encode(stringToEncode.getBytes())));
121 }
122
123 @Test
124 void testBase64IntByteArrayBoolean() {
125 Base64 b64;
126 b64 = new Base64(8, new byte[] {}, false);
127 assertFalse(b64.isUrlSafe());
128 b64 = new Base64(8, new byte[] {}, true);
129 assertTrue(b64.isUrlSafe());
130 assertThrows(IllegalArgumentException.class, () -> new Base64(8, new byte[] { 'A' }, false));
131 }
132
133 @Test
134 void testDecodeBase64ByteArray() {
135 checkDecoders("light w", new byte[] { 'b', 'G', 'l', 'n', 'a', 'H', 'Q', 'g', 'd', 'w', '=', '=' });
136 }
137
138 @Test
139 void testDecodeBase64String() {
140 checkDecoders("light w", "bGlnaHQgdw==");
141 }
142
143 @Test
144 void testDecodeByteArray() {
145 checkDecoders("foobar", new byte[] { 'Z', 'm', '9', 'v', 'Y', 'm', 'F', 'y' });
146 }
147
148 @Test
149 void testDecodeByteArrayEmpty() {
150 checkDecoders("", new byte[] {});
151 checkDecoders(null, (byte[]) null);
152
153 }
154
155 @Test
156 void testDecodeByteArrayNull() {
157 assertNull(new Base64().decode((byte[]) null));
158 }
159
160 @Test
161 void testDecodeInteger() {
162 testDecodeInteger(BigInteger.ONE);
163 testDecodeInteger(BigInteger.TEN);
164 testDecodeInteger(BigInteger.ZERO);
165 }
166
167 private void testDecodeInteger(final BigInteger bi) {
168 assertEquals(bi, Base64.decodeInteger(getJreEncoder().encode(bi.toByteArray())));
169 }
170
171 @Test
172 void testDecodeNullString() {
173 final Base64 base64 = new Base64();
174 assertThrows(NullPointerException.class, () -> base64.decode((String) null));
175 }
176
177 @Test
178 void testDecodeString() {
179 checkDecoders("Hello World!", "SGVsbG8gV29ybGQh");
180 }
181
182 @Test
183 void testEncodeBase64ByteArrayBoolean() {
184 final byte[] binaryData = { '1', '2', '3' };
185 final byte[] urlUnsafeData = "<<???>>".getBytes();
186 final byte[] urlUnsafeDataChunky = "<<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>>".getBytes();
187 byte[] encoded;
188
189
190
191 encoded = Base64.encodeBase64(binaryData, false);
192 assertNotNull(encoded);
193 assertEquals(4, encoded.length);
194 assertEquals(Base64.getEncodeLength(binaryData, Base64.CHUNK_SIZE, Base64.CHUNK_SEPARATOR) - 2, encoded.length);
195 assertEquals(getJreEncoder().encodeToString(binaryData), toString(encoded));
196 assertEquals("MTIz", toString(encoded));
197
198
199 encoded = Base64.encodeBase64(urlUnsafeData, false);
200 assertEquals("PDw/Pz8+Pg==", toString(encoded));
201 encoded = Base64.encodeBase64(urlUnsafeDataChunky, false);
202 assertEquals(getJreEncoder().encodeToString(urlUnsafeDataChunky), toString(encoded));
203
204
205 encoded = Base64.encodeBase64(binaryData, false);
206 assertNotNull(encoded);
207 assertEquals(4, encoded.length);
208 assertEquals(Base64.getEncodeLength(binaryData, Base64.CHUNK_SIZE, Base64.CHUNK_SEPARATOR) - 2, encoded.length);
209 assertEquals("MTIz", toString(encoded));
210
211
212 encoded = Base64.encodeBase64(binaryData, true);
213 assertNotNull(encoded);
214 assertEquals(6, encoded.length);
215 assertEquals(Base64.getEncodeLength(binaryData, Base64.CHUNK_SIZE, Base64.CHUNK_SEPARATOR), encoded.length);
216 assertEquals("MTIz\r\n", toString(encoded));
217
218
219 encoded = Base64.encodeBase64(urlUnsafeData, true);
220 assertEquals("PDw/Pz8+Pg==\r\n", toString(encoded));
221 encoded = Base64.encodeBase64(urlUnsafeDataChunky, true);
222 assertEquals(getJreMimeEncoder().encodeToString(urlUnsafeDataChunky) + "\r\n", toString(encoded));
223
224
225 encoded = Base64.encodeBase64(binaryData, true);
226 assertNotNull(encoded);
227 assertEquals(6, encoded.length);
228 assertEquals(Base64.getEncodeLength(binaryData, Base64.CHUNK_SIZE, Base64.CHUNK_SEPARATOR), encoded.length);
229 assertEquals("MTIz\r\n", toString(encoded));
230 }
231
232 @Test
233 void testEncodeBase64ByteArrayBooleanBoolean() {
234 final byte[] binaryData = { '1', '2', '3' };
235 byte[] encoded;
236 encoded = Base64.encodeBase64(binaryData, false, false);
237 assertNotNull(encoded);
238 assertEquals(4, encoded.length);
239 encoded = Base64.encodeBase64(binaryData, false, false);
240 assertNotNull(encoded);
241 assertEquals(4, encoded.length);
242 encoded = Base64.encodeBase64(binaryData, true, false);
243 assertNotNull(encoded);
244 assertEquals(6, encoded.length);
245 encoded = Base64.encodeBase64(binaryData, true, false);
246 assertNotNull(encoded);
247 assertEquals(6, encoded.length);
248 }
249
250 @Test
251 void testEncodeBase64ByteArrayBooleanBooleanInt() {
252 final byte[] binaryData = { '1', '2', '3' };
253 byte[] encoded;
254 encoded = Base64.encodeBase64(binaryData, false, false);
255 assertNotNull(encoded);
256 assertEquals(4, encoded.length);
257 assertThrows(IllegalArgumentException.class, () -> Base64.encodeBase64(binaryData, false, false, 3));
258 encoded = Base64.encodeBase64(binaryData, false, false, 4);
259 assertNotNull(encoded);
260 assertEquals(4, encoded.length);
261 encoded = Base64.encodeBase64(binaryData, true, false);
262 assertNotNull(encoded);
263 assertEquals(6, encoded.length);
264 assertThrows(IllegalArgumentException.class, () -> Base64.encodeBase64(binaryData, true, false, 5));
265 encoded = Base64.encodeBase64(binaryData, true, false, 6);
266 assertNotNull(encoded);
267 assertEquals(6, encoded.length);
268 }
269
270 @Test
271 void testEncodeBase64ByteArrayEdges() {
272 final byte[] binaryData = null;
273 assertArrayEquals(binaryData, Base64.encodeBase64(binaryData));
274 final byte[] binaryData2 = {};
275 assertArrayEquals(binaryData2, Base64.encodeBase64(binaryData2));
276 }
277
278 @Test
279 void testEncodeBase64Chunked() {
280 byte[] bytesToEncode = { 'f', 'o', 'o', 'b', 'a', 'r' };
281 byte[] encodedData = Base64.encodeBase64Chunked(bytesToEncode);
282 assertEquals("Zm9vYmFy\r\n", toString(encodedData));
283
284
285 bytesToEncode = "<<???>>".getBytes();
286 encodedData = Base64.encodeBase64Chunked(bytesToEncode);
287 assertEquals("PDw/Pz8+Pg==\r\n", toString(encodedData));
288
289 final byte[] chunkMe = ArrayFill.fill(new byte[Base64.CHUNK_SIZE * 2], (byte) 'A');
290 final byte[] chunked = Base64.encodeBase64Chunked(chunkMe);
291 assertEquals('\r', chunked[chunked.length - 2]);
292 assertEquals('\n', chunked[chunked.length - 1]);
293 assertArrayEquals(ArrayUtils.addAll(getJreMimeEncoder().encode(chunkMe), Base64.CHUNK_SEPARATOR), chunked);
294 }
295
296 @Test
297 void testEncodeBase64StringByteArray() {
298 String stringToEncode = "Many hands make light work.";
299 String encodedData = Base64.encodeBase64String(stringToEncode.getBytes());
300 assertEquals("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu\r\n", encodedData);
301
302
303 stringToEncode = "<<???>>";
304 encodedData = Base64.encodeBase64String(stringToEncode.getBytes());
305 assertEquals("PDw/Pz8+Pg==\r\n", encodedData);
306
307 final byte[] chunkMe = ArrayFill.fill(new byte[Base64.CHUNK_SIZE * 2], (byte) 'A');
308 final String chunked = Base64.encodeBase64String(chunkMe);
309 assertEquals('\r', chunked.charAt(chunked.length() - 2));
310 assertEquals('\n', chunked.charAt(chunked.length() - 1));
311 assertEquals(getJreMimeEncoder().encodeToString(chunkMe) + "\r\n", chunked);
312 }
313
314 @Test
315 void testEncodeBase64StringByteArrayBoolean() {
316 final byte[] bytesToEncode = "light work.".getBytes();
317 final String chunkedResult = Base64.encodeBase64String(bytesToEncode, true);
318 assertEquals("bGlnaHQgd29yay4=\r\n", chunkedResult);
319 final String unchunkedResult = Base64.encodeBase64String(bytesToEncode, false);
320 assertEquals("bGlnaHQgd29yay4=", unchunkedResult);
321 }
322
323 @Test
324 void testEncodeBase64StringUnChunked() {
325 byte[] bytesToEncode = "Many hands make light work.".getBytes();
326 String encodedData = Base64.encodeBase64StringUnChunked(bytesToEncode);
327 assertEquals("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu", encodedData);
328
329
330 bytesToEncode = "<<???>>".getBytes();
331 encodedData = Base64.encodeBase64StringUnChunked(bytesToEncode);
332 assertEquals("PDw/Pz8+Pg==", encodedData);
333
334 final byte[] chunkMe = ArrayFill.fill(new byte[Base64.CHUNK_SIZE * 2], (byte) 'A');
335 final String chunked = Base64.encodeBase64StringUnChunked(chunkMe);
336 assertEquals(getJreEncoder().encodeToString(chunkMe), chunked);
337 }
338
339 @Test
340 void testEncodeBase64URLSafe() {
341 byte[] bytesToEncode = "Many hands make light work.".getBytes();
342 byte[] encodedData = Base64.encodeBase64URLSafe(bytesToEncode);
343 assertEquals("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu", toString(encodedData));
344
345
346 bytesToEncode = "<<???>>".getBytes();
347 encodedData = Base64.encodeBase64URLSafe(bytesToEncode);
348 assertEquals("PDw_Pz8-Pg", toString(encodedData));
349
350 bytesToEncode = "<<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>>".getBytes();
351 encodedData = Base64.encodeBase64URLSafe(bytesToEncode);
352 assertEquals(getJreUrlEncoder().withoutPadding().encodeToString(bytesToEncode), toString(encodedData));
353 final String encodedUrlSafe = "PDw_Pz8-Pjw8Pz8_Pj48PD8_Pz4-PDw_Pz8-Pjw8Pz8_Pj48PD8_Pz4-PDw_Pz8-Pjw8Pz8_Pj48PD8_Pz4-PDw_Pz8-Pjw8Pz8_Pj4";
354 assertEquals(encodedUrlSafe, toString(encodedData));
355
356 assertEquals(encodedUrlSafe, toString(new Base64(0, null, true).encode(bytesToEncode)));
357 assertEquals(encodedUrlSafe, toString(new Base64(1, null, true).encode(bytesToEncode)));
358 assertEquals(encodedUrlSafe, toString(new Base64(999, null, true).encode(bytesToEncode)));
359 assertEquals(encodedUrlSafe, toString(new Base64(0, new byte[0], true).encode(bytesToEncode)));
360 assertEquals(encodedUrlSafe, toString(new Base64(0, new byte[10], true).encode(bytesToEncode)));
361 assertEquals(encodedUrlSafe, toString(new Base64(0, Base64.CHUNK_SEPARATOR, true).encode(bytesToEncode)));
362 assertEquals(encodedUrlSafe, toString(new Base64(Base64.CHUNK_SIZE, Base64.CHUNK_SEPARATOR, true).encode(bytesToEncode)));
363 assertEquals(encodedUrlSafe, toString(new Base64(999, Base64.CHUNK_SEPARATOR, true).encode(bytesToEncode)));
364 assertEquals(encodedUrlSafe, toString(new Base64(true).encode(bytesToEncode)));
365 }
366
367 @Test
368 void testEncodeBase64URLSafeString() {
369 byte[] bytesToEncode = "Many hands make light work.".getBytes();
370 String encodedData = Base64.encodeBase64URLSafeString(bytesToEncode);
371 assertEquals("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu", encodedData);
372
373
374 bytesToEncode = "<<???>>".getBytes();
375 encodedData = Base64.encodeBase64URLSafeString(bytesToEncode);
376 assertEquals("PDw_Pz8-Pg", encodedData);
377
378 bytesToEncode = "<<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>><<???>>".getBytes();
379 encodedData = Base64.encodeBase64URLSafeString(bytesToEncode);
380 assertEquals(getJreUrlEncoder().withoutPadding().encodeToString(bytesToEncode), encodedData);
381 assertEquals("PDw_Pz8-Pjw8Pz8_Pj48PD8_Pz4-PDw_Pz8-Pjw8Pz8_Pj48PD8_Pz4-PDw_Pz8-Pjw8Pz8_Pj48PD8_Pz4-PDw_Pz8-Pjw8Pz8_Pj4", encodedData);
382 }
383
384 @Test
385 void testEncodeByteArray() {
386 final Base64 base64 = new Base64();
387 final byte[] bytesToEncode = { 'l', 'i', 'g', 'h', 't', ' ', 'w', 'o', 'r' };
388 assertEquals("bGlnaHQgd29y\r\n", new String(base64.encode(bytesToEncode), StandardCharsets.UTF_8));
389 }
390
391 @Test
392 void testEncodeByteArrayEmpty() {
393 assertNull(new Base64().encode((byte[]) null));
394 final byte[] empty = {};
395 assertSame(empty, new Base64().encode(empty));
396 }
397
398 @Test
399 void testEncodeByteArrayNull() {
400 assertNull(new Base64().encode((byte[]) null));
401 }
402
403 @Test
404 void testEncodeInteger() {
405 testEncodeInteger(BigInteger.ONE);
406 testEncodeInteger(BigInteger.TEN);
407 testEncodeInteger(BigInteger.ZERO);
408 }
409
410 private void testEncodeInteger(final BigInteger bi) {
411 final byte[] decodedBytes = getJreDecoder().decode(Base64.encodeInteger(bi));
412 final BigInteger decoded = decodedBytes.length == 0 ? BigInteger.ZERO : new BigInteger(decodedBytes);
413 assertEquals(bi, decoded);
414 }
415
416 @Test
417 void testEncodeToString() {
418 final Base64 base64 = new Base64();
419 final byte[] bytesToEncode = { 'l', 'i', 'g', 'h', 't', ' ', 'w', 'o', 'r' };
420 assertEquals("bGlnaHQgd29y\r\n", base64.encodeToString(bytesToEncode));
421 }
422
423 @Test
424 void testIsArrayByteBase64() {
425 assertTrue(Base64.isArrayByteBase64(new byte[] { 'b', ' ' }));
426 assertFalse(Base64.isArrayByteBase64(new byte[] { '?' }));
427 }
428
429 @Test
430 void testIsBase64() {
431 assertTrue(Base64.isBase64((byte) '='));
432 assertTrue(Base64.isBase64((byte) 'b'));
433 assertFalse(Base64.isBase64((byte) ' '));
434 assertFalse(Base64.isBase64((byte) -1));
435 }
436
437 }