Base64.java 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. // Portions copyright 2002, Google, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package com.esenthel;
  15. // This code was converted from code at http://iharder.sourceforge.net/base64/
  16. // Lots of extraneous features were removed.
  17. /* The original code said:
  18. * <p>
  19. * I am placing this code in the Public Domain. Do with it as you will.
  20. * This software comes with no guarantees or warranties but with
  21. * plenty of well-wishing instead!
  22. * Please visit
  23. * <a href="http://iharder.net/xmlizable">http://iharder.net/xmlizable</a>
  24. * periodically to check for updates or to contribute improvements.
  25. * </p>
  26. *
  27. * @author Robert Harder
  28. * @author [email protected]
  29. * @version 1.3
  30. */
  31. /**
  32. * Base64 converter class. This code is not a complete MIME encoder;
  33. * it simply converts binary data to base64 data and back.
  34. *
  35. * <p>Note {@link CharBase64} is a GWT-compatible implementation of this
  36. * class.
  37. */
  38. public class Base64 {
  39. /** Specify encoding (value is {@code true}). */
  40. public final static boolean ENCODE = true;
  41. /** Specify decoding (value is {@code false}). */
  42. public final static boolean DECODE = false;
  43. /** The equals sign (=) as a byte. */
  44. private final static byte EQUALS_SIGN = (byte) '=';
  45. /** The new line character (\n) as a byte. */
  46. private final static byte NEW_LINE = (byte) '\n';
  47. /**
  48. * The 64 valid Base64 values.
  49. */
  50. private final static byte[] ALPHABET =
  51. {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
  52. (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',
  53. (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',
  54. (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',
  55. (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',
  56. (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
  57. (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
  58. (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
  59. (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',
  60. (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',
  61. (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',
  62. (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',
  63. (byte) '9', (byte) '+', (byte) '/'};
  64. /**
  65. * The 64 valid web safe Base64 values.
  66. */
  67. private final static byte[] WEBSAFE_ALPHABET =
  68. {(byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
  69. (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K',
  70. (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P',
  71. (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U',
  72. (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z',
  73. (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e',
  74. (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
  75. (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o',
  76. (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',
  77. (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y',
  78. (byte) 'z', (byte) '0', (byte) '1', (byte) '2', (byte) '3',
  79. (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',
  80. (byte) '9', (byte) '-', (byte) '_'};
  81. /**
  82. * Translates a Base64 value to either its 6-bit reconstruction value
  83. * or a negative number indicating some other meaning.
  84. **/
  85. private final static byte[] DECODABET = {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
  86. -5, -5, // Whitespace: Tab and Linefeed
  87. -9, -9, // Decimal 11 - 12
  88. -5, // Whitespace: Carriage Return
  89. -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
  90. -9, -9, -9, -9, -9, // Decimal 27 - 31
  91. -5, // Whitespace: Space
  92. -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
  93. 62, // Plus sign at decimal 43
  94. -9, -9, -9, // Decimal 44 - 46
  95. 63, // Slash at decimal 47
  96. 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
  97. -9, -9, -9, // Decimal 58 - 60
  98. -1, // Equals sign at decimal 61
  99. -9, -9, -9, // Decimal 62 - 64
  100. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
  101. 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
  102. -9, -9, -9, -9, -9, -9, // Decimal 91 - 96
  103. 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
  104. 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
  105. -9, -9, -9, -9, -9 // Decimal 123 - 127
  106. /* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139
  107. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
  108. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
  109. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
  110. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
  111. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
  112. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
  113. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
  114. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
  115. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
  116. };
  117. /** The web safe decodabet */
  118. private final static byte[] WEBSAFE_DECODABET =
  119. {-9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
  120. -5, -5, // Whitespace: Tab and Linefeed
  121. -9, -9, // Decimal 11 - 12
  122. -5, // Whitespace: Carriage Return
  123. -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
  124. -9, -9, -9, -9, -9, // Decimal 27 - 31
  125. -5, // Whitespace: Space
  126. -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 44
  127. 62, // Dash '-' sign at decimal 45
  128. -9, -9, // Decimal 46-47
  129. 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
  130. -9, -9, -9, // Decimal 58 - 60
  131. -1, // Equals sign at decimal 61
  132. -9, -9, -9, // Decimal 62 - 64
  133. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
  134. 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
  135. -9, -9, -9, -9, // Decimal 91-94
  136. 63, // Underscore '_' at decimal 95
  137. -9, // Decimal 96
  138. 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
  139. 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
  140. -9, -9, -9, -9, -9 // Decimal 123 - 127
  141. /* ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139
  142. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
  143. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
  144. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
  145. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
  146. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
  147. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
  148. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
  149. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
  150. -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
  151. };
  152. // Indicates white space in encoding
  153. private final static byte WHITE_SPACE_ENC = -5;
  154. // Indicates equals sign in encoding
  155. private final static byte EQUALS_SIGN_ENC = -1;
  156. /** Defeats instantiation. */
  157. private Base64() {
  158. }
  159. /* ******** E N C O D I N G M E T H O D S ******** */
  160. /**
  161. * Encodes up to three bytes of the array <var>source</var>
  162. * and writes the resulting four Base64 bytes to <var>destination</var>.
  163. * The source and destination arrays can be manipulated
  164. * anywhere along their length by specifying
  165. * <var>srcOffset</var> and <var>destOffset</var>.
  166. * This method does not check to make sure your arrays
  167. * are large enough to accommodate <var>srcOffset</var> + 3 for
  168. * the <var>source</var> array or <var>destOffset</var> + 4 for
  169. * the <var>destination</var> array.
  170. * The actual number of significant bytes in your array is
  171. * given by <var>numSigBytes</var>.
  172. *
  173. * @param source the array to convert
  174. * @param srcOffset the index where conversion begins
  175. * @param numSigBytes the number of significant bytes in your array
  176. * @param destination the array to hold the conversion
  177. * @param destOffset the index where output will be put
  178. * @param alphabet is the encoding alphabet
  179. * @return the <var>destination</var> array
  180. * @since 1.3
  181. */
  182. private static byte[] encode3to4(byte[] source, int srcOffset,
  183. int numSigBytes, byte[] destination, int destOffset, byte[] alphabet) {
  184. // 1 2 3
  185. // 01234567890123456789012345678901 Bit position
  186. // --------000000001111111122222222 Array position from threeBytes
  187. // --------| || || || | Six bit groups to index alphabet
  188. // >>18 >>12 >> 6 >> 0 Right shift necessary
  189. // 0x3f 0x3f 0x3f Additional AND
  190. // Create buffer with zero-padding if there are only one or two
  191. // significant bytes passed in the array.
  192. // We have to shift left 24 in order to flush out the 1's that appear
  193. // when Java treats a value as negative that is cast from a byte to an int.
  194. int inBuff =
  195. (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
  196. | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
  197. | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
  198. switch (numSigBytes) {
  199. case 3:
  200. destination[destOffset] = alphabet[(inBuff >>> 18)];
  201. destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];
  202. destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f];
  203. destination[destOffset + 3] = alphabet[(inBuff) & 0x3f];
  204. return destination;
  205. case 2:
  206. destination[destOffset] = alphabet[(inBuff >>> 18)];
  207. destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];
  208. destination[destOffset + 2] = alphabet[(inBuff >>> 6) & 0x3f];
  209. destination[destOffset + 3] = EQUALS_SIGN;
  210. return destination;
  211. case 1:
  212. destination[destOffset] = alphabet[(inBuff >>> 18)];
  213. destination[destOffset + 1] = alphabet[(inBuff >>> 12) & 0x3f];
  214. destination[destOffset + 2] = EQUALS_SIGN;
  215. destination[destOffset + 3] = EQUALS_SIGN;
  216. return destination;
  217. default:
  218. return destination;
  219. } // end switch
  220. } // end encode3to4
  221. /**
  222. * Encodes a byte array into Base64 notation.
  223. * Equivalent to calling
  224. * {@code encodeBytes(source, 0, source.length)}
  225. *
  226. * @param source The data to convert
  227. * @since 1.4
  228. */
  229. public static String encode(byte[] source) {
  230. return encode(source, 0, source.length, ALPHABET, true);
  231. }
  232. /**
  233. * Encodes a byte array into web safe Base64 notation.
  234. *
  235. * @param source The data to convert
  236. * @param doPadding is {@code true} to pad result with '=' chars
  237. * if it does not fall on 3 byte boundaries
  238. */
  239. public static String encodeWebSafe(byte[] source, boolean doPadding) {
  240. return encode(source, 0, source.length, WEBSAFE_ALPHABET, doPadding);
  241. }
  242. /**
  243. * Encodes a byte array into Base64 notation.
  244. *
  245. * @param source the data to convert
  246. * @param off offset in array where conversion should begin
  247. * @param len length of data to convert
  248. * @param alphabet the encoding alphabet
  249. * @param doPadding is {@code true} to pad result with '=' chars
  250. * if it does not fall on 3 byte boundaries
  251. * @since 1.4
  252. */
  253. public static String encode(byte[] source, int off, int len, byte[] alphabet,
  254. boolean doPadding) {
  255. byte[] outBuff = encode(source, off, len, alphabet, Integer.MAX_VALUE);
  256. int outLen = outBuff.length;
  257. // If doPadding is false, set length to truncate '='
  258. // padding characters
  259. while (doPadding == false && outLen > 0) {
  260. if (outBuff[outLen - 1] != '=') {
  261. break;
  262. }
  263. outLen -= 1;
  264. }
  265. return new String(outBuff, 0, outLen);
  266. }
  267. /**
  268. * Encodes a byte array into Base64 notation.
  269. *
  270. * @param source the data to convert
  271. * @param off offset in array where conversion should begin
  272. * @param len length of data to convert
  273. * @param alphabet is the encoding alphabet
  274. * @param maxLineLength maximum length of one line.
  275. * @return the BASE64-encoded byte array
  276. */
  277. public static byte[] encode(byte[] source, int off, int len, byte[] alphabet,
  278. int maxLineLength) {
  279. int lenDiv3 = (len + 2) / 3; // ceil(len / 3)
  280. int len43 = lenDiv3 * 4;
  281. byte[] outBuff = new byte[len43 // Main 4:3
  282. + (len43 / maxLineLength)]; // New lines
  283. int d = 0;
  284. int e = 0;
  285. int len2 = len - 2;
  286. int lineLength = 0;
  287. for (; d < len2; d += 3, e += 4) {
  288. // The following block of code is the same as
  289. // encode3to4( source, d + off, 3, outBuff, e, alphabet );
  290. // but inlined for faster encoding (~20% improvement)
  291. int inBuff =
  292. ((source[d + off] << 24) >>> 8)
  293. | ((source[d + 1 + off] << 24) >>> 16)
  294. | ((source[d + 2 + off] << 24) >>> 24);
  295. outBuff[e] = alphabet[(inBuff >>> 18)];
  296. outBuff[e + 1] = alphabet[(inBuff >>> 12) & 0x3f];
  297. outBuff[e + 2] = alphabet[(inBuff >>> 6) & 0x3f];
  298. outBuff[e + 3] = alphabet[(inBuff) & 0x3f];
  299. lineLength += 4;
  300. if (lineLength == maxLineLength) {
  301. outBuff[e + 4] = NEW_LINE;
  302. e++;
  303. lineLength = 0;
  304. } // end if: end of line
  305. } // end for: each piece of array
  306. if (d < len) {
  307. encode3to4(source, d + off, len - d, outBuff, e, alphabet);
  308. lineLength += 4;
  309. if (lineLength == maxLineLength) {
  310. // Add a last newline
  311. outBuff[e + 4] = NEW_LINE;
  312. e++;
  313. }
  314. e += 4;
  315. }
  316. assert (e == outBuff.length);
  317. return outBuff;
  318. }
  319. /* ******** D E C O D I N G M E T H O D S ******** */
  320. /**
  321. * Decodes four bytes from array <var>source</var>
  322. * and writes the resulting bytes (up to three of them)
  323. * to <var>destination</var>.
  324. * The source and destination arrays can be manipulated
  325. * anywhere along their length by specifying
  326. * <var>srcOffset</var> and <var>destOffset</var>.
  327. * This method does not check to make sure your arrays
  328. * are large enough to accommodate <var>srcOffset</var> + 4 for
  329. * the <var>source</var> array or <var>destOffset</var> + 3 for
  330. * the <var>destination</var> array.
  331. * This method returns the actual number of bytes that
  332. * were converted from the Base64 encoding.
  333. *
  334. *
  335. * @param source the array to convert
  336. * @param srcOffset the index where conversion begins
  337. * @param destination the array to hold the conversion
  338. * @param destOffset the index where output will be put
  339. * @param decodabet the decodabet for decoding Base64 content
  340. * @return the number of decoded bytes converted
  341. * @since 1.3
  342. */
  343. private static int decode4to3(byte[] source, int srcOffset,
  344. byte[] destination, int destOffset, byte[] decodabet) {
  345. // Example: Dk==
  346. if (source[srcOffset + 2] == EQUALS_SIGN) {
  347. int outBuff =
  348. ((decodabet[source[srcOffset]] << 24) >>> 6)
  349. | ((decodabet[source[srcOffset + 1]] << 24) >>> 12);
  350. destination[destOffset] = (byte) (outBuff >>> 16);
  351. return 1;
  352. } else if (source[srcOffset + 3] == EQUALS_SIGN) {
  353. // Example: DkL=
  354. int outBuff =
  355. ((decodabet[source[srcOffset]] << 24) >>> 6)
  356. | ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
  357. | ((decodabet[source[srcOffset + 2]] << 24) >>> 18);
  358. destination[destOffset] = (byte) (outBuff >>> 16);
  359. destination[destOffset + 1] = (byte) (outBuff >>> 8);
  360. return 2;
  361. } else {
  362. // Example: DkLE
  363. int outBuff =
  364. ((decodabet[source[srcOffset]] << 24) >>> 6)
  365. | ((decodabet[source[srcOffset + 1]] << 24) >>> 12)
  366. | ((decodabet[source[srcOffset + 2]] << 24) >>> 18)
  367. | ((decodabet[source[srcOffset + 3]] << 24) >>> 24);
  368. destination[destOffset] = (byte) (outBuff >> 16);
  369. destination[destOffset + 1] = (byte) (outBuff >> 8);
  370. destination[destOffset + 2] = (byte) (outBuff);
  371. return 3;
  372. }
  373. } // end decodeToBytes
  374. /**
  375. * Decodes data from Base64 notation.
  376. *
  377. * @param s the string to decode (decoded in default encoding)
  378. * @return the decoded data
  379. * @since 1.4
  380. */
  381. public static byte[] decode(String s) {
  382. byte[] bytes = s.getBytes();
  383. return decode(bytes, 0, bytes.length);
  384. }
  385. /**
  386. * Decodes data from web safe Base64 notation.
  387. * Web safe encoding uses '-' instead of '+', '_' instead of '/'
  388. *
  389. * @param s the string to decode (decoded in default encoding)
  390. * @return the decoded data
  391. */
  392. public static byte[] decodeWebSafe(String s) {
  393. byte[] bytes = s.getBytes();
  394. return decodeWebSafe(bytes, 0, bytes.length);
  395. }
  396. /**
  397. * Decodes Base64 content in byte array format and returns
  398. * the decoded byte array.
  399. *
  400. * @param source The Base64 encoded data
  401. * @return decoded data
  402. * @since 1.3
  403. * @throws Base64DecoderException
  404. */
  405. public static byte[] decode(byte[] source) {
  406. return decode(source, 0, source.length);
  407. }
  408. /**
  409. * Decodes web safe Base64 content in byte array format and returns
  410. * the decoded data.
  411. * Web safe encoding uses '-' instead of '+', '_' instead of '/'
  412. *
  413. * @param source the string to decode (decoded in default encoding)
  414. * @return the decoded data
  415. */
  416. public static byte[] decodeWebSafe(byte[] source) {
  417. return decodeWebSafe(source, 0, source.length);
  418. }
  419. /**
  420. * Decodes Base64 content in byte array format and returns
  421. * the decoded byte array.
  422. *
  423. * @param source the Base64 encoded data
  424. * @param off the offset of where to begin decoding
  425. * @param len the length of characters to decode
  426. * @return decoded data
  427. * @since 1.3
  428. * @throws Base64DecoderException
  429. */
  430. public static byte[] decode(byte[] source, int off, int len) {
  431. return decode(source, off, len, DECODABET);
  432. }
  433. /**
  434. * Decodes web safe Base64 content in byte array format and returns
  435. * the decoded byte array.
  436. * Web safe encoding uses '-' instead of '+', '_' instead of '/'
  437. *
  438. * @param source the Base64 encoded data
  439. * @param off the offset of where to begin decoding
  440. * @param len the length of characters to decode
  441. * @return decoded data
  442. */
  443. public static byte[] decodeWebSafe(byte[] source, int off, int len) {
  444. return decode(source, off, len, WEBSAFE_DECODABET);
  445. }
  446. /**
  447. * Decodes Base64 content using the supplied decodabet and returns
  448. * the decoded byte array.
  449. *
  450. * @param source the Base64 encoded data
  451. * @param off the offset of where to begin decoding
  452. * @param len the length of characters to decode
  453. * @param decodabet the decodabet for decoding Base64 content
  454. * @return decoded data
  455. */
  456. public static byte[] decode(byte[] source, int off, int len, byte[] decodabet) {
  457. int len34 = len * 3 / 4;
  458. byte[] outBuff = new byte[2 + len34]; // Upper limit on size of output
  459. int outBuffPosn = 0;
  460. byte[] b4 = new byte[4];
  461. int b4Posn = 0;
  462. int i = 0;
  463. byte sbiCrop = 0;
  464. byte sbiDecode = 0;
  465. for (i = 0; i < len; i++) {
  466. sbiCrop = (byte) (source[i + off] & 0x7f); // Only the low seven bits
  467. sbiDecode = decodabet[sbiCrop];
  468. if (sbiDecode >= WHITE_SPACE_ENC) { // White space Equals sign or better
  469. if (sbiDecode >= EQUALS_SIGN_ENC) {
  470. // An equals sign (for padding) must not occur at position 0 or 1
  471. // and must be the last byte[s] in the encoded value
  472. if (sbiCrop == EQUALS_SIGN) {
  473. int bytesLeft = len - i;
  474. byte lastByte = (byte) (source[len - 1 + off] & 0x7f);
  475. if (b4Posn == 0 || b4Posn == 1) {
  476. return null;
  477. } else if ((b4Posn == 3 && bytesLeft > 2)
  478. || (b4Posn == 4 && bytesLeft > 1)) {
  479. return null;
  480. } else if (lastByte != EQUALS_SIGN && lastByte != NEW_LINE) {
  481. return null;
  482. }
  483. break;
  484. }
  485. b4[b4Posn++] = sbiCrop;
  486. if (b4Posn == 4) {
  487. outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet);
  488. b4Posn = 0;
  489. }
  490. }
  491. } else {
  492. return null;
  493. }
  494. }
  495. // Because web safe encoding allows non padding base64 encodes, we
  496. // need to pad the rest of the b4 buffer with equal signs when
  497. // b4Posn != 0. There can be at most 2 equal signs at the end of
  498. // four characters, so the b4 buffer must have two or three
  499. // characters. This also catches the case where the input is
  500. // padded with EQUALS_SIGN
  501. if (b4Posn != 0) {
  502. if (b4Posn == 1) {
  503. return null;
  504. }
  505. b4[b4Posn++] = EQUALS_SIGN;
  506. outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, decodabet);
  507. }
  508. byte[] out = new byte[outBuffPosn];
  509. System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
  510. return out;
  511. }
  512. }