View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.codec.binary;
19  
20  import java.math.BigInteger;
21  import java.util.Arrays;
22  import java.util.Objects;
23  
24  import org.apache.commons.codec.CodecPolicy;
25  
26  /**
27   * Provides Base64 encoding and decoding as defined by <a href="https://www.ietf.org/rfc/rfc2045">RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part
28   * One: Format of Internet Message Bodies</a> and portions of <a href="https://datatracker.ietf.org/doc/html/rfc4648">RFC 4648 The Base16, Base32, and Base64
29   * Data Encodings</a>
30   *
31   * <p>
32   * This class implements <a href="https://www.ietf.org/rfc/rfc2045#section-6.8">RFC 2045 6.8. Base64 Content-Transfer-Encoding</a>.
33   * </p>
34   * <p>
35   * The class can be parameterized in the following manner with its {@link Builder}:
36   * </p>
37   * <ul>
38   * <li>URL-safe mode: Default off.</li>
39   * <li>Line length: Default 76. Line length that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
40   * <li>Line separator: Default is CRLF ({@code "\r\n"})</li>
41   * <li>Strict or lenient decoding policy; default is {@link CodecPolicy#LENIENT}.</li>
42   * <li>Custom decoding table.</li>
43   * <li>Custom encoding table.</li>
44   * <li>Padding; defaults is {@code '='}.</li>
45   * </ul>
46   * <p>
47   * The URL-safe parameter is only applied to encode operations. Decoding seamlessly handles both modes, see also
48   * {@code Builder#setDecodeTableFormat(DecodeTableFormat)}.
49   * </p>
50   * <p>
51   * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode character encodings which are
52   * compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc).
53   * </p>
54   * <p>
55   * This class is thread-safe.
56   * </p>
57   * <p>
58   * To configure a new instance, use a {@link Builder}. For example:
59   * </p>
60   *
61   * <pre>
62   * Base64 base64 = Base64.builder()
63   *   .setDecodingPolicy(CodecPolicy.LENIENT)    // default is lenient, null resets to default
64   *   .setEncodeTable(customEncodeTable)         // default is built in, null resets to default
65   *   .setLineLength(0)                          // default is none
66   *   .setLineSeparator('\r', '\n')              // default is CR LF, null resets to default
67   *   .setPadding('=')                           // default is '='
68   *   .setUrlSafe(false)                         // default is false
69   *   .get()
70   * </pre>
71   *
72   * @see Base64InputStream
73   * @see Base64OutputStream
74   * @see <a href="https://www.ietf.org/rfc/rfc2045">RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</a>
75   * @see <a href="https://datatracker.ietf.org/doc/html/rfc4648">RFC 4648 The Base16, Base32, and Base64 Data Encodings</a>
76   * @since 1.0
77   */
78  public class Base64 extends BaseNCodec {
79  
80      /**
81       * Builds {@link Base64} instances.
82       *
83       * <p>
84       * To configure a new instance, use a {@link Builder}. For example:
85       * </p>
86       *
87       * <pre>
88       * Base64 base64 = Base64.builder()
89       *   .setCodecPolicy(CodecPolicy.LENIENT)       // default is lenient, null resets to default
90       *   .setEncodeTable(customEncodeTable)         // default is built in, null resets to default
91       *   .setLineLength(0)                          // default is none
92       *   .setLineSeparator('\r', '\n')              // default is CR LF, null resets to default
93       *   .setPadding('=')                           // default is '='
94       *   .setUrlSafe(false)                         // default is false
95       *   .get()
96       * </pre>
97       *
98       * @since 1.17.0
99       */
100     public static class Builder extends AbstractBuilder<Base64, Builder> {
101 
102         /**
103          * Constructs a new instance.
104          */
105         public Builder() {
106             super(STANDARD_ENCODE_TABLE);
107             setDecodeTableRaw(DECODE_TABLE);
108             setEncodeTableRaw(STANDARD_ENCODE_TABLE);
109             setEncodedBlockSize(BYTES_PER_ENCODED_BLOCK);
110             setUnencodedBlockSize(BYTES_PER_UNENCODED_BLOCK);
111         }
112 
113         @Override
114         public Base64 get() {
115             return new Base64(this);
116         }
117 
118         /**
119          * Sets the format of the decoding table. This method allows to explicitly state whether a standard or URL-safe Base64 decoding is expected. This method
120          * does not modify behavior on encoding operations. For configuration of the encoding behavior, please use {@link #setUrlSafe(boolean)} method.
121          * <p>
122          * By default, the implementation uses the {@link DecodeTableFormat#MIXED} approach, allowing a seamless handling of both
123          * {@link DecodeTableFormat#URL_SAFE} and {@link DecodeTableFormat#STANDARD} base64.
124          * </p>
125          *
126          * @param format table format to be used on Base64 decoding. Use {@link DecodeTableFormat#MIXED} or null to reset to the default behavior.
127          * @return {@code this} instance.
128          * @since 1.21
129          */
130         public Builder setDecodeTableFormat(final DecodeTableFormat format) {
131             if (format == null) {
132                 return setDecodeTableRaw(DECODE_TABLE);
133             }
134             switch (format) {
135                 case STANDARD:
136                     return setDecodeTableRaw(STANDARD_DECODE_TABLE);
137                 case URL_SAFE:
138                     return setDecodeTableRaw(URL_SAFE_DECODE_TABLE);
139                 case MIXED:
140                 default:
141                     return setDecodeTableRaw(DECODE_TABLE);
142             }
143         }
144 
145         /**
146          * Sets the encode table.
147          *
148          * @param encodeTable The encode table with exactly 64 unique entries, null resets to the default.
149          * @return {@code this} instance.
150          * @throws IllegalArgumentException if {@code encodeTable} does not contain exactly 64 unique entries.
151          */
152         @Override
153         public Builder setEncodeTable(final byte... encodeTable) {
154             setDecodeTableRaw(toDecodeTable(encodeTable));
155             return super.setEncodeTable(encodeTable);
156         }
157 
158         /**
159          * Sets the URL-safe encoding policy.
160          * <p>
161          * This method does not modify behavior on decoding operations. For configuration of the decoding behavior, please use
162          * {@code Builder.setDecodeTableFormat(DecodeTableFormat)} method.
163          * </p>
164          *
165          * @param urlSafe URL-safe encoding policy.
166          * @return {@code this} instance.
167          */
168         public Builder setUrlSafe(final boolean urlSafe) {
169             // Javadoc 8 can't find {@link #setDecodeTableFormat(DecodeTableFormat)}
170             return setEncodeTable(toUrlSafeEncodeTable(urlSafe));
171         }
172 
173     }
174 
175     /**
176      * Enumerates the Base64 table format to be used on decoding.
177      * <p>
178      * By default, the method uses {@link DecodeTableFormat#MIXED} approach, allowing a seamless handling of both {@link DecodeTableFormat#URL_SAFE} and
179      * {@link DecodeTableFormat#STANDARD} base64 options.
180      * </p>
181      *
182      * @since 1.21
183      */
184     public enum DecodeTableFormat {
185 
186         /**
187          * Corresponds to the standard Base64 coding table, as specified in
188          * <a href="https://www.ietf.org/rfc/rfc2045#:~:text=Table%201%3A%20The%20Base64%20Alphabet">RFC 2045 Table 1: The Base64 Alphabet</a>.
189          */
190         STANDARD,
191 
192         /**
193          * Corresponds to the URL-safe Base64 coding table, as specified in
194          * <a href="https://datatracker.ietf.org/doc/html/rfc4648#:~:text=Table%202%3A%20The%20%22URL%20and%20Filename%20safe%22%20Base%2064%20Alphabet">RFC
195          * 4648 Table 2: The "URL and Filename safe" Base 64 Alphabet</a>.
196          */
197         URL_SAFE,
198 
199         /**
200          * Represents a joint approach, allowing a seamless decoding of both character sets, corresponding to either
201          * <a href="https://www.ietf.org/rfc/rfc2045#:~:text=Table%201%3A%20The%20Base64%20Alphabet">RFC 2045 Table 1: The Base64 Alphabet</a> or
202          * <a href="https://datatracker.ietf.org/doc/html/rfc4648#:~:text=Table%202%3A%20The%20%22URL%20and%20Filename%20safe%22%20Base%2064%20Alphabet">RFC
203          * 4648 Table 2: The "URL and Filename safe" Base 64 Alphabet</a>. This decoding table is used by default.
204          */
205         MIXED
206     }
207 
208     /**
209      * BASE64 characters are 6 bits in length.
210      * They are formed by taking a block of 3 octets to form a 24-bit string,
211      * which is converted into 4 BASE64 characters.
212      */
213     private static final int BITS_PER_ENCODED_BYTE = 6;
214     private static final int BYTES_PER_UNENCODED_BLOCK = 3;
215     private static final int BYTES_PER_ENCODED_BLOCK = 4;
216     private static final int DECODING_TABLE_LENGTH = 256;
217 
218     /**
219      * This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet" equivalents as specified in
220      * <a href="https://www.ietf.org/rfc/rfc2045#:~:text=Table%201%3A%20The%20Base64%20Alphabet">RFC 2045 Table 1: The Base64 Alphabet</a>.
221      * <p>
222      * Thanks to "commons" project in ws.apache.org for this code. https://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
223      * </p>
224      */
225     // @formatter:off
226     private static final byte[] STANDARD_ENCODE_TABLE = {
227             'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
228             'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
229             'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
230             'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
231             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
232     };
233 
234     /**
235      * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and / changed to - and _ to make the encoded Base64 results more URL-SAFE. This table is
236      * only used when the Base64's mode is set to URL-SAFE.
237      */
238     // @formatter:off
239     private static final byte[] URL_SAFE_ENCODE_TABLE = {
240             'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
241             'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
242             'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
243             'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
244             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
245     };
246     // @formatter:on
247 
248     /**
249      * This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified in
250      * <a href="https://www.ietf.org/rfc/rfc2045#:~:text=Table%201%3A%20The%20Base64%20Alphabet">RFC 2045 Table 1: The Base64 Alphabet</a>) into their 6-bit
251      * positive integer equivalents. Characters that are not in the Base64 or Base64 URL-safe alphabets but fall within the bounds of the array are translated
252      * to -1.
253      * <p>
254      * The characters '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both URL_SAFE and STANDARD base64.
255      * (The encoder, on the other hand, needs to know ahead of time what to emit).
256      * </p>
257      * <p>
258      * Thanks to "commons" project in ws.apache.org for this code. https://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
259      * </p>
260      */
261     private static final byte[] DECODE_TABLE = {
262         //   0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
263             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f
264             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f
265             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, // 20-2f + - /
266             52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 30-3f 0-9
267             -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, // 40-4f A-O
268             15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, // 50-5f P-Z _
269             -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 60-6f a-o
270             41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51                      // 70-7a p-z
271     };
272 
273     /**
274      * This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified in
275      * <a href="https://www.ietf.org/rfc/rfc2045#:~:text=Table%201%3A%20The%20Base64%20Alphabet">RFC 2045 Table 1: The Base64 Alphabet</a>) into their 6-bit
276      * positive integer equivalents. Characters that are not in the Base64 alphabet but fall within the bounds of the array are translated to -1. This decoding
277      * table handles only the standard base64 characters, such as '+' and '/'. The "url-safe" characters such as '-' and '_' are not supported by the table.
278      */
279     private static final byte[] STANDARD_DECODE_TABLE = {
280         //   0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
281             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f
282             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f
283             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 20-2f + /
284             52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 30-3f 0-9
285             -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, // 40-4f A-O
286             15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 50-5f P-Z
287             -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 60-6f a-o
288             41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51                      // 70-7a p-z
289     };
290 
291     /**
292      * This array is a lookup table that translates Unicode characters drawn from the "Base64 URL-safe Alphabet" (as specified in
293      * <a href="https://datatracker.ietf.org/doc/html/rfc4648#:~:text=Table%202%3A%20The%20%22URL%20and%20Filename%20safe%22%20Base%2064%20Alphabet">RFC 4648
294      * Table 2: The "URL and Filename safe" Base 64 Alphabet</a>) into their 6-bit positive integer equivalents. Characters that are not in the Base64 URL-safe
295      * alphabet but fall within the bounds of the array are translated to -1. This decoding table handles only the URL-safe base64 characters, such as '-' and
296      * '_'. The standard characters such as '+' and '/' are not supported by the table.
297      */
298     private static final byte[] URL_SAFE_DECODE_TABLE = {
299             //   0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
300             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f
301             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f
302             -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, // 20-2f -
303             52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 30-3f 0-9
304             -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, // 40-4f A-O
305             15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, // 50-5f P-Z _
306             -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 60-6f a-o
307             41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51                      // 70-7a p-z
308     };
309 
310     /**
311      * Base64 uses 6-bit fields.
312      */
313 
314     /** Mask used to extract 6 bits, used when encoding */
315     private static final int MASK_6_BITS = 0x3f;
316 
317     // The static final fields above are used for the original static byte[] methods on Base64.
318     // The private member fields below are used with the new streaming approach, which requires
319     // some state be preserved between calls of encode() and decode().
320 
321     /** Mask used to extract 4 bits, used when decoding final trailing character. */
322     private static final int MASK_4_BITS = 0xf;
323 
324     /** Mask used to extract 2 bits, used when decoding final trailing character. */
325     private static final int MASK_2_BITS = 0x3;
326 
327     /**
328      * Creates a new Builder.
329      *
330      * <p>
331      * To configure a new instance, use a {@link Builder}. For example:
332      * </p>
333      *
334      * <pre>
335      * Base64 base64 = Base64.builder()
336      *   .setDecodingPolicy(CodecPolicy.LENIENT) // default is lenient, null resets to default
337      *   .setEncodeTable(customEncodeTable)         // default is built in, null resets to default
338      *   .setLineLength(0)                          // default is none
339      *   .setLineSeparator('\r', '\n')              // default is CR LF, null resets to default
340      *   .setPadding('=')                           // default is '='
341      *   .setUrlSafe(false)                         // default is false
342      *   .get()
343      * </pre>
344      *
345      * @return A new Builder.
346      * @since 1.17.0
347      */
348     public static Builder builder() {
349         return new Builder();
350     }
351 
352     /**
353      * Calculates a decode table for a given encode table.
354      *
355      * @param encodeTable that is used to determine decode lookup table.
356      * @return A new decode table.
357      */
358     private static byte[] calculateDecodeTable(final byte[] encodeTable) {
359         if (encodeTable.length != STANDARD_ENCODE_TABLE.length) {
360             throw new IllegalArgumentException("encodeTable must have exactly 64 entries.");
361         }
362         final byte[] decodeTable = new byte[DECODING_TABLE_LENGTH];
363         Arrays.fill(decodeTable, (byte) -1);
364         for (int i = 0; i < encodeTable.length; i++) {
365             final int encodedByte = encodeTable[i] & 0xff;
366             if (decodeTable[encodedByte] != -1) {
367                 throw new IllegalArgumentException("encodeTable must not contain duplicate entries.");
368             }
369             decodeTable[encodedByte] = (byte) i;
370         }
371         return decodeTable;
372     }
373 
374     private static boolean contains(final byte[] bytes, final byte value) {
375         for (final byte element : bytes) {
376             if (element == value) {
377                 return true;
378             }
379         }
380         return false;
381     }
382 
383     /**
384      * Decodes Base64 data into octets.
385      * <p>
386      * This method seamlessly handles data encoded in URL-safe or normal mode. For enforcing verification against strict standard Base64 or Base64 URL-safe
387      * tables, please use {@link #decodeBase64Standard(byte[])} or {@link #decodeBase64UrlSafe(byte[])} methods respectively. This method skips unknown or
388      * unsupported bytes.
389      * </p>
390      *
391      * @param base64Data Byte array containing Base64 data.
392      * @return New array containing decoded data.
393      */
394     public static byte[] decodeBase64(final byte[] base64Data) {
395         return new Base64().decode(base64Data);
396     }
397 
398     /**
399      * Decodes a Base64 String into octets.
400      * <p>
401      * This method seamlessly handles data encoded in URL-safe or normal mode. For enforcing verification against strict standard Base64 or Base64 URL-safe
402      * tables, please use {@link #decodeBase64Standard(String)} or {@link #decodeBase64UrlSafe(String)} methods respectively. This method skips unknown or
403      * unsupported bytes.
404      * </p>
405      *
406      * @param base64String String containing Base64 data.
407      * @return New array containing decoded data.
408      * @since 1.4
409      */
410     public static byte[] decodeBase64(final String base64String) {
411         return new Base64().decode(base64String);
412     }
413 
414     /**
415      * Decodes standard Base64 data into octets.
416      * <p>
417      * This implementation is aligned with the <a href="https://www.ietf.org/rfc/rfc2045#:~:text=Table%201%3A%20The%20Base64%20Alphabet">RFC 2045 Table 1: The
418      * Base64 Alphabet</a>. This method skips unknown or unsupported bytes.
419      * </p>
420      *
421      * @param base64Data Byte array containing Base64 data.
422      * @return New array containing decoded data.
423      * @since 1.21
424      */
425     public static byte[] decodeBase64Standard(final byte[] base64Data) {
426         return builder().setDecodeTableFormat(DecodeTableFormat.STANDARD).get().decode(base64Data);
427     }
428 
429     /**
430      * Decodes a standard Base64 String into octets.
431      * <p>
432      * This implementation is aligned with the <a href="https://www.ietf.org/rfc/rfc2045#:~:text=Table%201%3A%20The%20Base64%20Alphabet">RFC 2045 Table 1: The
433      * Base64 Alphabet</a>. This method skips unknown or unsupported characters.
434      * </p>
435      *
436      * @param base64String String containing Base64 data.
437      * @return New array containing decoded data.
438      * @since 1.21
439      */
440     public static byte[] decodeBase64Standard(final String base64String) {
441         return builder().setDecodeTableFormat(DecodeTableFormat.STANDARD).get().decode(base64String);
442     }
443 
444     /**
445      * Decodes URL-safe Base64 data into octets.
446      * <p>
447      * This implementation is aligned with
448      * <a href="https://datatracker.ietf.org/doc/html/rfc4648#:~:text=Table%202%3A%20The%20%22URL%20and%20Filename%20safe%22%20Base%2064%20Alphabet">RFC 4648
449      * Table 2: The "URL and Filename safe" Base 64 Alphabet</a>. This method skips unknown or unsupported characters.
450      * </p>
451      *
452      * @param base64Data Byte array containing Base64 data.
453      * @return New array containing decoded data.
454      * @since 1.21
455      */
456     public static byte[] decodeBase64UrlSafe(final byte[] base64Data) {
457         return builder().setDecodeTableFormat(DecodeTableFormat.URL_SAFE).get().decode(base64Data);
458     }
459 
460     /**
461      * Decodes a URL-safe Base64 String into octets.
462      * <p>
463      * This implementation is aligned with
464      * <a href="https://datatracker.ietf.org/doc/html/rfc4648#:~:text=Table%202%3A%20The%20%22URL%20and%20Filename%20safe%22%20Base%2064%20Alphabet">RFC 4648
465      * Table 2: The "URL and Filename safe" Base 64 Alphabet</a>. This method skips unknown or unsupported characters.
466      * </p>
467      *
468      * @param base64String String containing Base64 data.
469      * @return New array containing decoded data.
470      * @since 1.21
471      */
472     public static byte[] decodeBase64UrlSafe(final String base64String) {
473         return builder().setDecodeTableFormat(DecodeTableFormat.URL_SAFE).get().decode(base64String);
474     }
475 
476     /**
477      * Decodes a byte64-encoded integer according to crypto standards such as W3C's XML-Signature.
478      *
479      * @param array A byte array containing base64 character data.
480      * @return A BigInteger.
481      * @since 1.4
482      */
483     public static BigInteger decodeInteger(final byte[] array) {
484         return new BigInteger(1, decodeBase64(array));
485     }
486 
487     /**
488      * Encodes binary data using the base64 algorithm but does not chunk the output.
489      *
490      * @param binaryData binary data to encode.
491      * @return byte[] containing Base64 characters in their UTF-8 representation.
492      */
493     public static byte[] encodeBase64(final byte[] binaryData) {
494         return encodeBase64(binaryData, false);
495     }
496 
497     /**
498      * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
499      *
500      * @param binaryData Array containing binary data to encode.
501      * @param isChunked  if {@code true} this encoder will chunk the base64 output into 76 character blocks.
502      * @return Base64-encoded data.
503      * @throws IllegalArgumentException Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}.
504      */
505     public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked) {
506         return encodeBase64(binaryData, isChunked, false);
507     }
508 
509     /**
510      * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
511      *
512      * @param binaryData Array containing binary data to encode.
513      * @param isChunked  if {@code true} this encoder will chunk the base64 output into 76 character blocks.
514      * @param urlSafe    if {@code true} this encoder will emit - and _ instead of the usual + and / characters. <strong>No padding is added when encoding using
515      *                   the URL-safe alphabet.</strong>
516      * @return Base64-encoded data.
517      * @throws IllegalArgumentException Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}.
518      * @since 1.4
519      */
520     public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked, final boolean urlSafe) {
521         return encodeBase64(binaryData, isChunked, urlSafe, Integer.MAX_VALUE);
522     }
523 
524     /**
525      * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
526      *
527      * @param binaryData    Array containing binary data to encode.
528      * @param isChunked     if {@code true} this encoder will chunk the base64 output into 76 character blocks.
529      * @param urlSafe       if {@code true} this encoder will emit - and _ instead of the usual + and / characters. <strong>No padding is added when encoding
530      *                      using the URL-safe alphabet.</strong>
531      * @param maxResultSize The maximum result size to accept.
532      * @return Base64-encoded data.
533      * @throws IllegalArgumentException Thrown when the input array needs an output array bigger than maxResultSize.
534      * @since 1.4
535      */
536     public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked, final boolean urlSafe, final int maxResultSize) {
537         if (BinaryCodec.isEmpty(binaryData)) {
538             return binaryData;
539         }
540         // Create this so can use the super-class method
541         // Also ensures that the same roundings are performed by the ctor and the code
542         final Base64 b64 = isChunked ? new Base64(urlSafe) : new Base64(0, CHUNK_SEPARATOR, urlSafe);
543         final long len = b64.getEncodedLength(binaryData);
544         if (len > maxResultSize) {
545             throw new IllegalArgumentException(
546                     "Input array too big, the output array would be bigger (" + len + ") than the specified maximum size of " + maxResultSize);
547         }
548         return b64.encode(binaryData);
549     }
550 
551     /**
552      * Encodes binary data using the base64 algorithm and chunks the encoded output into 76 character blocks
553      *
554      * @param binaryData binary data to encode.
555      * @return Base64 characters chunked in 76 character blocks.
556      */
557     public static byte[] encodeBase64Chunked(final byte[] binaryData) {
558         return encodeBase64(binaryData, true);
559     }
560 
561     /**
562      * Encodes binary data using the base64 algorithm but does not chunk the output.
563      * <p>
564      * <strong> We changed the behavior of this method from multi-line chunking (1.4) to single-line non-chunking (1.5).</strong>
565      * </p>
566      *
567      * @param binaryData binary data to encode.
568      * @return String containing Base64 characters.
569      * @since 1.4 (NOTE: 1.4 chunked the output, whereas 1.5 does not).
570      */
571     public static String encodeBase64String(final byte[] binaryData) {
572         return StringUtils.newStringUsAscii(encodeBase64(binaryData, false));
573     }
574 
575     /**
576      * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The url-safe variation emits - and _ instead of +
577      * and / characters. <strong>No padding is added.</strong>
578      *
579      * @param binaryData binary data to encode.
580      * @return byte[] containing Base64 characters in their UTF-8 representation.
581      * @since 1.4
582      */
583     public static byte[] encodeBase64URLSafe(final byte[] binaryData) {
584         return encodeBase64(binaryData, false, true);
585     }
586 
587     /**
588      * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The url-safe variation emits - and _ instead of +
589      * and / characters. <strong>No padding is added.</strong>
590      *
591      * @param binaryData binary data to encode.
592      * @return String containing Base64 characters.
593      * @since 1.4
594      */
595     public static String encodeBase64URLSafeString(final byte[] binaryData) {
596         return StringUtils.newStringUsAscii(encodeBase64(binaryData, false, true));
597     }
598 
599     /**
600      * Encodes to a byte64-encoded integer according to crypto standards such as W3C's XML-Signature.
601      *
602      * @param bigInteger A BigInteger.
603      * @return A byte array containing base64 character data.
604      * @throws NullPointerException if null is passed in.
605      * @since 1.4
606      */
607     public static byte[] encodeInteger(final BigInteger bigInteger) {
608         Objects.requireNonNull(bigInteger, "bigInteger");
609         return encodeBase64(toUnsignedBytes(bigInteger), false);
610     }
611 
612     /**
613      * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the method treats whitespace as valid.
614      *
615      * @param arrayOctet byte array to test.
616      * @return {@code true} if all bytes are valid characters in the Base64 alphabet or if the byte array is empty; {@code false}, otherwise.
617      * @deprecated 1.5 Use {@link #isBase64(byte[])}, will be removed in 2.0.
618      */
619     @Deprecated
620     public static boolean isArrayByteBase64(final byte[] arrayOctet) {
621         return isBase64(arrayOctet);
622     }
623 
624     /**
625      * Tests whether or not the {@code octet} is in the Base64 alphabet.
626      * <p>
627      * This method threats all characters included within standard base64 and base64url encodings as valid base64 characters. This includes the '+' and '/'
628      * (standard base64), as well as '-' and '_' (URL-safe base64) characters. For enforcing verification against strict standard Base64 or Base64 URL-safe
629      * tables, please use {@link #isBase64Standard(byte)} or {@link #isBase64Url(byte)} methods respectively.
630      * </p>
631      *
632      * @param octet The value to test.
633      * @return {@code true} if the value is defined in the Base64 alphabet, {@code false} otherwise.
634      * @since 1.4
635      */
636     public static boolean isBase64(final byte octet) {
637         return octet == PAD_DEFAULT || octet >= 0 && octet < DECODE_TABLE.length && DECODE_TABLE[octet] != -1;
638     }
639 
640     /**
641      * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the method treats whitespace as valid.
642      * <p>
643      * This method treats all characters included within standard base64 and base64url encodings as valid base64 characters. This includes the '+' and '/'
644      * (standard base64), as well as '-' and '_' (URL-safe base64) characters. For enforcing verification against strict standard Base64 or Base64 URL-safe
645      * tables, please use {@link #isBase64Standard(byte[])} or {@link #isBase64Url(byte[])} methods respectively.
646      * </p>
647      *
648      * @param arrayOctet byte array to test.
649      * @return {@code true} if all bytes are valid characters in the Base64 alphabet or if the byte array is empty; {@code false}, otherwise.
650      * @since 1.5
651      */
652     public static boolean isBase64(final byte[] arrayOctet) {
653         for (final byte element : arrayOctet) {
654             if (!isBase64(element) && !Character.isWhitespace(element)) {
655                 return false;
656             }
657         }
658         return true;
659     }
660 
661     /**
662      * Tests a given String to see if it contains only valid characters within the Base64 alphabet. Currently the method treats whitespace as valid.
663      * <p>
664      * This method threats all characters included within standard base64 and base64url encodings as valid base64 characters. This includes the '+' and '/'
665      * (standard base64), as well as '-' and '_' (URL-safe base64) characters. For enforcing verification against strict standard Base64 or Base64 URL-safe
666      * tables, please use {@link #isBase64Standard(String)} or {@link #isBase64Url(String)} methods respectively.
667      * </p>
668      *
669      * @param base64 String to test.
670      * @return {@code true} if all characters in the String are valid characters in the Base64 alphabet or if the String is empty; {@code false}, otherwise.
671      * @since 1.5
672      */
673     public static boolean isBase64(final String base64) {
674         return isBase64(StringUtils.getBytesUtf8(base64));
675     }
676 
677     /**
678      * Tests whether or not the {@code octet} is in the standard Base64 alphabet.
679      * <p>
680      * This implementation is aligned with <a href="https://www.ietf.org/rfc/rfc2045#:~:text=Table%201%3A%20The%20Base64%20Alphabet">RFC 2045 Table 1: The
681      * Base64 Alphabet</a>.
682      * </p>
683      *
684      * @param octet The value to test.
685      * @return {@code true} if the value is defined in the standard Base64 alphabet, {@code false} otherwise.
686      * @since 1.21
687      */
688     public static boolean isBase64Standard(final byte octet) {
689         return octet == PAD_DEFAULT || octet >= 0 && octet < STANDARD_DECODE_TABLE.length && STANDARD_DECODE_TABLE[octet] != -1;
690     }
691 
692     /**
693      * Tests a given byte array to see if it contains only valid characters within the standard Base64 alphabet. The method treats whitespace as valid.
694      * <p>
695      * This implementation is aligned with <a href="https://www.ietf.org/rfc/rfc2045#:~:text=Table%201%3A%20The%20Base64%20Alphabet">RFC 2045 Table 1: The
696      * Base64 Alphabet</a>.
697      * </p>
698      *
699      * @param arrayOctet byte array to test.
700      * @return {@code true} if all bytes are valid characters in the standard Base64 alphabet. {@code false}, otherwise.
701      * @since 1.21
702      */
703     public static boolean isBase64Standard(final byte[] arrayOctet) {
704         for (final byte element : arrayOctet) {
705             if (!isBase64Standard(element) && !Character.isWhitespace(element)) {
706                 return false;
707             }
708         }
709         return true;
710     }
711 
712     /**
713      * Tests a given String to see if it contains only valid characters within the standard Base64 alphabet. The method treats whitespace as valid.
714      * <p>
715      * This implementation is aligned with <a href="https://www.ietf.org/rfc/rfc2045#:~:text=Table%201%3A%20The%20Base64%20Alphabet">RFC 2045 Table 1: The
716      * Base64 Alphabet</a>.
717      * </p>
718      *
719      * @param base64 String to test.
720      * @return {@code true} if all characters in the String are valid characters in the standard Base64 alphabet or if the String is empty; {@code false},
721      *         otherwise.
722      * @since 1.21
723      */
724     public static boolean isBase64Standard(final String base64) {
725         return isBase64Standard(StringUtils.getBytesUtf8(base64));
726     }
727 
728     /**
729      * Tests whether or not the {@code octet} is in the URL-safe Base64 alphabet.
730      * <p>
731      * This implementation is aligned with
732      * <a href="https://datatracker.ietf.org/doc/html/rfc4648#:~:text=Table%202%3A%20The%20%22URL%20and%20Filename%20safe%22%20Base%2064%20Alphabet">RFC 4648
733      * Table 2: The "URL and Filename safe" Base 64 Alphabet</a>.
734      * </p>
735      *
736      * @param octet The value to test.
737      * @return {@code true} if the value is defined in the URL-safe Base64 alphabet, {@code false} otherwise.
738      * @since 1.21
739      */
740     public static boolean isBase64Url(final byte octet) {
741         return octet == PAD_DEFAULT || octet >= 0 && octet < URL_SAFE_DECODE_TABLE.length && URL_SAFE_DECODE_TABLE[octet] != -1;
742     }
743 
744     /**
745      * Tests a given byte array to see if it contains only valid characters within the URL-safe Base64 alphabet. The method treats whitespace as valid.
746      * <p>
747      * This implementation is aligned with
748      * <a href="https://datatracker.ietf.org/doc/html/rfc4648#:~:text=Table%202%3A%20The%20%22URL%20and%20Filename%20safe%22%20Base%2064%20Alphabet">RFC 4648
749      * Table 2: The "URL and Filename safe" Base 64 Alphabet</a>.
750      * </p>
751      *
752      * @param arrayOctet byte array to test.
753      * @return {@code true} if all bytes are valid characters in the URL-safe Base64 alphabet, {@code false}, otherwise.
754      * @since 1.21
755      */
756     public static boolean isBase64Url(final byte[] arrayOctet) {
757         for (final byte element : arrayOctet) {
758             if (!isBase64Url(element) && !Character.isWhitespace(element)) {
759                 return false;
760             }
761         }
762         return true;
763     }
764 
765     /**
766      * Tests a given String to see if it contains only valid characters within the URL-safe Base64 alphabet. The method treats whitespace as valid.
767      * <p>
768      * This implementation is aligned with
769      * <a href="https://datatracker.ietf.org/doc/html/rfc4648#:~:text=Table%202%3A%20The%20%22URL%20and%20Filename%20safe%22%20Base%2064%20Alphabet">RFC 4648
770      * Table 2: The "URL and Filename safe" Base 64 Alphabet</a>.
771      * </p>
772      *
773      * @param base64 String to test.
774      * @return {@code true} if all characters in the String are valid characters in the URL-safe Base64 alphabet or if the String is empty; {@code false},
775      *         otherwise.
776      * @since 1.21
777      */
778     public static boolean isBase64Url(final String base64) {
779         return isBase64Url(StringUtils.getBytesUtf8(base64));
780     }
781 
782     private static byte[] toDecodeTable(final byte[] encodeTable) {
783         final byte[] table = encodeTable != null ? encodeTable : STANDARD_ENCODE_TABLE;
784         if (Arrays.equals(table, STANDARD_ENCODE_TABLE) || Arrays.equals(table, URL_SAFE_ENCODE_TABLE)) {
785             return DECODE_TABLE;
786         }
787         return calculateDecodeTable(table);
788     }
789 
790     static byte[] toUrlSafeEncodeTable(final boolean urlSafe) {
791         return urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;
792     }
793 
794     /**
795      * Line separator for encoding. Not used when decoding. Only used if lineLength &gt; 0.
796      */
797     private final byte[] lineSeparator;
798 
799     /**
800      * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing. {@code encodeSize = 4 + lineSeparator.length;}
801      */
802     private final int encodeSize;
803     private final boolean isUrlSafe;
804     private final boolean isStandardEncodeTable;
805 
806     /**
807      * Constructs a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
808      * <p>
809      * When encoding the line length is 0 (no chunking), and the encoding table is STANDARD_ENCODE_TABLE.
810      * </p>
811      * <p>
812      * When decoding all variants are supported.
813      * </p>
814      */
815     public Base64() {
816         this(0);
817     }
818 
819     /**
820      * Constructs a Base64 codec used for decoding (all modes) and encoding in the given URL-safe mode.
821      * <p>
822      * When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE.
823      * </p>
824      * <p>
825      * When decoding all variants are supported.
826      * </p>
827      *
828      * @param urlSafe if {@code true}, URL-safe encoding is used. In most cases this should be set to {@code false}.
829      * @since 1.4
830      * @deprecated Use {@link #builder()} and {@link Builder}.
831      */
832     @Deprecated
833     public Base64(final boolean urlSafe) {
834         this(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe);
835     }
836 
837     private Base64(final Builder builder) {
838         super(builder);
839         final byte[] encTable = builder.getEncodeTable();
840         if (encTable.length != STANDARD_ENCODE_TABLE.length) {
841             throw new IllegalArgumentException("encodeTable must have exactly 64 entries.");
842         }
843         if (contains(encTable, pad)) {
844             throw new IllegalArgumentException("encodeTable must not contain the padding byte.");
845         }
846         this.isStandardEncodeTable = Arrays.equals(encTable, STANDARD_ENCODE_TABLE);
847         this.isUrlSafe = Arrays.equals(encTable, URL_SAFE_ENCODE_TABLE);
848         // TODO could be simplified if there is no requirement to reject invalid line sep when length <=0
849         // @see test case Base64Test.testConstructors()
850         if (builder.getLineSeparator().length > 0) {
851             final byte[] lineSeparatorB = builder.getLineSeparator();
852             if (containsAlphabetOrPad(lineSeparatorB)) {
853                 final String sep = StringUtils.newStringUtf8(lineSeparatorB);
854                 throw new IllegalArgumentException("lineSeparator must not contain base64 characters: [" + sep + "]");
855             }
856             if (builder.getLineLength() > 0) { // null line-sep forces no chunking rather than throwing IAE
857                 this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparatorB.length;
858                 this.lineSeparator = lineSeparatorB;
859             } else {
860                 this.encodeSize = BYTES_PER_ENCODED_BLOCK;
861                 this.lineSeparator = null;
862             }
863         } else {
864             this.encodeSize = BYTES_PER_ENCODED_BLOCK;
865             this.lineSeparator = null;
866         }
867     }
868 
869     /**
870      * Constructs a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
871      * <p>
872      * When encoding the line length is given in the constructor, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE.
873      * </p>
874      * <p>
875      * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
876      * </p>
877      * <p>
878      * When decoding all variants are supported.
879      * </p>
880      *
881      * @param lineLength Each line of encoded data will be at most of the given length (rounded down to the nearest multiple of 4). If lineLength &lt;= 0, then
882      *                   the output will not be divided into lines (chunks). Ignored when decoding.
883      * @since 1.4
884      * @deprecated Use {@link #builder()} and {@link Builder}.
885      */
886     @Deprecated
887     public Base64(final int lineLength) {
888         this(lineLength, CHUNK_SEPARATOR);
889     }
890 
891     /**
892      * Constructs a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
893      * <p>
894      * When encoding the line length and line separator are given in the constructor, and the encoding table is STANDARD_ENCODE_TABLE.
895      * </p>
896      * <p>
897      * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
898      * </p>
899      * <p>
900      * When decoding all variants are supported.
901      * </p>
902      *
903      * @param lineLength    Each line of encoded data will be at most of the given length (rounded down to the nearest multiple of 4). If lineLength &lt;= 0,
904      *                      then the output will not be divided into lines (chunks). Ignored when decoding.
905      * @param lineSeparator Each line of encoded data will end with this sequence of bytes.
906      * @throws IllegalArgumentException Thrown when the provided lineSeparator included some base64 characters.
907      * @since 1.4
908      * @deprecated Use {@link #builder()} and {@link Builder}.
909      */
910     @Deprecated
911     public Base64(final int lineLength, final byte[] lineSeparator) {
912         this(lineLength, lineSeparator, false);
913     }
914 
915     /**
916      * Constructs a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
917      * <p>
918      * When encoding the line length and line separator are given in the constructor, and the encoding table is STANDARD_ENCODE_TABLE.
919      * </p>
920      * <p>
921      * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
922      * </p>
923      * <p>
924      * When decoding all variants are supported.
925      * </p>
926      *
927      * @param lineLength    Each line of encoded data will be at most of the given length (rounded down to the nearest multiple of 4). If lineLength &lt;= 0,
928      *                      then the output will not be divided into lines (chunks). Ignored when decoding.
929      * @param lineSeparator Each line of encoded data will end with this sequence of bytes.
930      * @param urlSafe       Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode operations. Decoding seamlessly
931      *                      handles both modes. <strong>No padding is added when using the URL-safe alphabet.</strong>
932      * @throws IllegalArgumentException Thrown when the {@code lineSeparator} contains Base64 characters.
933      * @since 1.4
934      * @deprecated Use {@link #builder()} and {@link Builder}.
935      */
936     @Deprecated
937     public Base64(final int lineLength, final byte[] lineSeparator, final boolean urlSafe) {
938         this(builder().setLineLength(lineLength).setLineSeparator(lineSeparator != null ? lineSeparator : EMPTY_BYTE_ARRAY).setPadding(PAD_DEFAULT)
939                 .setEncodeTableRaw(toUrlSafeEncodeTable(urlSafe)).setDecodingPolicy(DECODING_POLICY_DEFAULT));
940     }
941 
942     /**
943      * Constructs a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
944      * <p>
945      * When encoding the line length and line separator are given in the constructor, and the encoding table is STANDARD_ENCODE_TABLE.
946      * </p>
947      * <p>
948      * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
949      * </p>
950      * <p>
951      * When decoding all variants are supported.
952      * </p>
953      *
954      * @param lineLength     Each line of encoded data will be at most of the given length (rounded down to the nearest multiple of 4). If lineLength &lt;= 0,
955      *                       then the output will not be divided into lines (chunks). Ignored when decoding.
956      * @param lineSeparator  Each line of encoded data will end with this sequence of bytes.
957      * @param urlSafe        Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode operations. Decoding seamlessly
958      *                       handles both modes. <strong>No padding is added when using the URL-safe alphabet.</strong>
959      * @param decodingPolicy The decoding policy.
960      * @throws IllegalArgumentException Thrown when the {@code lineSeparator} contains Base64 characters.
961      * @since 1.15
962      * @deprecated Use {@link #builder()} and {@link Builder}.
963      */
964     @Deprecated
965     public Base64(final int lineLength, final byte[] lineSeparator, final boolean urlSafe, final CodecPolicy decodingPolicy) {
966         this(builder().setLineLength(lineLength).setLineSeparator(lineSeparator).setPadding(PAD_DEFAULT).setEncodeTableRaw(toUrlSafeEncodeTable(urlSafe))
967                 .setDecodingPolicy(decodingPolicy));
968     }
969 
970     /**
971      * <p>
972      * Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once with the data to decode, and once with
973      * inAvail set to "-1" to alert decoder that EOF has been reached. The "-1" call is not necessary when decoding, but it doesn't hurt, either.
974      * </p>
975      * <p>
976      * Ignores all non-base64 characters. This is how chunked (for example 76 character) data is handled, since CR and LF are silently ignored, but has
977      * implications for other bytes, too. This method subscribes to the garbage-in, garbage-out philosophy: it will not check the provided data for validity.
978      * </p>
979      * <p>
980      * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
981      * https://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
982      * </p>
983      *
984      * @param input   byte[] array of ASCII data to base64 decode.
985      * @param inPos   Position to start reading data from.
986      * @param inAvail Amount of bytes available from input for decoding.
987      * @param context The context to be used.
988      */
989     @Override
990     void decode(final byte[] input, int inPos, final int inAvail, final Context context) {
991         if (context.eof) {
992             return;
993         }
994         if (inAvail < 0) {
995             context.eof = true;
996         }
997         final int decodeSize = this.encodeSize - 1;
998         for (int i = 0; i < inAvail; i++) {
999             final int b = input[inPos++] & 0xff;
1000             if (b == (pad & 0xff)) {
1001                 // We're done.
1002                 context.eof = true;
1003                 break;
1004             }
1005             final byte[] buffer = ensureBufferSize(decodeSize, context);
1006             if (b < decodeTable.length) {
1007                 final int result = decodeTable[b];
1008                 if (result >= 0) {
1009                     context.modulus = (context.modulus + 1) % BYTES_PER_ENCODED_BLOCK;
1010                     context.ibitWorkArea = (context.ibitWorkArea << BITS_PER_ENCODED_BYTE) + result;
1011                     if (context.modulus == 0) {
1012                         buffer[context.pos++] = (byte) (context.ibitWorkArea >> 16 & MASK_8BITS);
1013                         buffer[context.pos++] = (byte) (context.ibitWorkArea >> 8 & MASK_8BITS);
1014                         buffer[context.pos++] = (byte) (context.ibitWorkArea & MASK_8BITS);
1015                     }
1016                 }
1017             }
1018         }
1019 
1020         // Two forms of EOF as far as base64 decoder is concerned: actual
1021         // EOF (-1) and first time '=' character is encountered in stream.
1022         // This approach makes the '=' padding characters completely optional.
1023         if (context.eof && context.modulus != 0) {
1024             final byte[] buffer = ensureBufferSize(decodeSize, context);
1025 
1026             // We have some spare bits remaining
1027             // Output all whole multiples of 8 bits and ignore the rest
1028             switch (context.modulus) {
1029 //              case 0 : // impossible, as excluded above
1030                 case 1 : // 6 bits - either ignore entirely, or raise an exception
1031                     validateTrailingCharacter();
1032                     break;
1033                 case 2 : // 12 bits = 8 + 4
1034                     validateCharacter(MASK_4_BITS, context);
1035                     context.ibitWorkArea = context.ibitWorkArea >> 4; // dump the extra 4 bits
1036                     buffer[context.pos++] = (byte) (context.ibitWorkArea & MASK_8BITS);
1037                     break;
1038                 case 3 : // 18 bits = 8 + 8 + 2
1039                     validateCharacter(MASK_2_BITS, context);
1040                     context.ibitWorkArea = context.ibitWorkArea >> 2; // dump 2 bits
1041                     buffer[context.pos++] = (byte) (context.ibitWorkArea >> 8 & MASK_8BITS);
1042                     buffer[context.pos++] = (byte) (context.ibitWorkArea & MASK_8BITS);
1043                     break;
1044                 default:
1045                     throw new IllegalStateException("Impossible modulus " + context.modulus);
1046             }
1047         }
1048     }
1049 
1050     /**
1051      * <p>
1052      * Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with the data to encode, and once with
1053      * inAvail set to "-1" to alert encoder that EOF has been reached, to flush last remaining bytes (if not multiple of 3).
1054      * </p>
1055      * <p>
1056      * <strong>No padding is added when encoding using the URL-safe alphabet.</strong>
1057      * </p>
1058      * <p>
1059      * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
1060      * https://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
1061      * </p>
1062      *
1063      * @param in      byte[] array of binary data to base64 encode.
1064      * @param inPos   Position to start reading data from.
1065      * @param inAvail Amount of bytes available from input for encoding.
1066      * @param context The context to be used.
1067      */
1068     @Override
1069     void encode(final byte[] in, int inPos, final int inAvail, final Context context) {
1070         if (context.eof) {
1071             return;
1072         }
1073         // inAvail < 0 is how we're informed of EOF in the underlying data we're
1074         // encoding.
1075         if (inAvail < 0) {
1076             context.eof = true;
1077             if (0 == context.modulus && lineLength == 0) {
1078                 return; // no leftovers to process and not using chunking
1079             }
1080             final byte[] buffer = ensureBufferSize(encodeSize, context);
1081             final int savedPos = context.pos;
1082             switch (context.modulus) { // 0-2
1083                 case 0 : // nothing to do here
1084                     break;
1085                 case 1 : // 8 bits = 6 + 2
1086                     // top 6 bits:
1087                     buffer[context.pos++] = encodeTable[context.ibitWorkArea >> 2 & MASK_6_BITS];
1088                     // remaining 2:
1089                     buffer[context.pos++] = encodeTable[context.ibitWorkArea << 4 & MASK_6_BITS];
1090                     // URL-SAFE skips the padding to further reduce size.
1091                     if (isStandardEncodeTable) {
1092                         buffer[context.pos++] = pad;
1093                         buffer[context.pos++] = pad;
1094                     }
1095                     break;
1096 
1097                 case 2 : // 16 bits = 6 + 6 + 4
1098                     buffer[context.pos++] = encodeTable[context.ibitWorkArea >> 10 & MASK_6_BITS];
1099                     buffer[context.pos++] = encodeTable[context.ibitWorkArea >> 4 & MASK_6_BITS];
1100                     buffer[context.pos++] = encodeTable[context.ibitWorkArea << 2 & MASK_6_BITS];
1101                     // URL-SAFE skips the padding to further reduce size.
1102                     if (isStandardEncodeTable) {
1103                         buffer[context.pos++] = pad;
1104                     }
1105                     break;
1106                 default:
1107                     throw new IllegalStateException("Impossible modulus " + context.modulus);
1108             }
1109             context.currentLinePos += context.pos - savedPos; // keep track of current line position
1110             // if currentPos == 0 we are at the start of a line, so don't add CRLF
1111             if (lineLength > 0 && context.currentLinePos > 0) {
1112                 System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length);
1113                 context.pos += lineSeparator.length;
1114             }
1115         } else {
1116             for (int i = 0; i < inAvail; i++) {
1117                 final byte[] buffer = ensureBufferSize(encodeSize, context);
1118                 context.modulus = (context.modulus + 1) % BYTES_PER_UNENCODED_BLOCK;
1119                 int b = in[inPos++];
1120                 if (b < 0) {
1121                     b += 256;
1122                 }
1123                 context.ibitWorkArea = (context.ibitWorkArea << 8) + b; // BITS_PER_BYTE
1124                 if (0 == context.modulus) { // 3 bytes = 24 bits = 4 * 6 bits to extract
1125                     buffer[context.pos++] = encodeTable[context.ibitWorkArea >> 18 & MASK_6_BITS];
1126                     buffer[context.pos++] = encodeTable[context.ibitWorkArea >> 12 & MASK_6_BITS];
1127                     buffer[context.pos++] = encodeTable[context.ibitWorkArea >> 6 & MASK_6_BITS];
1128                     buffer[context.pos++] = encodeTable[context.ibitWorkArea & MASK_6_BITS];
1129                     context.currentLinePos += BYTES_PER_ENCODED_BLOCK;
1130                     if (lineLength > 0 && lineLength <= context.currentLinePos) {
1131                         System.arraycopy(lineSeparator, 0, buffer, context.pos, lineSeparator.length);
1132                         context.pos += lineSeparator.length;
1133                         context.currentLinePos = 0;
1134                     }
1135                 }
1136             }
1137         }
1138     }
1139 
1140     /**
1141      * Gets the line separator (for testing only).
1142      *
1143      * @return The line separator.
1144      */
1145     byte[] getLineSeparator() {
1146         return lineSeparator;
1147     }
1148 
1149     /**
1150      * Returns whether or not the {@code octet} is in the Base64 alphabet.
1151      *
1152      * @param octet The value to test.
1153      * @return {@code true} if the value is defined in the Base64 alphabet {@code false} otherwise.
1154      */
1155     @Override
1156     protected boolean isInAlphabet(final byte octet) {
1157         final int value = octet & 0xff;
1158         return value < decodeTable.length && decodeTable[value] != -1;
1159     }
1160 
1161     /**
1162      * Returns our current encode mode. True if we're URL-safe, false otherwise.
1163      *
1164      * @return true if we're in URL-safe mode, false otherwise.
1165      * @since 1.4
1166      */
1167     public boolean isUrlSafe() {
1168         return isUrlSafe;
1169     }
1170 
1171     /**
1172      * Validates whether decoding the final trailing character is possible in the context of the set of possible Base64 values.
1173      * <p>
1174      * The character is valid if the lower bits within the provided mask are zero. This is used to test the final trailing base-64 digit is zero in the bits
1175      * that will be discarded.
1176      * </p>
1177      *
1178      * @param emptyBitsMask The mask of the lower bits that should be empty.
1179      * @param context       The context to be used.
1180      * @throws IllegalArgumentException if the bits being checked contain any non-zero value.
1181      */
1182     private void validateCharacter(final int emptyBitsMask, final Context context) {
1183         if (isStrictDecoding() && (context.ibitWorkArea & emptyBitsMask) != 0) {
1184             throw new IllegalArgumentException("Strict decoding: Last encoded character (before the paddings if any) is a valid " +
1185                     "Base64 alphabet but not a possible encoding. Expected the discarded bits from the character to be zero.");
1186         }
1187     }
1188 
1189     /**
1190      * Validates whether decoding allows an entire final trailing character that cannot be used for a complete byte.
1191      *
1192      * @throws IllegalArgumentException if strict decoding is enabled.
1193      */
1194     private void validateTrailingCharacter() {
1195         if (isStrictDecoding()) {
1196             throw new IllegalArgumentException("Strict decoding: Last encoded character (before the paddings if any) is a valid " +
1197                     "Base64 alphabet but not a possible encoding. Decoding requires at least two trailing 6-bit characters to create bytes.");
1198         }
1199     }
1200 
1201 }