1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.crypto.tink.subtle; 18 19 import com.google.errorprone.annotations.CanIgnoreReturnValue; 20 import java.io.UnsupportedEncodingException; 21 import java.nio.charset.Charset; 22 23 /** 24 * Utilities for encoding and decoding the Base64 representation of binary data. 25 * 26 * <p>See RFCs <a href="http://www.ietf.org/rfc/rfc2045.txt">2045</a> and <a 27 * href="http://www.ietf.org/rfc/rfc3548.txt">3548</a>. 28 * 29 * <p>This is a copy of android.util.Base64, with minor modifications to to fix style and ErrorProne 30 * errors. 31 * 32 * @since 1.0.0 33 */ 34 public final class Base64 { 35 private static final Charset UTF_8 = Charset.forName("UTF-8"); 36 37 /** Default values for encoder/decoder flags. */ 38 public static final int DEFAULT = 0; 39 40 /** Encoder flag bit to omit the padding '=' characters at the end of the output (if any). */ 41 public static final int NO_PADDING = 1; 42 43 /** Encoder flag bit to omit all line terminators (i.e., the output will be on one long line). */ 44 public static final int NO_WRAP = 2; 45 46 /** 47 * Encoder flag bit to indicate lines should be terminated with a CRLF pair instead of just an LF. 48 * Has no effect if {@code NO_WRAP} is specified as well. 49 */ 50 public static final int CRLF = 4; 51 52 /** 53 * Encoder/decoder flag bit to indicate using the "URL and filename safe" variant of Base64 (see 54 * RFC 3548 section 4) where {@code -} and {@code _} are used in place of {@code +} and {@code /}. 55 */ 56 public static final int URL_SAFE = 8; 57 58 /** 59 * Flag to pass to {@link Base64OutputStream} to indicate that it should not close the output 60 * stream it is wrapping when it itself is closed. 61 */ 62 public static final int NO_CLOSE = 16; 63 64 // -------------------------------------------------------- 65 // shared code 66 // -------------------------------------------------------- 67 68 /* package */ abstract static class Coder { 69 public byte[] output; 70 public int op; 71 72 /** 73 * Encode/decode another block of input data. this.output is provided by the caller, and must be 74 * big enough to hold all the coded data. On exit, this.opwill be set to the length of the coded 75 * data. 76 * 77 * @param finish true if this is the final call to process for this object. Will finalize the 78 * coder state and include any final bytes in the output. 79 * @return true if the input so far is good; false if some error has been detected in the input 80 * stream.. 81 */ process(byte[] input, int offset, int len, boolean finish)82 public abstract boolean process(byte[] input, int offset, int len, boolean finish); 83 84 /** 85 * @return the maximum number of bytes a call to process() could produce for the given number of 86 * input bytes. This may be an overestimate. 87 */ maxOutputSize(int len)88 public abstract int maxOutputSize(int len); 89 } 90 91 // -------------------------------------------------------- 92 // decoding 93 // -------------------------------------------------------- 94 95 /** Decodes a base64 string to a byte array. */ decode(String input)96 public static byte[] decode(String input) { 97 return decode(input, DEFAULT | NO_WRAP); 98 } 99 100 /** 101 * Decode the Base64-encoded data in input and return the data in a new byte array. 102 * 103 * <p>The padding '=' characters at the end are considered optional, but if any are present, there 104 * must be the correct number of them. 105 * 106 * @param str the input String to decode, which is converted to bytes using the default charset 107 * @param flags controls certain features of the decoded output. Pass {@code DEFAULT} to decode 108 * standard Base64. 109 * @throws IllegalArgumentException if the input contains incorrect padding 110 */ decode(String str, int flags)111 public static byte[] decode(String str, int flags) { 112 return decode(str.getBytes(UTF_8), flags); 113 } 114 115 /** 116 * Decode the Base64-encoded data in input and return the data in a new byte array. 117 * 118 * <p>The padding '=' characters at the end are considered optional, but if any are present, there 119 * must be the correct number of them. 120 * 121 * @param input the input array to decode 122 * @param flags controls certain features of the decoded output. Pass {@code DEFAULT} to decode 123 * standard Base64. 124 * @throws IllegalArgumentException if the input contains incorrect padding 125 */ decode(byte[] input, int flags)126 public static byte[] decode(byte[] input, int flags) { 127 return decode(input, 0, input.length, flags); 128 } 129 130 /** 131 * Decode the Base64-encoded data in input and return the data in a new byte array. 132 * 133 * <p>The padding '=' characters at the end are considered optional, but if any are present, there 134 * must be the correct number of them. 135 * 136 * @param input the data to decode 137 * @param offset the position within the input array at which to start 138 * @param len the number of bytes of input to decode 139 * @param flags controls certain features of the decoded output. Pass {@code DEFAULT} to decode 140 * standard Base64. 141 * @throws IllegalArgumentException if the input contains incorrect padding 142 */ decode(byte[] input, int offset, int len, int flags)143 public static byte[] decode(byte[] input, int offset, int len, int flags) { 144 // Allocate space for the most data the input could represent. 145 // (It could contain less if it contains whitespace, etc.) 146 Decoder decoder = new Decoder(flags, new byte[len * 3 / 4]); 147 148 if (!decoder.process(input, offset, len, true)) { 149 throw new IllegalArgumentException("bad base-64"); 150 } 151 152 // Maybe we got lucky and allocated exactly enough output space. 153 if (decoder.op == decoder.output.length) { 154 return decoder.output; 155 } 156 157 // Need to shorten the array, so allocate a new one of the 158 // right size and copy. 159 byte[] temp = new byte[decoder.op]; 160 System.arraycopy(decoder.output, 0, temp, 0, decoder.op); 161 return temp; 162 } 163 164 /** Decodes a url-safe base64 string to a byte array. */ urlSafeDecode(String input)165 public static byte[] urlSafeDecode(String input) { 166 return decode(input, DEFAULT | NO_PADDING | NO_WRAP | URL_SAFE); 167 } 168 169 /* package */ static class Decoder extends Coder { 170 /** Lookup table for turning bytes into their position in the Base64 alphabet. */ 171 private static final int[] DECODE = { 172 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 173 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 174 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 175 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, 176 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 177 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, 178 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 179 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, 180 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 181 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 182 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 183 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 184 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 185 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 186 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 187 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 188 }; 189 190 /** 191 * Decode lookup table for the "web safe" variant (RFC 3548 sec. 4) where - and _ replace + and 192 * /. 193 */ 194 private static final int[] DECODE_WEBSAFE = { 195 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 196 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 197 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, 198 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, 199 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 200 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, 201 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 202 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, 203 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 204 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 205 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 206 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 207 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 208 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 209 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 210 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 211 }; 212 213 /** Non-data values in the DECODE arrays. */ 214 private static final int SKIP = -1; 215 216 private static final int EQUALS = -2; 217 218 /** 219 * States 0-3 are reading through the next input tuple. State 4 is having read one '=' and 220 * expecting exactly one more. State 5 is expecting no more data or padding characters in the 221 * input. State 6 is the error state; an error has been detected in the input and no future 222 * input can "fix" it. 223 */ 224 private int state; // state number (0 to 6) 225 226 private int value; 227 228 private final int[] alphabet; 229 Decoder(int flags, byte[] output)230 public Decoder(int flags, byte[] output) { 231 this.output = output; 232 233 alphabet = ((flags & URL_SAFE) == 0) ? DECODE : DECODE_WEBSAFE; 234 state = 0; 235 value = 0; 236 } 237 238 /** @return an overestimate for the number of bytes {@code len} bytes could decode to. */ 239 @Override maxOutputSize(int len)240 public int maxOutputSize(int len) { 241 return len * 3 / 4 + 10; 242 } 243 244 /** 245 * Decode another block of input data. 246 * 247 * @return true if the state machine is still healthy. false if bad base-64 data has been 248 * detected in the input stream. 249 */ 250 @Override process(byte[] input, int offset, int len, boolean finish)251 public boolean process(byte[] input, int offset, int len, boolean finish) { 252 if (this.state == 6) { 253 return false; 254 } 255 256 int p = offset; 257 len += offset; 258 259 // Using local variables makes the decoder about 12% 260 // faster than if we manipulate the member variables in 261 // the loop. (Even alphabet makes a measurable 262 // difference, which is somewhat surprising to me since 263 // the member variable is final.) 264 int state = this.state; 265 int value = this.value; 266 int op = 0; 267 final byte[] output = this.output; 268 final int[] alphabet = this.alphabet; 269 270 while (p < len) { 271 if (state == 0) { 272 while (p + 4 <= len 273 && (value = 274 ((alphabet[input[p] & 0xff] << 18) 275 | (alphabet[input[p + 1] & 0xff] << 12) 276 | (alphabet[input[p + 2] & 0xff] << 6) 277 | (alphabet[input[p + 3] & 0xff]))) 278 >= 0) { 279 output[op + 2] = (byte) value; 280 output[op + 1] = (byte) (value >> 8); 281 output[op] = (byte) (value >> 16); 282 op += 3; 283 p += 4; 284 } 285 if (p >= len) { 286 break; 287 } 288 } 289 290 // The fast path isn't available -- either we've read a 291 // partial tuple, or the next four input bytes aren't all 292 // data, or whatever. Fall back to the slower state 293 // machine implementation. 294 295 int d = alphabet[input[p++] & 0xff]; 296 297 switch (state) { 298 case 0: 299 if (d >= 0) { 300 value = d; 301 ++state; 302 } else if (d != SKIP) { 303 this.state = 6; 304 return false; 305 } 306 break; 307 308 case 1: 309 if (d >= 0) { 310 value = (value << 6) | d; 311 ++state; 312 } else if (d != SKIP) { 313 this.state = 6; 314 return false; 315 } 316 break; 317 318 case 2: 319 if (d >= 0) { 320 value = (value << 6) | d; 321 ++state; 322 } else if (d == EQUALS) { 323 // Emit the last (partial) output tuple; 324 // expect exactly one more padding character. 325 output[op++] = (byte) (value >> 4); 326 state = 4; 327 } else if (d != SKIP) { 328 this.state = 6; 329 return false; 330 } 331 break; 332 333 case 3: 334 if (d >= 0) { 335 // Emit the output triple and return to state 0. 336 value = (value << 6) | d; 337 output[op + 2] = (byte) value; 338 output[op + 1] = (byte) (value >> 8); 339 output[op] = (byte) (value >> 16); 340 op += 3; 341 state = 0; 342 } else if (d == EQUALS) { 343 // Emit the last (partial) output tuple; 344 // expect no further data or padding characters. 345 output[op + 1] = (byte) (value >> 2); 346 output[op] = (byte) (value >> 10); 347 op += 2; 348 state = 5; 349 } else if (d != SKIP) { 350 this.state = 6; 351 return false; 352 } 353 break; 354 355 case 4: 356 if (d == EQUALS) { 357 ++state; 358 } else if (d != SKIP) { 359 this.state = 6; 360 return false; 361 } 362 break; 363 364 case 5: 365 if (d != SKIP) { 366 this.state = 6; 367 return false; 368 } 369 break; 370 default: 371 break; 372 } 373 } 374 375 if (!finish) { 376 // We're out of input, but a future call could provide 377 // more. 378 this.state = state; 379 this.value = value; 380 this.op = op; 381 return true; 382 } 383 384 // Done reading input. Now figure out where we are left in 385 // the state machine and finish up. 386 387 switch (state) { 388 case 0: 389 // Output length is a multiple of three. Fine. 390 break; 391 case 1: 392 // Read one extra input byte, which isn't enough to 393 // make another output byte. Illegal. 394 this.state = 6; 395 return false; 396 case 2: 397 // Read two extra input bytes, enough to emit 1 more 398 // output byte. Fine. 399 output[op++] = (byte) (value >> 4); 400 break; 401 case 3: 402 // Read three extra input bytes, enough to emit 2 more 403 // output bytes. Fine. 404 output[op++] = (byte) (value >> 10); 405 output[op++] = (byte) (value >> 2); 406 break; 407 case 4: 408 // Read one padding '=' when we expected 2. Illegal. 409 this.state = 6; 410 return false; 411 case 5: 412 // Read all the padding '='s we expected and no more. 413 // Fine. 414 break; 415 default: 416 break; 417 } 418 419 this.state = state; 420 this.op = op; 421 return true; 422 } 423 } 424 425 // -------------------------------------------------------- 426 // encoding 427 // -------------------------------------------------------- 428 429 /** Base64 encodes a byte array to a string. */ encode(final byte[] input)430 public static String encode(final byte[] input) { 431 return encodeToString(input, DEFAULT | NO_WRAP); 432 } 433 434 /** 435 * Base64-encode the given data and return a newly allocated byte[] with the result. 436 * 437 * @param input the data to encode 438 * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} results 439 * in output that adheres to RFC 2045. 440 */ encode(byte[] input, int flags)441 public static byte[] encode(byte[] input, int flags) { 442 return encode(input, 0, input.length, flags); 443 } 444 445 /** 446 * Base64-encode the given data and return a newly allocated byte[] with the result. 447 * 448 * @param input the data to encode 449 * @param offset the position within the input array at which to start 450 * @param len the number of bytes of input to encode 451 * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} results 452 * in output that adheres to RFC 2045. 453 */ encode(byte[] input, int offset, int len, int flags)454 public static byte[] encode(byte[] input, int offset, int len, int flags) { 455 Encoder encoder = new Encoder(flags, null); 456 457 // Compute the exact length of the array we will produce. 458 int outputLen = len / 3 * 4; 459 460 // Account for the tail of the data and the padding bytes, if any. 461 if (encoder.doPadding) { 462 if (len % 3 > 0) { 463 outputLen += 4; 464 } 465 } else { 466 switch (len % 3) { 467 case 0: 468 break; 469 case 1: 470 outputLen += 2; 471 break; 472 case 2: 473 outputLen += 3; 474 break; 475 default: 476 break; 477 } 478 } 479 480 // Account for the newlines, if any. 481 if (encoder.doNewline && len > 0) { 482 outputLen += (((len - 1) / (3 * Encoder.LINE_GROUPS)) + 1) * (encoder.doCr ? 2 : 1); 483 } 484 485 encoder.output = new byte[outputLen]; 486 encoder.process(input, offset, len, true); 487 488 assert encoder.op == outputLen; 489 490 return encoder.output; 491 } 492 493 /** Url-safe base64 encodes a byte array to a string. */ urlSafeEncode(final byte[] input)494 public static String urlSafeEncode(final byte[] input) { 495 return encodeToString(input, DEFAULT | NO_PADDING | NO_WRAP | URL_SAFE); 496 } 497 498 /** 499 * Base64-encode the given data and return a newly allocated String with the result. 500 * 501 * @param input the data to encode 502 * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} results 503 * in output that adheres to RFC 2045. 504 */ encodeToString(byte[] input, int flags)505 public static String encodeToString(byte[] input, int flags) { 506 try { 507 return new String(encode(input, flags), "US-ASCII"); 508 } catch (UnsupportedEncodingException e) { 509 // US-ASCII is guaranteed to be available. 510 throw new AssertionError(e); 511 } 512 } 513 514 /** 515 * Base64-encode the given data and return a newly allocated String with the result. 516 * 517 * @param input the data to encode 518 * @param offset the position within the input array at which to start 519 * @param len the number of bytes of input to encode 520 * @param flags controls certain features of the encoded output. Passing {@code DEFAULT} results 521 * in output that adheres to RFC 2045. 522 */ encodeToString(byte[] input, int offset, int len, int flags)523 public static String encodeToString(byte[] input, int offset, int len, int flags) { 524 try { 525 return new String(encode(input, offset, len, flags), "US-ASCII"); 526 } catch (UnsupportedEncodingException e) { 527 // US-ASCII is guaranteed to be available. 528 throw new AssertionError(e); 529 } 530 } 531 532 /* package */ static class Encoder extends Coder { 533 /** 534 * Emit a new line every this many output tuples. Corresponds to a 76-character line length (the 535 * maximum allowable according to <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>). 536 */ 537 public static final int LINE_GROUPS = 19; 538 539 /** Lookup table for turning Base64 alphabet positions (6 bits) into output bytes. */ 540 private static final byte[] ENCODE = { 541 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 542 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 543 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 544 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', 545 }; 546 547 /** Lookup table for turning Base64 alphabet positions (6 bits) into output bytes. */ 548 private static final byte[] ENCODE_WEBSAFE = { 549 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 550 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 551 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 552 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_', 553 }; 554 555 private final byte[] tail; 556 /* package */ int tailLen; 557 private int count; 558 559 public final boolean doPadding; 560 public final boolean doNewline; 561 public final boolean doCr; 562 private final byte[] alphabet; 563 Encoder(int flags, byte[] output)564 public Encoder(int flags, byte[] output) { 565 this.output = output; 566 567 doPadding = (flags & NO_PADDING) == 0; 568 doNewline = (flags & NO_WRAP) == 0; 569 doCr = (flags & CRLF) != 0; 570 alphabet = ((flags & URL_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE; 571 572 tail = new byte[2]; 573 tailLen = 0; 574 575 count = doNewline ? LINE_GROUPS : -1; 576 } 577 578 /** @return an overestimate for the number of bytes {@code len} bytes could encode to. */ 579 @Override maxOutputSize(int len)580 public int maxOutputSize(int len) { 581 return len * 8 / 5 + 10; 582 } 583 584 /** 585 * Processes the input to encode it in base 64. 586 * 587 * <p>This function always returns true -- encoding can never fail. So if one knows that one has 588 * this class one can ignore the return value. 589 */ 590 @CanIgnoreReturnValue 591 @Override process(byte[] input, int offset, int len, boolean finish)592 public boolean process(byte[] input, int offset, int len, boolean finish) { 593 // Using local variables makes the encoder about 9% faster. 594 final byte[] alphabet = this.alphabet; 595 final byte[] output = this.output; 596 int op = 0; 597 int count = this.count; 598 599 int p = offset; 600 len += offset; 601 int v = -1; 602 603 // First we need to concatenate the tail of the previous call 604 // with any input bytes available now and see if we can empty 605 // the tail. 606 607 switch (tailLen) { 608 case 0: 609 // There was no tail. 610 break; 611 612 case 1: 613 if (p + 2 <= len) { 614 // A 1-byte tail with at least 2 bytes of 615 // input available now. 616 v = ((tail[0] & 0xff) << 16) | ((input[p++] & 0xff) << 8) | (input[p++] & 0xff); 617 tailLen = 0; 618 } 619 break; 620 621 case 2: 622 if (p + 1 <= len) { 623 // A 2-byte tail with at least 1 byte of input. 624 v = ((tail[0] & 0xff) << 16) | ((tail[1] & 0xff) << 8) | (input[p++] & 0xff); 625 tailLen = 0; 626 } 627 break; 628 default: 629 break; 630 } 631 632 if (v != -1) { 633 output[op++] = alphabet[(v >> 18) & 0x3f]; 634 output[op++] = alphabet[(v >> 12) & 0x3f]; 635 output[op++] = alphabet[(v >> 6) & 0x3f]; 636 output[op++] = alphabet[v & 0x3f]; 637 if (--count == 0) { 638 if (doCr) { 639 output[op++] = '\r'; 640 } 641 output[op++] = '\n'; 642 count = LINE_GROUPS; 643 } 644 } 645 646 // At this point either there is no tail, or there are fewer 647 // than 3 bytes of input available. 648 649 // The main loop, turning 3 input bytes into 4 output bytes on 650 // each iteration. 651 while (p + 3 <= len) { 652 v = ((input[p] & 0xff) << 16) | ((input[p + 1] & 0xff) << 8) | (input[p + 2] & 0xff); 653 output[op] = alphabet[(v >> 18) & 0x3f]; 654 output[op + 1] = alphabet[(v >> 12) & 0x3f]; 655 output[op + 2] = alphabet[(v >> 6) & 0x3f]; 656 output[op + 3] = alphabet[v & 0x3f]; 657 p += 3; 658 op += 4; 659 if (--count == 0) { 660 if (doCr) { 661 output[op++] = '\r'; 662 } 663 output[op++] = '\n'; 664 count = LINE_GROUPS; 665 } 666 } 667 668 if (finish) { 669 // Finish up the tail of the input. Note that we need to 670 // consume any bytes in tail before any bytes 671 // remaining in input; there should be at most two bytes 672 // total. 673 674 if (p - tailLen == len - 1) { 675 int t = 0; 676 v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4; 677 tailLen -= t; 678 output[op++] = alphabet[(v >> 6) & 0x3f]; 679 output[op++] = alphabet[v & 0x3f]; 680 if (doPadding) { 681 output[op++] = '='; 682 output[op++] = '='; 683 } 684 if (doNewline) { 685 if (doCr) { 686 output[op++] = '\r'; 687 } 688 output[op++] = '\n'; 689 } 690 } else if (p - tailLen == len - 2) { 691 int t = 0; 692 v = 693 (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10) 694 | (((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2); 695 tailLen -= t; 696 output[op++] = alphabet[(v >> 12) & 0x3f]; 697 output[op++] = alphabet[(v >> 6) & 0x3f]; 698 output[op++] = alphabet[v & 0x3f]; 699 if (doPadding) { 700 output[op++] = '='; 701 } 702 if (doNewline) { 703 if (doCr) { 704 output[op++] = '\r'; 705 } 706 output[op++] = '\n'; 707 } 708 } else if (doNewline && op > 0 && count != LINE_GROUPS) { 709 if (doCr) { 710 output[op++] = '\r'; 711 } 712 output[op++] = '\n'; 713 } 714 715 assert tailLen == 0; 716 assert p == len; 717 } else { 718 // Save the leftovers in tail to be consumed on the next 719 // call to encodeInternal. 720 721 if (p == len - 1) { 722 tail[tailLen++] = input[p]; 723 } else if (p == len - 2) { 724 tail[tailLen++] = input[p]; 725 tail[tailLen++] = input[p + 1]; 726 } 727 } 728 729 this.op = op; 730 this.count = count; 731 732 return true; 733 } 734 } 735 Base64()736 private Base64() {} // don't instantiate 737 } 738