├── 20200212 ├── AndroidBase64.java ├── Cipher.java ├── ContextHolder.java ├── Mac.java ├── MessageDigest.java └── MyUtil.java ├── 8.1.0_r1.zip └── README.md /20200212/AndroidBase64.java: -------------------------------------------------------------------------------- 1 | package javax.crypto; 2 | 3 | /* 4 | * Copyright (C) 2010 The Android Open Source Project 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | import java.io.UnsupportedEncodingException; 19 | /** 20 | * Utilities for encoding and decoding the Base64 representation of 21 | * binary data. See RFCs 2045 and 3548. 24 | */ 25 | public class AndroidBase64 { 26 | /** 27 | * Default values for encoder/decoder flags. 28 | */ 29 | public static final int DEFAULT = 0; 30 | /** 31 | * Encoder flag bit to omit the padding '=' characters at the end 32 | * of the output (if any). 33 | */ 34 | public static final int NO_PADDING = 1; 35 | /** 36 | * Encoder flag bit to omit all line terminators (i.e., the output 37 | * will be on one long line). 38 | */ 39 | public static final int NO_WRAP = 2; 40 | /** 41 | * Encoder flag bit to indicate lines should be terminated with a 42 | * CRLF pair instead of just an LF. Has no effect if {@code 43 | * NO_WRAP} is specified as well. 44 | */ 45 | public static final int CRLF = 4; 46 | /** 47 | * Encoder/decoder flag bit to indicate using the "URL and 48 | * filename safe" variant of Base64 (see RFC 3548 section 4) where 49 | * {@code -} and {@code _} are used in place of {@code +} and 50 | * {@code /}. 51 | */ 52 | public static final int URL_SAFE = 8; 53 | public static final int NO_CLOSE = 16; 54 | // -------------------------------------------------------- 55 | // shared code 56 | // -------------------------------------------------------- 57 | /* package */ static abstract class Coder { 58 | public byte[] output; 59 | public int op; 60 | /** 61 | * Encode/decode another block of input data. this.output is 62 | * provided by the caller, and must be big enough to hold all 63 | * the coded data. On exit, this.opwill be set to the length 64 | * of the coded data. 65 | * 66 | * @param finish true if this is the final call to process for 67 | * this object. Will finalize the coder state and 68 | * include any final bytes in the output. 69 | * 70 | * @return true if the input so far is good; false if some 71 | * error has been detected in the input stream.. 72 | */ 73 | public abstract boolean process(byte[] input, int offset, int len, boolean finish); 74 | /** 75 | * @return the maximum number of bytes a call to process() 76 | * could produce for the given number of input bytes. This may 77 | * be an overestimate. 78 | */ 79 | public abstract int maxOutputSize(int len); 80 | } 81 | // -------------------------------------------------------- 82 | // decoding 83 | // -------------------------------------------------------- 84 | /** 85 | * Decode the Base64-encoded data in input and return the data in 86 | * a new byte array. 87 | * 88 | *
The padding '=' characters at the end are considered optional, but 89 | * if any are present, there must be the correct number of them. 90 | * 91 | * @param str the input String to decode, which is converted to 92 | * bytes using the default charset 93 | * @param flags controls certain features of the decoded output. 94 | * Pass {@code DEFAULT} to decode standard Base64. 95 | * 96 | * @throws IllegalArgumentException if the input contains 97 | * incorrect padding 98 | */ 99 | public static byte[] decode(String str, int flags) { 100 | return decode(str.getBytes(), flags); 101 | } 102 | /** 103 | * Decode the Base64-encoded data in input and return the data in 104 | * a new byte array. 105 | * 106 | *
The padding '=' characters at the end are considered optional, but 107 | * if any are present, there must be the correct number of them. 108 | * 109 | * @param input the input array to decode 110 | * @param flags controls certain features of the decoded output. 111 | * Pass {@code DEFAULT} to decode standard Base64. 112 | * 113 | * @throws IllegalArgumentException if the input contains 114 | * incorrect padding 115 | */ 116 | public static byte[] decode(byte[] input, int flags) { 117 | return decode(input, 0, input.length, flags); 118 | } 119 | /** 120 | * Decode the Base64-encoded data in input and return the data in 121 | * a new byte array. 122 | * 123 | *
The padding '=' characters at the end are considered optional, but 124 | * if any are present, there must be the correct number of them. 125 | * 126 | * @param input the data to decode 127 | * @param offset the position within the input array at which to start 128 | * @param len the number of bytes of input to decode 129 | * @param flags controls certain features of the decoded output. 130 | * Pass {@code DEFAULT} to decode standard Base64. 131 | * 132 | * @throws IllegalArgumentException if the input contains 133 | * incorrect padding 134 | */ 135 | public static byte[] decode(byte[] input, int offset, int len, int flags) { 136 | // Allocate space for the most data the input could represent. 137 | // (It could contain less if it contains whitespace, etc.) 138 | Decoder decoder = new Decoder(flags, new byte[len*3/4]); 139 | if (!decoder.process(input, offset, len, true)) { 140 | throw new IllegalArgumentException("bad base-64"); 141 | } 142 | // Maybe we got lucky and allocated exactly enough output space. 143 | if (decoder.op == decoder.output.length) { 144 | return decoder.output; 145 | } 146 | // Need to shorten the array, so allocate a new one of the 147 | // right size and copy. 148 | byte[] temp = new byte[decoder.op]; 149 | System.arraycopy(decoder.output, 0, temp, 0, decoder.op); 150 | return temp; 151 | } 152 | /* package */ static class Decoder extends Coder { 153 | /** 154 | * Lookup table for turning bytes into their position in the 155 | * Base64 alphabet. 156 | */ 157 | private static final int DECODE[] = { 158 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 159 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 160 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 161 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, 162 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 163 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, 164 | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 165 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, 166 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 167 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 168 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 169 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 170 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 171 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 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 | }; 175 | /** 176 | * Decode lookup table for the "web safe" variant (RFC 3548 177 | * sec. 4) where - and _ replace + and /. 178 | */ 179 | private static final int DECODE_WEBSAFE[] = { 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, 62, -1, -1, 183 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, 184 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 185 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, 186 | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 187 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, 188 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 189 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 190 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 191 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 192 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 193 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 194 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 195 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 196 | }; 197 | /** Non-data values in the DECODE arrays. */ 198 | private static final int SKIP = -1; 199 | private static final int EQUALS = -2; 200 | /** 201 | * States 0-3 are reading through the next input tuple. 202 | * State 4 is having read one '=' and expecting exactly 203 | * one more. 204 | * State 5 is expecting no more data or padding characters 205 | * in the input. 206 | * State 6 is the error state; an error has been detected 207 | * in the input and no future input can "fix" it. 208 | */ 209 | private int state; // state number (0 to 6) 210 | private int value; 211 | final private int[] alphabet; 212 | public Decoder(int flags, byte[] output) { 213 | this.output = output; 214 | alphabet = ((flags & URL_SAFE) == 0) ? DECODE : DECODE_WEBSAFE; 215 | state = 0; 216 | value = 0; 217 | } 218 | /** 219 | * @return an overestimate for the number of bytes {@code 220 | * len} bytes could decode to. 221 | */ 222 | public int maxOutputSize(int len) { 223 | return len * 3/4 + 10; 224 | } 225 | /** 226 | * Decode another block of input data. 227 | * 228 | * @return true if the state machine is still healthy. false if 229 | * bad base-64 data has been detected in the input stream. 230 | */ 231 | public boolean process(byte[] input, int offset, int len, boolean finish) { 232 | if (this.state == 6) return false; 233 | int p = offset; 234 | len += offset; 235 | // Using local variables makes the decoder about 12% 236 | // faster than if we manipulate the member variables in 237 | // the loop. (Even alphabet makes a measurable 238 | // difference, which is somewhat surprising to me since 239 | // the member variable is final.) 240 | int state = this.state; 241 | int value = this.value; 242 | int op = 0; 243 | final byte[] output = this.output; 244 | final int[] alphabet = this.alphabet; 245 | while (p < len) { 246 | // Try the fast path: we're starting a new tuple and the 247 | // next four bytes of the input stream are all data 248 | // bytes. This corresponds to going through states 249 | // 0-1-2-3-0. We expect to use this method for most of 250 | // the data. 251 | // 252 | // If any of the next four bytes of input are non-data 253 | // (whitespace, etc.), value will end up negative. (All 254 | // the non-data values in decode are small negative 255 | // numbers, so shifting any of them up and or'ing them 256 | // together will result in a value with its top bit set.) 257 | // 258 | // You can remove this whole block and the output should 259 | // be the same, just slower. 260 | if (state == 0) { 261 | while (p+4 <= len && 262 | (value = ((alphabet[input[p] & 0xff] << 18) | 263 | (alphabet[input[p+1] & 0xff] << 12) | 264 | (alphabet[input[p+2] & 0xff] << 6) | 265 | (alphabet[input[p+3] & 0xff]))) >= 0) { 266 | output[op+2] = (byte) value; 267 | output[op+1] = (byte) (value >> 8); 268 | output[op] = (byte) (value >> 16); 269 | op += 3; 270 | p += 4; 271 | } 272 | if (p >= len) break; 273 | } 274 | // The fast path isn't available -- either we've read a 275 | // partial tuple, or the next four input bytes aren't all 276 | // data, or whatever. Fall back to the slower state 277 | // machine implementation. 278 | int d = alphabet[input[p++] & 0xff]; 279 | switch (state) { 280 | case 0: 281 | if (d >= 0) { 282 | value = d; 283 | ++state; 284 | } else if (d != SKIP) { 285 | this.state = 6; 286 | return false; 287 | } 288 | break; 289 | case 1: 290 | if (d >= 0) { 291 | value = (value << 6) | d; 292 | ++state; 293 | } else if (d != SKIP) { 294 | this.state = 6; 295 | return false; 296 | } 297 | break; 298 | case 2: 299 | if (d >= 0) { 300 | value = (value << 6) | d; 301 | ++state; 302 | } else if (d == EQUALS) { 303 | // Emit the last (partial) output tuple; 304 | // expect exactly one more padding character. 305 | output[op++] = (byte) (value >> 4); 306 | state = 4; 307 | } else if (d != SKIP) { 308 | this.state = 6; 309 | return false; 310 | } 311 | break; 312 | case 3: 313 | if (d >= 0) { 314 | // Emit the output triple and return to state 0. 315 | value = (value << 6) | d; 316 | output[op+2] = (byte) value; 317 | output[op+1] = (byte) (value >> 8); 318 | output[op] = (byte) (value >> 16); 319 | op += 3; 320 | state = 0; 321 | } else if (d == EQUALS) { 322 | // Emit the last (partial) output tuple; 323 | // expect no further data or padding characters. 324 | output[op+1] = (byte) (value >> 2); 325 | output[op] = (byte) (value >> 10); 326 | op += 2; 327 | state = 5; 328 | } else if (d != SKIP) { 329 | this.state = 6; 330 | return false; 331 | } 332 | break; 333 | case 4: 334 | if (d == EQUALS) { 335 | ++state; 336 | } else if (d != SKIP) { 337 | this.state = 6; 338 | return false; 339 | } 340 | break; 341 | case 5: 342 | if (d != SKIP) { 343 | this.state = 6; 344 | return false; 345 | } 346 | break; 347 | } 348 | } 349 | if (!finish) { 350 | // We're out of input, but a future call could provide 351 | // more. 352 | this.state = state; 353 | this.value = value; 354 | this.op = op; 355 | return true; 356 | } 357 | // Done reading input. Now figure out where we are left in 358 | // the state machine and finish up. 359 | switch (state) { 360 | case 0: 361 | // Output length is a multiple of three. Fine. 362 | break; 363 | case 1: 364 | // Read one extra input byte, which isn't enough to 365 | // make another output byte. Illegal. 366 | this.state = 6; 367 | return false; 368 | case 2: 369 | // Read two extra input bytes, enough to emit 1 more 370 | // output byte. Fine. 371 | output[op++] = (byte) (value >> 4); 372 | break; 373 | case 3: 374 | // Read three extra input bytes, enough to emit 2 more 375 | // output bytes. Fine. 376 | output[op++] = (byte) (value >> 10); 377 | output[op++] = (byte) (value >> 2); 378 | break; 379 | case 4: 380 | // Read one padding '=' when we expected 2. Illegal. 381 | this.state = 6; 382 | return false; 383 | case 5: 384 | // Read all the padding '='s we expected and no more. 385 | // Fine. 386 | break; 387 | } 388 | this.state = state; 389 | this.op = op; 390 | return true; 391 | } 392 | } 393 | // -------------------------------------------------------- 394 | // encoding 395 | // -------------------------------------------------------- 396 | /** 397 | * Base64-encode the given data and return a newly allocated 398 | * String with the result. 399 | * 400 | * @param input the data to encode 401 | * @param flags controls certain features of the encoded output. 402 | * Passing {@code DEFAULT} results in output that 403 | * adheres to RFC 2045. 404 | */ 405 | public static String encodeToString(byte[] input, int flags) { 406 | try { 407 | return new String(encode(input, flags), "US-ASCII"); 408 | } catch (UnsupportedEncodingException e) { 409 | // US-ASCII is guaranteed to be available. 410 | throw new AssertionError(e); 411 | } 412 | } 413 | /** 414 | * Base64-encode the given data and return a newly allocated 415 | * String with the result. 416 | * 417 | * @param input the data to encode 418 | * @param offset the position within the input array at which to 419 | * start 420 | * @param len the number of bytes of input to encode 421 | * @param flags controls certain features of the encoded output. 422 | * Passing {@code DEFAULT} results in output that 423 | * adheres to RFC 2045. 424 | */ 425 | public static String encodeToString(byte[] input, int offset, int len, int flags) { 426 | try { 427 | return new String(encode(input, offset, len, flags), "US-ASCII"); 428 | } catch (UnsupportedEncodingException e) { 429 | // US-ASCII is guaranteed to be available. 430 | throw new AssertionError(e); 431 | } 432 | } 433 | /** 434 | * Base64-encode the given data and return a newly allocated 435 | * byte[] with the result. 436 | * 437 | * @param input the data to encode 438 | * @param flags controls certain features of the encoded output. 439 | * Passing {@code DEFAULT} results in output that 440 | * adheres to RFC 2045. 441 | */ 442 | public static byte[] encode(byte[] input, int flags) { 443 | return encode(input, 0, input.length, flags); 444 | } 445 | /** 446 | * Base64-encode the given data and return a newly allocated 447 | * byte[] with the result. 448 | * 449 | * @param input the data to encode 450 | * @param offset the position within the input array at which to 451 | * start 452 | * @param len the number of bytes of input to encode 453 | * @param flags controls certain features of the encoded output. 454 | * Passing {@code DEFAULT} results in output that 455 | * adheres to RFC 2045. 456 | */ 457 | public static byte[] encode(byte[] input, int offset, int len, int flags) { 458 | Encoder encoder = new Encoder(flags, null); 459 | // Compute the exact length of the array we will produce. 460 | int output_len = len / 3 * 4; 461 | // Account for the tail of the data and the padding bytes, if any. 462 | if (encoder.do_padding) { 463 | if (len % 3 > 0) { 464 | output_len += 4; 465 | } 466 | } else { 467 | switch (len % 3) { 468 | case 0: break; 469 | case 1: output_len += 2; break; 470 | case 2: output_len += 3; break; 471 | } 472 | } 473 | // Account for the newlines, if any. 474 | if (encoder.do_newline && len > 0) { 475 | output_len += (((len-1) / (3 * Encoder.LINE_GROUPS)) + 1) * 476 | (encoder.do_cr ? 2 : 1); 477 | } 478 | encoder.output = new byte[output_len]; 479 | encoder.process(input, offset, len, true); 480 | assert encoder.op == output_len; 481 | return encoder.output; 482 | } 483 | /* package */ static class Encoder extends Coder { 484 | /** 485 | * Emit a new line every this many output tuples. Corresponds to 486 | * a 76-character line length (the maximum allowable according to 487 | * RFC 2045). 488 | */ 489 | public static final int LINE_GROUPS = 19; 490 | /** 491 | * Lookup table for turning Base64 alphabet positions (6 bits) 492 | * into output bytes. 493 | */ 494 | private static final byte ENCODE[] = { 495 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 496 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 497 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 498 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', 499 | }; 500 | /** 501 | * Lookup table for turning Base64 alphabet positions (6 bits) 502 | * into output bytes. 503 | */ 504 | private static final byte ENCODE_WEBSAFE[] = { 505 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 506 | 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 507 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 508 | 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_', 509 | }; 510 | final private byte[] tail; 511 | /* package */ int tailLen; 512 | private int count; 513 | final public boolean do_padding; 514 | final public boolean do_newline; 515 | final public boolean do_cr; 516 | final private byte[] alphabet; 517 | public Encoder(int flags, byte[] output) { 518 | this.output = output; 519 | do_padding = (flags & NO_PADDING) == 0; 520 | do_newline = (flags & NO_WRAP) == 0; 521 | do_cr = (flags & CRLF) != 0; 522 | alphabet = ((flags & URL_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE; 523 | tail = new byte[2]; 524 | tailLen = 0; 525 | count = do_newline ? LINE_GROUPS : -1; 526 | } 527 | /** 528 | * @return an overestimate for the number of bytes {@code 529 | * len} bytes could encode to. 530 | */ 531 | public int maxOutputSize(int len) { 532 | return len * 8/5 + 10; 533 | } 534 | public boolean process(byte[] input, int offset, int len, boolean finish) { 535 | // Using local variables makes the encoder about 9% faster. 536 | final byte[] alphabet = this.alphabet; 537 | final byte[] output = this.output; 538 | int op = 0; 539 | int count = this.count; 540 | int p = offset; 541 | len += offset; 542 | int v = -1; 543 | // First we need to concatenate the tail of the previous call 544 | // with any input bytes available now and see if we can empty 545 | // the tail. 546 | switch (tailLen) { 547 | case 0: 548 | // There was no tail. 549 | break; 550 | case 1: 551 | if (p+2 <= len) { 552 | // A 1-byte tail with at least 2 bytes of 553 | // input available now. 554 | v = ((tail[0] & 0xff) << 16) | 555 | ((input[p++] & 0xff) << 8) | 556 | (input[p++] & 0xff); 557 | tailLen = 0; 558 | }; 559 | break; 560 | case 2: 561 | if (p+1 <= len) { 562 | // A 2-byte tail with at least 1 byte of input. 563 | v = ((tail[0] & 0xff) << 16) | 564 | ((tail[1] & 0xff) << 8) | 565 | (input[p++] & 0xff); 566 | tailLen = 0; 567 | } 568 | break; 569 | } 570 | if (v != -1) { 571 | output[op++] = alphabet[(v >> 18) & 0x3f]; 572 | output[op++] = alphabet[(v >> 12) & 0x3f]; 573 | output[op++] = alphabet[(v >> 6) & 0x3f]; 574 | output[op++] = alphabet[v & 0x3f]; 575 | if (--count == 0) { 576 | if (do_cr) output[op++] = '\r'; 577 | output[op++] = '\n'; 578 | count = LINE_GROUPS; 579 | } 580 | } 581 | // At this point either there is no tail, or there are fewer 582 | // than 3 bytes of input available. 583 | // The main loop, turning 3 input bytes into 4 output bytes on 584 | // each iteration. 585 | while (p+3 <= len) { 586 | v = ((input[p] & 0xff) << 16) | 587 | ((input[p+1] & 0xff) << 8) | 588 | (input[p+2] & 0xff); 589 | output[op] = alphabet[(v >> 18) & 0x3f]; 590 | output[op+1] = alphabet[(v >> 12) & 0x3f]; 591 | output[op+2] = alphabet[(v >> 6) & 0x3f]; 592 | output[op+3] = alphabet[v & 0x3f]; 593 | p += 3; 594 | op += 4; 595 | if (--count == 0) { 596 | if (do_cr) output[op++] = '\r'; 597 | output[op++] = '\n'; 598 | count = LINE_GROUPS; 599 | } 600 | } 601 | if (finish) { 602 | // Finish up the tail of the input. Note that we need to 603 | // consume any bytes in tail before any bytes 604 | // remaining in input; there should be at most two bytes 605 | // total. 606 | if (p-tailLen == len-1) { 607 | int t = 0; 608 | v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4; 609 | tailLen -= t; 610 | output[op++] = alphabet[(v >> 6) & 0x3f]; 611 | output[op++] = alphabet[v & 0x3f]; 612 | if (do_padding) { 613 | output[op++] = '='; 614 | output[op++] = '='; 615 | } 616 | if (do_newline) { 617 | if (do_cr) output[op++] = '\r'; 618 | output[op++] = '\n'; 619 | } 620 | } else if (p-tailLen == len-2) { 621 | int t = 0; 622 | v = (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10) | 623 | (((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2); 624 | tailLen -= t; 625 | output[op++] = alphabet[(v >> 12) & 0x3f]; 626 | output[op++] = alphabet[(v >> 6) & 0x3f]; 627 | output[op++] = alphabet[v & 0x3f]; 628 | if (do_padding) { 629 | output[op++] = '='; 630 | } 631 | if (do_newline) { 632 | if (do_cr) output[op++] = '\r'; 633 | output[op++] = '\n'; 634 | } 635 | } else if (do_newline && op > 0 && count != LINE_GROUPS) { 636 | if (do_cr) output[op++] = '\r'; 637 | output[op++] = '\n'; 638 | } 639 | assert tailLen == 0; 640 | assert p == len; 641 | } else { 642 | // Save the leftovers in tail to be consumed on the next 643 | // call to encodeInternal. 644 | if (p == len-1) { 645 | tail[tailLen++] = input[p]; 646 | } else if (p == len-2) { 647 | tail[tailLen++] = input[p]; 648 | tail[tailLen++] = input[p+1]; 649 | } 650 | } 651 | this.op = op; 652 | this.count = count; 653 | return true; 654 | } 655 | } 656 | } -------------------------------------------------------------------------------- /20200212/Cipher.java: -------------------------------------------------------------------------------- 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 | * http://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 javax.crypto; 19 | 20 | import java.nio.ByteBuffer; 21 | import java.security.AlgorithmParameters; 22 | import java.security.InvalidAlgorithmParameterException; 23 | import java.security.InvalidKeyException; 24 | import java.security.InvalidParameterException; 25 | import java.security.Key; 26 | import java.security.NoSuchAlgorithmException; 27 | import java.security.NoSuchProviderException; 28 | import java.security.PrivateKey; 29 | import java.security.Provider; 30 | import java.security.Provider.Service; 31 | import java.security.ProviderException; 32 | import java.security.PublicKey; 33 | import java.security.SecureRandom; 34 | import java.security.Security; 35 | import java.security.cert.Certificate; 36 | import java.security.cert.X509Certificate; 37 | import java.security.spec.AlgorithmParameterSpec; 38 | import java.security.spec.DSAParameterSpec; 39 | import java.security.spec.ECGenParameterSpec; 40 | import java.security.spec.ECParameterSpec; 41 | import java.security.spec.MGF1ParameterSpec; 42 | import java.security.spec.PSSParameterSpec; 43 | import java.security.spec.RSAKeyGenParameterSpec; 44 | import java.util.ArrayList; 45 | import java.util.Locale; 46 | import java.util.Set; 47 | import org.apache.harmony.crypto.internal.NullCipherSpi; 48 | import org.apache.harmony.security.fortress.Engine; 49 | import org.json.JSONObject; 50 | 51 | import javax.crypto.interfaces.PBEKey; 52 | import javax.crypto.spec.IvParameterSpec; 53 | import javax.crypto.spec.PBEParameterSpec; 54 | 55 | /** 56 | * This class provides access to implementations of cryptographic ciphers for 57 | * encryption and decryption. Cipher classes can not be instantiated directly, 58 | * one has to call the Cipher's {@code getInstance} method with the name of a 59 | * requested transformation, optionally with a provider. A transformation 60 | * specifies an operation (or a set of operations) as a string in the form: 61 | *
70 | * A valid transformation would be: 71 | *
"[cipher]"
572 | * "[cipher]/[mode]/[padding]"
573 | * "[cipher]//[padding]"
574 | * "[cipher]/[mode]"
575 | * 577 | * Returns the specified transformation split up into three parts 578 | * corresponding to their function: 579 | *
580 | *
581 | * {<algorithm>, <mode>, <padding>}
582 | *
583 | *
584 | */ 585 | private static String[] checkTransformation(String transformation) 586 | throws NoSuchAlgorithmException { 587 | // ignore an extra prefix / characters such as in 588 | // "/DES/CBC/PKCS5Padding" http://b/3387688 589 | if (transformation.startsWith("/")) { 590 | transformation = transformation.substring(1); 591 | } 592 | // 'transformation' should be of the form "algorithm/mode/padding". 593 | String[] pieces = transformation.split("/"); 594 | if (pieces.length > 3) { 595 | throw invalidTransformation(transformation); 596 | } 597 | // Empty or missing pieces are represented by null. 598 | String[] result = new String[3]; 599 | for (int i = 0; i < pieces.length; ++i) { 600 | String piece = pieces[i].trim(); 601 | if (!piece.isEmpty()) { 602 | result[i] = piece; 603 | } 604 | } 605 | // You MUST specify an algorithm. 606 | if (result[0] == null) { 607 | throw invalidTransformation(transformation); 608 | } 609 | if (!(result[1] == null && result[2] == null) && (result[1] == null || result[2] == null)) { 610 | throw invalidTransformation(transformation); 611 | } 612 | return result; 613 | } 614 | 615 | /** 616 | * Makes sure a CipherSpi that matches this type is selected. If 617 | * {@code key != null} then it assumes that a suitable provider exists for 618 | * this instance (used by {@link #init}. If the {@code initParams} is passed 619 | * in, then the {@code CipherSpi} returned will be initialized. 620 | * 621 | * @throws InvalidKeyException if the specified key cannot be used to 622 | * initialize this cipher. 623 | * @throws InvalidAlgorithmParameterException 624 | */ 625 | private CipherSpi getSpi(InitParams initParams) throws InvalidKeyException, 626 | InvalidAlgorithmParameterException { 627 | if (specifiedSpi != null) { 628 | return specifiedSpi; 629 | } 630 | 631 | synchronized (initLock) { 632 | // This is not only a matter of performance. Many methods like update, doFinal, etc. 633 | // call {@code #getSpi()} (ie, {@code #getSpi(null /* params */)}) and without this 634 | // shortcut they would override an spi that was chosen using the key. 635 | if (spiImpl != null && initParams == null) { 636 | return spiImpl; 637 | } 638 | 639 | final Engine.SpiAndProvider sap = tryCombinations(initParams, specifiedProvider, 640 | transformation, transformParts); 641 | if (sap == null) { 642 | throw new ProviderException("No provider found for " + transformation); 643 | } 644 | 645 | spiImpl = (CipherSpi) sap.spi; 646 | provider = sap.provider; 647 | 648 | return spiImpl; 649 | } 650 | } 651 | 652 | /** 653 | * Convenience call when the Key is not available. 654 | */ 655 | private CipherSpi getSpi() { 656 | try { 657 | return getSpi(null); 658 | } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { 659 | throw new ProviderException("Exception thrown when params == null", e); 660 | } 661 | } 662 | 663 | /** 664 | * Returns the {@code CipherSpi} backing this {@code Cipher} or {@code null} if no 665 | * {@code CipherSpi} is backing this {@code Cipher}. 666 | * 667 | * @hide 668 | */ 669 | public CipherSpi getCurrentSpi() { 670 | if (specifiedSpi != null) { 671 | return specifiedSpi; 672 | } 673 | 674 | synchronized (initLock) { 675 | return spiImpl; 676 | } 677 | } 678 | 679 | /** 680 | * Tries to find the correct {@code Cipher} transform to use. Returns a 681 | * {@link Engine.SpiAndProvider}, throws the first exception that was 682 | * encountered during attempted initialization, or {@code null} if there are 683 | * no providers that support the {@code initParams}. 684 | *
685 | * {@code transformParts} must be in the format returned by 686 | * {@link #checkTransformation(String)}. The combinations of mode strings 687 | * tried are as follows: 688 | *
[cipher]/[mode]/[padding]
690 | * [cipher]/[mode]
691 | * [cipher]//[padding]
692 | * [cipher]
693 | * 856 | * This is the name of the transformation argument used in the 857 | * {@code getInstance} call creating this object. 858 | * 859 | * @return the name of the algorithm of this cipher instance. 860 | */ 861 | public final String getAlgorithm() { 862 | return transformation; 863 | } 864 | 865 | /** 866 | * Returns this ciphers block size (in bytes). 867 | * 868 | * @return this ciphers block size. 869 | */ 870 | public final int getBlockSize() { 871 | return getSpi().engineGetBlockSize(); 872 | } 873 | 874 | /** 875 | * Returns the length in bytes an output buffer needs to be when this cipher 876 | * is updated with {@code inputLen} bytes. 877 | * 878 | * @param inputLen 879 | * the number of bytes of the input. 880 | * @return the output buffer length for the input length. 881 | * @throws IllegalStateException 882 | * if this cipher instance is in an invalid state. 883 | */ 884 | public final int getOutputSize(int inputLen) { 885 | if (mode == 0) { 886 | throw new IllegalStateException("Cipher has not yet been initialized"); 887 | } 888 | return getSpi().engineGetOutputSize(inputLen); 889 | } 890 | 891 | /** 892 | * Returns the initialization vector for this cipher instance. 893 | * 894 | * @return the initialization vector for this cipher instance. 895 | */ 896 | public final byte[] getIV() { 897 | return getSpi().engineGetIV(); 898 | } 899 | 900 | /** 901 | * Returns the parameters that where used to create this cipher instance. 902 | *
903 | * These may be a the same parameters that were used to create this cipher 904 | * instance, or may be a combination of default and random parameters, 905 | * depending on the underlying cipher implementation. 906 | * 907 | * @return the parameters that where used to create this cipher instance, or 908 | * {@code null} if this cipher instance does not have any 909 | * parameters. 910 | */ 911 | public final AlgorithmParameters getParameters() { 912 | return getSpi().engineGetParameters(); 913 | } 914 | 915 | /** 916 | * Returns the exemption mechanism associated with this cipher. 917 | * 918 | * @return currently {@code null} 919 | */ 920 | public final ExemptionMechanism getExemptionMechanism() { 921 | //FIXME implement getExemptionMechanism 922 | 923 | // try { 924 | // return ExemptionMechanism.getInstance(transformation, provider); 925 | // } catch (NoSuchAlgorithmException e) { 926 | return null; 927 | // } 928 | 929 | } 930 | 931 | /** 932 | * Checks that the provided {@code mode} is one that is valid for 933 | * {@code Cipher}. 934 | */ 935 | private void checkMode(int mode) { 936 | if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE && mode != UNWRAP_MODE 937 | && mode != WRAP_MODE) { 938 | throw new InvalidParameterException("Invalid mode: " + mode); 939 | } 940 | } 941 | 942 | /** 943 | * Initializes this cipher instance with the specified key. 944 | *
945 | * The cipher is initialized for the specified operational mode (one of: 946 | * encryption, decryption, key wrapping or key unwrapping) depending on 947 | * {@code opmode}. 948 | *
949 | * If this cipher instance needs any algorithm parameters or random values 950 | * that the specified key can not provide, the underlying implementation of 951 | * this cipher is supposed to generate the required parameters (using its 952 | * provider or random values). 953 | *
954 | * When a cipher instance is initialized by a call to any of the {@code 955 | * init} methods, the state of the instance is overridden, meaning that it 956 | * is equivalent to creating a new instance and calling its {@code init} 957 | * method. 958 | * 959 | * @param opmode 960 | * the operation this cipher instance should be initialized for 961 | * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 962 | * WRAP_MODE} or {@code UNWRAP_MODE}). 963 | * @param key 964 | * the input key for the operation. 965 | * @throws InvalidKeyException 966 | * if the specified key can not be used to initialize this 967 | * cipher instance. 968 | */ 969 | public final void init(int opmode, Key key) throws InvalidKeyException { 970 | if (secureRandom == null) { 971 | // In theory it might be thread-unsafe but in the given case it's OK 972 | // since it does not matter which SecureRandom instance is passed 973 | // to the init() 974 | secureRandom = new SecureRandom(); 975 | } 976 | init(opmode, key, secureRandom); 977 | } 978 | 979 | /** 980 | * Initializes this cipher instance with the specified key and a source of 981 | * randomness. 982 | *
983 | * The cipher is initialized for the specified operational mode (one of: 984 | * encryption, decryption, key wrapping or key unwrapping) depending on 985 | * {@code opmode}. 986 | *
987 | * If this cipher instance needs any algorithm parameters or random values 988 | * that the specified key can not provide, the underlying implementation of 989 | * this cipher is supposed to generate the required parameters (using its 990 | * provider or random values). Random values are generated using {@code 991 | * random}; 992 | *
993 | * When a cipher instance is initialized by a call to any of the {@code 994 | * init} methods, the state of the instance is overridden, means it is 995 | * equivalent to creating a new instance and calling it {@code init} method. 996 | * 997 | * @param opmode 998 | * the operation this cipher instance should be initialized for 999 | * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 1000 | * WRAP_MODE} or {@code UNWRAP_MODE}). 1001 | * @param key 1002 | * the input key for the operation. 1003 | * @param random 1004 | * the source of randomness to use. 1005 | * @throws InvalidKeyException 1006 | * if the specified key can not be used to initialize this 1007 | * cipher instance. 1008 | * @throws InvalidParameterException 1009 | * if the specified opmode is invalid. 1010 | */ 1011 | public final void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException { 1012 | checkMode(opmode); 1013 | // FIXME InvalidKeyException 1014 | // if keysize exceeds the maximum allowable keysize 1015 | // (jurisdiction policy files) 1016 | try { 1017 | getSpi(new InitParams(InitType.KEY, opmode, key, random, null, null)); 1018 | } catch (InvalidAlgorithmParameterException e) { 1019 | // Should never happen since we only specified the key. 1020 | throw new ProviderException("Invalid parameters when params == null", e); 1021 | } 1022 | mode = opmode; 1023 | 1024 | //add by icew4y 2019 12 13 1025 | 1026 | passThrough_InitParams(InitType.KEY, opmode, key, random, null, null); 1027 | //System.out.println("MyTag: InitParams -> " + sb.toString()); 1028 | //add by icew4y 2019 12 13 1029 | } 1030 | 1031 | /** 1032 | * Initializes this cipher instance with the specified key and algorithm 1033 | * parameters. 1034 | *
1035 | * The cipher is initialized for the specified operational mode (one of: 1036 | * encryption, decryption, key wrapping or key unwrapping). 1037 | *
1038 | * If this cipher instance needs any algorithm parameters and {@code params} 1039 | * is {@code null}, the underlying implementation of this cipher is supposed 1040 | * to generate the required parameters (using its provider or random 1041 | * values). 1042 | *
1043 | * When a cipher instance is initialized by a call to any of the {@code 1044 | * init} methods, the state of the instance is overridden, means it is 1045 | * equivalent to creating a new instance and calling it {@code init} method. 1046 | * 1047 | * @param opmode 1048 | * the operation this cipher instance should be initialized for 1049 | * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 1050 | * WRAP_MODE} or {@code UNWRAP_MODE}). 1051 | * @param key 1052 | * the input key for the operation. 1053 | * @param params 1054 | * the algorithm parameters. 1055 | * @throws InvalidKeyException 1056 | * if the specified key can not be used to initialize this 1057 | * cipher instance. 1058 | * @throws InvalidAlgorithmParameterException 1059 | * it the specified parameters are inappropriate for this 1060 | * cipher. 1061 | */ 1062 | public final void init(int opmode, Key key, AlgorithmParameterSpec params) 1063 | throws InvalidKeyException, InvalidAlgorithmParameterException { 1064 | if (secureRandom == null) { 1065 | secureRandom = new SecureRandom(); 1066 | } 1067 | init(opmode, key, params, secureRandom); 1068 | } 1069 | 1070 | /** 1071 | * Initializes this cipher instance with the specified key, algorithm 1072 | * parameters and a source of randomness. 1073 | *
1074 | * The cipher is initialized for the specified operational mode (one of: 1075 | * encryption, decryption, key wrapping or key unwrapping) depending on 1076 | * {@code opmode}. 1077 | *
1078 | * If this cipher instance needs any algorithm parameters and {@code params} 1079 | * is {@code null}, the underlying implementation of this cipher is supposed 1080 | * to generate the required parameters (using its provider or random 1081 | * values). Random values are generated using {@code random}; 1082 | *
1083 | * When a cipher instance is initialized by a call to any of the {@code 1084 | * init} methods, the state of the instance is overridden, meaning that it 1085 | * is equivalent to creating a new instance and calling it {@code init} 1086 | * method. 1087 | * 1088 | * @param opmode 1089 | * the operation this cipher instance should be initialized for 1090 | * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 1091 | * WRAP_MODE} or {@code UNWRAP_MODE}). 1092 | * @param key 1093 | * the input key for the operation. 1094 | * @param params 1095 | * the algorithm parameters. 1096 | * @param random 1097 | * the source of randomness to use. 1098 | * @throws InvalidKeyException 1099 | * if the specified key can not be used to initialize this 1100 | * cipher instance. 1101 | * @throws InvalidAlgorithmParameterException 1102 | * it the specified parameters are inappropriate for this 1103 | * cipher. 1104 | * @throws InvalidParameterException 1105 | * if the specified {@code opmode} is invalid. 1106 | */ 1107 | public final void init(int opmode, Key key, AlgorithmParameterSpec params, 1108 | SecureRandom random) throws InvalidKeyException, 1109 | InvalidAlgorithmParameterException { 1110 | checkMode(opmode); 1111 | // FIXME InvalidKeyException 1112 | // if keysize exceeds the maximum allowable keysize 1113 | // (jurisdiction policy files) 1114 | // FIXME InvalidAlgorithmParameterException 1115 | // cryptographic strength exceed the legal limits 1116 | // (jurisdiction policy files) 1117 | getSpi(new InitParams(InitType.ALGORITHM_PARAM_SPEC, opmode, key, random, params, null)); 1118 | mode = opmode; 1119 | 1120 | // add by icew4y 2019 12 13 1121 | passThrough_InitParams(InitType.ALGORITHM_PARAM_SPEC, opmode, key, random, params, null); 1122 | // add by icew4y 2019 12 13 1123 | } 1124 | 1125 | /** 1126 | * Initializes this cipher instance with the specified key and algorithm 1127 | * parameters. 1128 | *
1129 | * The cipher is initialized for the specified operation (one of: 1130 | * encryption, decryption, key wrapping or key unwrapping) depending on 1131 | * {@code opmode}. 1132 | *
1133 | * If this cipher instance needs any algorithm parameters and {@code params} 1134 | * is {@code null}, the underlying implementation of this cipher is supposed 1135 | * to generate the required parameters (using its provider or random 1136 | * values). 1137 | *
1138 | * When a cipher instance is initialized by a call to any of the {@code 1139 | * init} methods, the state of the instance is overridden, meaning that it 1140 | * is equivalent to creating a new instance and calling it {@code init} 1141 | * method. 1142 | * 1143 | * @param opmode 1144 | * the operation this cipher instance should be initialized for 1145 | * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 1146 | * WRAP_MODE} or {@code UNWRAP_MODE}). 1147 | * @param key 1148 | * the input key for the operation. 1149 | * @param params 1150 | * the algorithm parameters. 1151 | * @throws InvalidKeyException 1152 | * if the specified key can not be used to initialize this 1153 | * cipher instance. 1154 | * @throws InvalidAlgorithmParameterException 1155 | * it the specified parameters are inappropriate for this 1156 | * cipher. 1157 | */ 1158 | public final void init(int opmode, Key key, AlgorithmParameters params) 1159 | throws InvalidKeyException, InvalidAlgorithmParameterException { 1160 | if (secureRandom == null) { 1161 | secureRandom = new SecureRandom(); 1162 | } 1163 | init(opmode, key, params, secureRandom); 1164 | } 1165 | 1166 | /** 1167 | * Initializes this cipher instance with the specified key, algorithm 1168 | * parameters and a source of randomness. 1169 | *
1170 | * The cipher will be initialized for the specified operation (one of: 1171 | * encryption, decryption, key wrapping or key unwrapping) depending on 1172 | * {@code opmode}. 1173 | *
1174 | * If this cipher instance needs any algorithm parameters and {@code params} 1175 | * is {@code null}, the underlying implementation of this cipher is supposed 1176 | * to generate the required parameters (using its provider or random 1177 | * values). Random values are generated using {@code random}. 1178 | *
1179 | * When a cipher instance is initialized by a call to any of the {@code 1180 | * init} methods, the state of the instance is overridden, means it is 1181 | * equivalent to creating a new instance and calling it {@code init} method. 1182 | * 1183 | * @param opmode 1184 | * the operation this cipher instance should be initialized for 1185 | * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 1186 | * WRAP_MODE} or {@code UNWRAP_MODE}). 1187 | * @param key 1188 | * the input key for the operation. 1189 | * @param params 1190 | * the algorithm parameters. 1191 | * @param random 1192 | * the source of randomness to use. 1193 | * @throws InvalidKeyException 1194 | * if the specified key can not be used to initialize this 1195 | * cipher instance. 1196 | * @throws InvalidAlgorithmParameterException 1197 | * if the specified parameters are inappropriate for this 1198 | * cipher. 1199 | * @throws InvalidParameterException 1200 | * if the specified {@code opmode} is invalid. 1201 | */ 1202 | public final void init(int opmode, Key key, AlgorithmParameters params, 1203 | SecureRandom random) throws InvalidKeyException, 1204 | InvalidAlgorithmParameterException { 1205 | checkMode(opmode); 1206 | // FIXME InvalidKeyException 1207 | // if keysize exceeds the maximum allowable keysize 1208 | // (jurisdiction policy files) 1209 | // FIXME InvalidAlgorithmParameterException 1210 | // cryptographic strength exceed the legal limits 1211 | // (jurisdiction policy files) 1212 | getSpi(new InitParams(InitType.ALGORITHM_PARAMS, opmode, key, random, null, params)); 1213 | mode = opmode; 1214 | 1215 | // add by icew4y 2019 12 13 1216 | passThrough_InitParams(InitType.ALGORITHM_PARAMS, opmode, key, random, null, params); 1217 | // add by icew4y 2019 12 13 1218 | } 1219 | 1220 | /** 1221 | * Initializes this cipher instance with the public key from the specified 1222 | * certificate. 1223 | *
1224 | * The cipher will be initialized for the specified operation (one of: 1225 | * encryption, decryption, key wrapping or key unwrapping) depending on 1226 | * {@code opmode}. 1227 | *
1228 | * It the type of the certificate is X.509 and the certificate has a key 1229 | * usage extension field marked as critical, the specified {@code 1230 | * opmode} has the be enabled for this key, otherwise an {@code 1231 | * InvalidKeyException} is thrown. 1232 | *
1233 | * If this cipher instance needs any algorithm parameters that the key in 1234 | * the certificate can not provide, the underlying implementation of this 1235 | * cipher is supposed to generate the required parameters (using its 1236 | * provider or random values). 1237 | *
1238 | * When a cipher instance is initialized by a call to any of the {@code 1239 | * init} methods, the state of the instance is overridden, means it is 1240 | * equivalent to creating a new instance and calling it {@code init} method. 1241 | * 1242 | * @param opmode 1243 | * the operation this cipher instance should be initialized for 1244 | * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 1245 | * WRAP_MODE} or {@code UNWRAP_MODE}). 1246 | * @param certificate 1247 | * the certificate. 1248 | * @throws InvalidKeyException 1249 | * if the public key in the certificate can not be used to 1250 | * initialize this cipher instance. 1251 | */ 1252 | public final void init(int opmode, Certificate certificate) 1253 | throws InvalidKeyException { 1254 | if (secureRandom == null) { 1255 | secureRandom = new SecureRandom(); 1256 | } 1257 | init(opmode, certificate, secureRandom); 1258 | } 1259 | 1260 | /** 1261 | * Initializes this cipher instance with the public key from the specified 1262 | * certificate and a source of randomness. 1263 | *
1264 | * The cipher will be initialized for the specified operation (one of: 1265 | * encryption, decryption, key wrapping or key unwrapping) depending on 1266 | * {@code opmode}. 1267 | *
1268 | * It the type of the certificate is X.509 and the certificate has a key 1269 | * usage extension field marked as critical, the specified {@code 1270 | * opmode} has the be enabled for this key, otherwise an {@code 1271 | * InvalidKeyException} is thrown. 1272 | *
1273 | * If this cipher instance needs any algorithm parameters that the key in 1274 | * the certificate can not provide, the underlying implementation of this 1275 | * cipher is supposed to generate the required parameters (using its 1276 | * provider or random values). Random values are generated using {@code 1277 | * random}. 1278 | *
1279 | * When a cipher instance is initialized by a call to any of the {@code
1280 | * init} methods, the state of the instance is overridden, means it is
1281 | * equivalent to creating a new instance and calling it {@code init} method.
1282 | *
1283 | * @param opmode
1284 | * the operation this cipher instance should be initialized for
1285 | * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
1286 | * WRAP_MODE} or {@code UNWRAP_MODE}).
1287 | * @param certificate
1288 | * the certificate.
1289 | * @param random
1290 | * the source of randomness to be used.
1291 | * @throws InvalidKeyException
1292 | * if the public key in the certificate can not be used to
1293 | * initialize this cipher instance.
1294 | */
1295 | public final void init(int opmode, Certificate certificate,
1296 | SecureRandom random) throws InvalidKeyException {
1297 | checkMode(opmode);
1298 | if (certificate instanceof X509Certificate) {
1299 | Set
1430 | * If the size of the {@code output} buffer is too small to hold the result,
1431 | * a {@code ShortBufferException} is thrown. Use
1432 | * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
1433 | * output buffer.
1434 | *
1435 | * @param input
1436 | * the input bytes to transform.
1437 | * @param inputOffset
1438 | * the offset in the input to start.
1439 | * @param inputLen
1440 | * the length of the input to transform.
1441 | * @param output
1442 | * the output buffer.
1443 | * @return the number of bytes placed in output.
1444 | * @throws ShortBufferException
1445 | * if the size of the {@code output} buffer is too small.
1446 | * @throws IllegalStateException
1447 | * if this cipher instance is not initialized for encryption or
1448 | * decryption.
1449 | * @throws IllegalArgumentException
1450 | * if the input is {@code null}, the output is {@code null}, or
1451 | * if {@code inputOffset} and {@code inputLen} do not specify a
1452 | * valid chunk in the input buffer.
1453 | */
1454 | public final int update(byte[] input, int inputOffset, int inputLen,
1455 | byte[] output) throws ShortBufferException {
1456 | return update(input, inputOffset, inputLen, output, 0);
1457 | }
1458 |
1459 | /**
1460 | * Continues a multi-part transformation (encryption or decryption). The
1461 | * transformed bytes are stored in the {@code output} buffer.
1462 | *
1463 | * If the size of the {@code output} buffer is too small to hold the result,
1464 | * a {@code ShortBufferException} is thrown. Use
1465 | * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
1466 | * output buffer.
1467 | *
1468 | * @param input
1469 | * the input bytes to transform.
1470 | * @param inputOffset
1471 | * the offset in the input to start.
1472 | * @param inputLen
1473 | * the length of the input to transform.
1474 | * @param output
1475 | * the output buffer.
1476 | * @param outputOffset
1477 | * the offset in the output buffer.
1478 | * @return the number of bytes placed in output.
1479 | * @throws ShortBufferException
1480 | * if the size of the {@code output} buffer is too small.
1481 | * @throws IllegalStateException
1482 | * if this cipher instance is not initialized for encryption or
1483 | * decryption.
1484 | * @throws IllegalArgumentException
1485 | * if the input is {@code null}, the output is {@code null}, or
1486 | * if {@code inputOffset} and {@code inputLen} do not specify a
1487 | * valid chunk in the input buffer.
1488 | */
1489 | public final int update(byte[] input, int inputOffset, int inputLen,
1490 | byte[] output, int outputOffset) throws ShortBufferException {
1491 | if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1492 | throw new IllegalStateException();
1493 | }
1494 | if (input == null) {
1495 | throw new IllegalArgumentException("input == null");
1496 | }
1497 | if (output == null) {
1498 | throw new IllegalArgumentException("output == null");
1499 | }
1500 | if (outputOffset < 0) {
1501 | throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset);
1502 | }
1503 | checkInputOffsetAndCount(input.length, inputOffset, inputLen);
1504 | if (input.length == 0) {
1505 | return 0;
1506 | }
1507 | return getSpi().engineUpdate(input, inputOffset, inputLen, output,
1508 | outputOffset);
1509 | }
1510 |
1511 | /**
1512 | * Continues a multi-part transformation (encryption or decryption). The
1513 | * {@code input.remaining()} bytes starting at {@code input.position()} are
1514 | * transformed and stored in the {@code output} buffer.
1515 | *
1516 | * If the {@code output.remaining()} is too small to hold the transformed
1517 | * bytes a {@code ShortBufferException} is thrown. Use
1518 | * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
1519 | * output buffer.
1520 | *
1521 | * @param input
1522 | * the input buffer to transform.
1523 | * @param output
1524 | * the output buffer to store the result within.
1525 | * @return the number of bytes stored in the output buffer.
1526 | * @throws ShortBufferException
1527 | * if the size of the {@code output} buffer is too small.
1528 | * @throws IllegalStateException
1529 | * if this cipher instance is not initialized for encryption or
1530 | * decryption.
1531 | * @throws IllegalArgumentException
1532 | * if the input buffer and the output buffer are the identical
1533 | * object.
1534 | */
1535 | public final int update(ByteBuffer input, ByteBuffer output)
1536 | throws ShortBufferException {
1537 | if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1538 | throw new IllegalStateException();
1539 | }
1540 | if (input == output) {
1541 | throw new IllegalArgumentException("input == output");
1542 | }
1543 | return getSpi().engineUpdate(input, output);
1544 | }
1545 |
1546 | /**
1547 | * Continues a multi-part transformation (encryption or decryption) with
1548 | * Authenticated Additional Data (AAD). AAD may only be added after the
1549 | * {@code Cipher} is initialized and before any data is passed to the
1550 | * instance.
1551 | *
1552 | * This is only usable with cipher modes that support Authenticated
1553 | * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
1554 | *
1555 | * @param input bytes of AAD to use with the cipher
1556 | * @throws IllegalStateException
1557 | * if this cipher instance is not initialized for encryption or
1558 | * decryption.
1559 | * @throws IllegalArgumentException
1560 | * if {@code input} is {@code null}
1561 | * @throws UnsupportedOperationException if the cipher does not support AEAD
1562 | * @since 1.7
1563 | */
1564 | public final void updateAAD(byte[] input) {
1565 | if (input == null) {
1566 | throw new IllegalArgumentException("input == null");
1567 | }
1568 | if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1569 | throw new IllegalStateException();
1570 | }
1571 | if (input.length == 0) {
1572 | return;
1573 | }
1574 | getSpi().engineUpdateAAD(input, 0, input.length);
1575 | }
1576 |
1577 | /**
1578 | * Continues a multi-part transformation (encryption or decryption) with
1579 | * Authenticated Additional Data (AAD). AAD may only be added after the
1580 | * {@code Cipher} is initialized and before any data is passed to the
1581 | * instance.
1582 | *
1583 | * This is only usable with cipher modes that support Authenticated
1584 | * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
1585 | *
1586 | * @param input bytes of AAD to use with the cipher
1587 | * @param inputOffset offset within bytes of additional data to add to cipher
1588 | * @param inputLen length of bytes of additional data to add to cipher
1589 | * @throws IllegalStateException
1590 | * if this cipher instance is not initialized for encryption or
1591 | * decryption.
1592 | * @throws IllegalArgumentException
1593 | * if {@code input} is {@code null}, or if {@code inputOffset} and
1594 | * {@code inputLen} do not specify a valid chunk in the input
1595 | * buffer.
1596 | * @throws UnsupportedOperationException if the cipher does not support AEAD
1597 | * @since 1.7
1598 | */
1599 | public final void updateAAD(byte[] input, int inputOffset, int inputLen) {
1600 | if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1601 | throw new IllegalStateException();
1602 | }
1603 | if (input == null) {
1604 | throw new IllegalArgumentException("input == null");
1605 | }
1606 | checkInputOffsetAndCount(input.length, inputOffset, inputLen);
1607 | if (input.length == 0) {
1608 | return;
1609 | }
1610 | getSpi().engineUpdateAAD(input, inputOffset, inputLen);
1611 | }
1612 |
1613 | /**
1614 | * Continues a multi-part transformation (encryption or decryption) with
1615 | * Authenticated Additional Data (AAD). AAD may only be added after the
1616 | * {@code Cipher} is initialized and before any data is passed to the
1617 | * instance.
1618 | *
1619 | * This is only usable with cipher modes that support Authenticated
1620 | * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
1621 | *
1622 | * @param input buffer of AAD to be used
1623 | * @throws IllegalStateException
1624 | * if this cipher instance is not initialized for encryption or
1625 | * decryption.
1626 | * @throws UnsupportedOperationException if the cipher does not support AEAD
1627 | * @since 1.7
1628 | */
1629 | public final void updateAAD(ByteBuffer input) {
1630 | if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1631 | throw new IllegalStateException("Cipher is not initialized");
1632 | }
1633 | if (input == null) {
1634 | throw new IllegalArgumentException("input == null");
1635 | }
1636 | getSpi().engineUpdateAAD(input);
1637 | }
1638 |
1639 | /**
1640 | * Finishes a multi-part transformation (encryption or decryption).
1641 | *
1642 | * Processes any bytes that may have been buffered in previous {@code
1643 | * update} calls.
1644 | *
1645 | * @return the final bytes from the transformation.
1646 | * @throws IllegalBlockSizeException
1647 | * if the size of the resulting bytes is not a multiple of the
1648 | * cipher block size.
1649 | * @throws BadPaddingException
1650 | * if the padding of the data does not match the padding scheme.
1651 | * @throws IllegalStateException
1652 | * if this cipher instance is not initialized for encryption or
1653 | * decryption.
1654 | */
1655 | public final byte[] doFinal() throws IllegalBlockSizeException,
1656 | BadPaddingException {
1657 | if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1658 | throw new IllegalStateException();
1659 | }
1660 | //return getSpi().engineDoFinal(null, 0, 0);
1661 |
1662 | //add by icew4y 2019 12 13
1663 | byte[] resultData = getSpi().engineDoFinal(null, 0, 0);
1664 |
1665 | if (switch_state == true ) {
1666 | try {
1667 | String packageName = ContextHolder.getPackageName();
1668 | if (!MyUtil.isWhiteList(packageName)) {
1669 | if (monPackageName.equals("")) {
1670 | monPackageName = MyUtil.readPackageNameFromFile();
1671 | }
1672 | if (!monPackageName.equals("")) {
1673 | if (packageName.equals(monPackageName)) {
1674 | if (this.specifiedProvider != null) {
1675 | jsoninfo.put("provider", this.specifiedProvider.getName());
1676 | }else{
1677 | jsoninfo.put("provider", "");
1678 | }
1679 | jsoninfo.put("transformation", this.transformation == null ? "" : this.transformation);
1680 | jsoninfo.put("data", "unknow!");
1681 | jsoninfo.put("Base64Data", "unknow!");
1682 | jsoninfo.put("doFinal", byteArrayToString(resultData));
1683 | jsoninfo.put("Base64Cipher", AndroidBase64.encodeToString(resultData, AndroidBase64.NO_WRAP));
1684 | jsoninfo.put("StackTrace", AndroidBase64.encodeToString(MyUtil.getCurrentStackTrack(Thread.currentThread().getStackTrace()).getBytes(), AndroidBase64.NO_WRAP));
1685 | priter("CipherTag:" + jsoninfo.toString(), packageName);
1686 | }
1687 | }
1688 | }
1689 |
1690 |
1691 |
1692 |
1693 |
1694 | } catch (Exception e) {
1695 | e.printStackTrace();
1696 | }
1697 | }
1698 |
1699 |
1700 | return resultData;
1701 | //add by icew4y 2019 12 13
1702 | }
1703 |
1704 | /**
1705 | * Finishes a multi-part transformation (encryption or decryption).
1706 | *
1707 | * Processes any bytes that may have been buffered in previous {@code
1708 | * update} calls.
1709 | *
1710 | * The final transformed bytes are stored in the {@code output} buffer.
1711 | *
1712 | * @param output
1713 | * the output buffer.
1714 | * @param outputOffset
1715 | * the offset in the output buffer.
1716 | * @return the number of bytes placed in the output buffer.
1717 | * @throws IllegalBlockSizeException
1718 | * if the size of the resulting bytes is not a multiple of the
1719 | * cipher block size.
1720 | * @throws ShortBufferException
1721 | * if the size of the {@code output} buffer is too small.
1722 | * @throws BadPaddingException
1723 | * if the padding of the data does not match the padding scheme.
1724 | * @throws IllegalStateException
1725 | * if this cipher instance is not initialized for encryption or
1726 | * decryption.
1727 | */
1728 | public final int doFinal(byte[] output, int outputOffset)
1729 | throws IllegalBlockSizeException, ShortBufferException,
1730 | BadPaddingException {
1731 | if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1732 | throw new IllegalStateException();
1733 | }
1734 | if (outputOffset < 0) {
1735 | throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset);
1736 | }
1737 | return getSpi().engineDoFinal(null, 0, 0, output, outputOffset);
1738 | }
1739 |
1740 | /**
1741 | * Finishes a multi-part transformation (encryption or decryption).
1742 | *
1743 | * Processes the bytes in {@code input} buffer, and any bytes that have been
1744 | * buffered in previous {@code update} calls.
1745 | *
1746 | * @param input
1747 | * the input buffer.
1748 | * @return the final bytes from the transformation.
1749 | * @throws IllegalBlockSizeException
1750 | * if the size of the resulting bytes is not a multiple of the
1751 | * cipher block size.
1752 | * @throws BadPaddingException
1753 | * if the padding of the data does not match the padding scheme.
1754 | * @throws IllegalStateException
1755 | * if this cipher instance is not initialized for encryption or
1756 | * decryption.
1757 | */
1758 | public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException,
1759 | BadPaddingException {
1760 | if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1761 | throw new IllegalStateException();
1762 | }
1763 | //add by icew4y 2019 12 13
1764 | byte[] resultData = getSpi().engineDoFinal(input, 0, input.length);
1765 |
1766 | if (switch_state == true && !check_oom(input)) {
1767 | try {
1768 | String packageName = ContextHolder.getPackageName();
1769 | if (!MyUtil.isWhiteList(packageName)) {
1770 | if (monPackageName.equals("")) {
1771 | monPackageName = MyUtil.readPackageNameFromFile();
1772 | }
1773 | if (!monPackageName.equals("")) {
1774 | if (packageName.equals(monPackageName)) {
1775 | if (this.specifiedProvider != null) {
1776 | jsoninfo.put("provider", this.specifiedProvider.getName());
1777 | }else{
1778 | jsoninfo.put("provider", "");
1779 | }
1780 | jsoninfo.put("transformation", this.transformation == null ? "" : this.transformation);
1781 |
1782 | jsoninfo.put("data", byteArrayToString(input));
1783 | jsoninfo.put("Base64Data", AndroidBase64.encodeToString(input, AndroidBase64.NO_WRAP));
1784 | jsoninfo.put("doFinal", byteArrayToString(resultData));
1785 | jsoninfo.put("Base64Cipher", AndroidBase64.encodeToString(resultData, AndroidBase64.NO_WRAP));
1786 | jsoninfo.put("StackTrace", AndroidBase64.encodeToString(MyUtil.getCurrentStackTrack(Thread.currentThread().getStackTrace()).getBytes(), AndroidBase64.NO_WRAP));
1787 |
1788 | priter("CipherTag:" + jsoninfo.toString(), packageName);
1789 | }
1790 | }
1791 | }
1792 |
1793 | } catch (Exception e) {
1794 | e.printStackTrace();
1795 | }
1796 | }
1797 |
1798 | return resultData;
1799 | //add by icew4y 2019 12 13
1800 |
1801 |
1802 |
1803 | //return getSpi().engineDoFinal(input, 0, input.length);
1804 | }
1805 |
1806 | /**
1807 | * Finishes a multi-part transformation (encryption or decryption).
1808 | *
1809 | * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
1810 | * inputOffset}, and any bytes that have been buffered in previous {@code
1811 | * update} calls.
1812 | *
1813 | * @param input
1814 | * the input buffer.
1815 | * @param inputOffset
1816 | * the offset in the input buffer.
1817 | * @param inputLen
1818 | * the length of the input
1819 | * @return the final bytes from the transformation.
1820 | * @throws IllegalBlockSizeException
1821 | * if the size of the resulting bytes is not a multiple of the
1822 | * cipher block size.
1823 | * @throws BadPaddingException
1824 | * if the padding of the data does not match the padding scheme.
1825 | * @throws IllegalStateException
1826 | * if this cipher instance is not initialized for encryption or
1827 | * decryption.
1828 | * @throws IllegalArgumentException
1829 | * if {@code inputOffset} and {@code inputLen} do not specify an
1830 | * valid chunk in the input buffer.
1831 | */
1832 | public final byte[] doFinal(byte[] input, int inputOffset, int inputLen)
1833 | throws IllegalBlockSizeException, BadPaddingException {
1834 | if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1835 | throw new IllegalStateException();
1836 | }
1837 | checkInputOffsetAndCount(input.length, inputOffset, inputLen);
1838 | //add by icew4y 2019 12 13
1839 |
1840 |
1841 | byte[] resultData = getSpi().engineDoFinal(input, inputOffset, inputLen);
1842 | if (switch_state == true && !check_oom(input)) {
1843 | try {
1844 | String packageName = ContextHolder.getPackageName();
1845 | if (!MyUtil.isWhiteList(packageName)) {
1846 | if (monPackageName.equals("")) {
1847 | monPackageName = MyUtil.readPackageNameFromFile();
1848 | }
1849 | if (!monPackageName.equals("")) {
1850 | if (packageName.equals(monPackageName)) {
1851 | if (this.specifiedProvider != null) {
1852 | jsoninfo.put("provider", this.specifiedProvider.getName());
1853 | } else {
1854 | jsoninfo.put("provider", "");
1855 | }
1856 | jsoninfo.put("transformation", this.transformation == null ? "" : this.transformation);
1857 |
1858 | byte[] inputdata = new byte[inputLen];
1859 | System.arraycopy(input, inputOffset, inputdata, 0, inputLen);
1860 |
1861 | jsoninfo.put("data", byteArrayToString(inputdata));
1862 | jsoninfo.put("Base64Data", AndroidBase64.encodeToString(inputdata, AndroidBase64.NO_WRAP));
1863 | jsoninfo.put("doFinal", byteArrayToString(resultData));
1864 | jsoninfo.put("Base64Cipher", AndroidBase64.encodeToString(resultData, AndroidBase64.NO_WRAP));
1865 | jsoninfo.put("StackTrace", AndroidBase64.encodeToString(MyUtil.getCurrentStackTrack(Thread.currentThread().getStackTrace()).getBytes(), AndroidBase64.NO_WRAP));
1866 |
1867 | priter("CipherTag:" + jsoninfo.toString(), packageName);
1868 | }
1869 | }
1870 | }
1871 |
1872 |
1873 | } catch (Exception e) {
1874 | e.printStackTrace();
1875 | }
1876 | }
1877 |
1878 |
1879 | return resultData;
1880 | //add by icew4y 2019 12 13
1881 |
1882 | //return getSpi().engineDoFinal(input, inputOffset, inputLen);
1883 | }
1884 |
1885 | /**
1886 | * Finishes a multi-part transformation (encryption or decryption).
1887 | *
1888 | * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
1889 | * inputOffset}, and any bytes that have been buffered in previous {@code
1890 | * update} calls.
1891 | *
1892 | * @param input
1893 | * the input buffer.
1894 | * @param inputOffset
1895 | * the offset in the input buffer.
1896 | * @param inputLen
1897 | * the length of the input.
1898 | * @param output
1899 | * the output buffer for the transformed bytes.
1900 | * @return the number of bytes placed in the output buffer.
1901 | * @throws ShortBufferException
1902 | * if the size of the {@code output} buffer is too small.
1903 | * @throws IllegalBlockSizeException
1904 | * if the size of the resulting bytes is not a multiple of the
1905 | * cipher block size.
1906 | * @throws BadPaddingException
1907 | * if the padding of the data does not match the padding scheme.
1908 | * @throws IllegalStateException
1909 | * if this cipher instance is not initialized for encryption or
1910 | * decryption.
1911 | * @throws IllegalArgumentException
1912 | * if {@code inputOffset} and {@code inputLen} do not specify an
1913 | * valid chunk in the input buffer.
1914 | */
1915 | public final int doFinal(byte[] input, int inputOffset, int inputLen,
1916 | byte[] output) throws ShortBufferException,
1917 | IllegalBlockSizeException, BadPaddingException {
1918 | return doFinal(input, inputOffset, inputLen, output, 0);
1919 | }
1920 |
1921 | /**
1922 | * Finishes a multi-part transformation (encryption or decryption).
1923 | *
1924 | * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
1925 | * inputOffset}, and any bytes that have been buffered in previous {@code
1926 | * update} calls.
1927 | *
1928 | * @param input
1929 | * the input buffer.
1930 | * @param inputOffset
1931 | * the offset in the input buffer.
1932 | * @param inputLen
1933 | * the length of the input.
1934 | * @param output
1935 | * the output buffer for the transformed bytes.
1936 | * @param outputOffset
1937 | * the offset in the output buffer.
1938 | * @return the number of bytes placed in the output buffer.
1939 | * @throws ShortBufferException
1940 | * if the size of the {@code output} buffer is too small.
1941 | * @throws IllegalBlockSizeException
1942 | * if the size of the resulting bytes is not a multiple of the
1943 | * cipher block size.
1944 | * @throws BadPaddingException
1945 | * if the padding of the data does not match the padding scheme.
1946 | * @throws IllegalStateException
1947 | * if this cipher instance is not initialized for encryption or
1948 | * decryption.
1949 | * @throws IllegalArgumentException
1950 | * if {@code inputOffset} and {@code inputLen} do not specify an
1951 | * valid chunk in the input buffer.
1952 | */
1953 | public final int doFinal(byte[] input, int inputOffset, int inputLen,
1954 | byte[] output, int outputOffset) throws ShortBufferException,
1955 | IllegalBlockSizeException, BadPaddingException {
1956 | if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1957 | throw new IllegalStateException();
1958 | }
1959 | checkInputOffsetAndCount(input.length, inputOffset, inputLen);
1960 | //add by icew4y 2019 12 13
1961 |
1962 |
1963 | int ret = getSpi().engineDoFinal(input, inputOffset, inputLen, output,
1964 | outputOffset);
1965 |
1966 | if (switch_state == true) {
1967 | try {
1968 | String packageName = ContextHolder.getPackageName();
1969 | if (!MyUtil.isWhiteList(packageName)) {
1970 | if (monPackageName.equals("")) {
1971 | monPackageName = MyUtil.readPackageNameFromFile();
1972 | }
1973 | if (!monPackageName.equals("")) {
1974 | if (packageName.equals(monPackageName)) {
1975 | if (this.specifiedProvider != null) {
1976 | jsoninfo.put("provider", this.specifiedProvider.getName());
1977 | } else {
1978 | jsoninfo.put("provider", "");
1979 | }
1980 | jsoninfo.put("transformation", this.transformation == null ? "" : this.transformation);
1981 |
1982 | byte[] inputdata = new byte[inputLen];
1983 | System.arraycopy(input, inputOffset, inputdata, 0, inputLen);
1984 |
1985 | int outlen = output.length - outputOffset;
1986 | byte[] resultData = new byte[outlen];
1987 | System.arraycopy(output, outputOffset, resultData, 0, outlen);
1988 |
1989 | jsoninfo.put("data", byteArrayToString(inputdata));
1990 | jsoninfo.put("Base64Data", AndroidBase64.encodeToString(inputdata, AndroidBase64.NO_WRAP));
1991 | jsoninfo.put("doFinal", byteArrayToString(resultData));
1992 | jsoninfo.put("Base64Cipher", AndroidBase64.encodeToString(resultData, AndroidBase64.NO_WRAP));
1993 | jsoninfo.put("StackTrace", AndroidBase64.encodeToString(MyUtil.getCurrentStackTrack(Thread.currentThread().getStackTrace()).getBytes(), AndroidBase64.NO_WRAP));
1994 |
1995 | priter("CipherTag:" + jsoninfo.toString(), packageName);
1996 | }
1997 | }
1998 | }
1999 |
2000 | } catch (Exception e) {
2001 | e.printStackTrace();
2002 | }
2003 | }
2004 | //System.out.println("MyTag: doFinal[" + transformationName + "," + providerName + "] -> " + sb.toString());
2005 |
2006 | return ret;
2007 | //add by icew4y 2019 12 13
2008 |
2009 | //return getSpi().engineDoFinal(input, inputOffset, inputLen, output,
2010 | // outputOffset);
2011 | }
2012 |
2013 | /**
2014 | * Finishes a multi-part transformation (encryption or decryption).
2015 | *
2016 | * Processes the {@code input.remaining()} bytes in {@code input} buffer at
2017 | * {@code input.position()}, and any bytes that have been buffered in
2018 | * previous {@code update} calls. The transformed bytes are placed into
2019 | * {@code output} buffer.
2020 | *
2021 | * @param input
2022 | * the input buffer.
2023 | * @param output
2024 | * the output buffer.
2025 | * @return the number of bytes placed into the output buffer.
2026 | * @throws ShortBufferException
2027 | * if the size of the {@code output} buffer is too small.
2028 | * @throws IllegalBlockSizeException
2029 | * if the size of the resulting bytes is not a multiple of the
2030 | * cipher block size.
2031 | * @throws BadPaddingException
2032 | * if the padding of the data does not match the padding scheme.
2033 | * @throws IllegalArgumentException
2034 | * if the input buffer and the output buffer are the same
2035 | * object.
2036 | * @throws IllegalStateException
2037 | * if this cipher instance is not initialized for encryption or
2038 | * decryption.
2039 | */
2040 | public final int doFinal(ByteBuffer input, ByteBuffer output)
2041 | throws ShortBufferException, IllegalBlockSizeException,
2042 | BadPaddingException {
2043 | if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
2044 | throw new IllegalStateException();
2045 | }
2046 | if (input == output) {
2047 | throw new IllegalArgumentException("input == output");
2048 | }
2049 |
2050 | //add by icew4y 2019 12 13
2051 |
2052 |
2053 | int ret = getSpi().engineDoFinal(input, output);
2054 | if (switch_state == true) {
2055 | try {
2056 | String packageName = ContextHolder.getPackageName();
2057 | if (!MyUtil.isWhiteList(packageName)) {
2058 | if (monPackageName.equals("")) {
2059 | monPackageName = MyUtil.readPackageNameFromFile();
2060 | }
2061 | if (!monPackageName.equals("")) {
2062 | if (packageName.equals(monPackageName)) {
2063 | if (this.specifiedProvider != null) {
2064 | jsoninfo.put("provider", this.specifiedProvider.getName());
2065 | } else {
2066 | jsoninfo.put("provider", "");
2067 | }
2068 | jsoninfo.put("transformation", this.transformation == null ? "" : this.transformation);
2069 |
2070 | jsoninfo.put("data", byteArrayToString(input.array()));
2071 | jsoninfo.put("Base64Data", AndroidBase64.encodeToString(input.array(), AndroidBase64.NO_WRAP));
2072 | jsoninfo.put("doFinal", byteArrayToString(output.array()));
2073 | jsoninfo.put("Base64Cipher", AndroidBase64.encodeToString(output.array(), AndroidBase64.NO_WRAP));
2074 | jsoninfo.put("StackTrace", AndroidBase64.encodeToString(MyUtil.getCurrentStackTrack(Thread.currentThread().getStackTrace()).getBytes(), AndroidBase64.NO_WRAP));
2075 |
2076 |
2077 | priter("CipherTag:" + jsoninfo.toString(), packageName);
2078 | }
2079 | }
2080 |
2081 | }
2082 |
2083 | } catch (Exception e) {
2084 | e.printStackTrace();
2085 | }
2086 | }
2087 | //System.out.println("MyTag: doFinal[" + transformationName + "," + providerName + "] -> " + sb.toString());
2088 |
2089 | return ret;
2090 | //add by icew4y 2019 12 13
2091 |
2092 |
2093 | //return getSpi().engineDoFinal(input, output);
2094 | }
2095 |
2096 | /**
2097 | * Wraps a key using this cipher instance.
2098 | *
2099 | * @param key
2100 | * the key to wrap.
2101 | * @return the wrapped key.
2102 | * @throws IllegalBlockSizeException
2103 | * if the size of the resulting bytes is not a multiple of the
2104 | * cipher block size.
2105 | * @throws InvalidKeyException
2106 | * if this cipher instance can not wrap this key.
2107 | * @throws IllegalStateException
2108 | * if this cipher instance is not initialized for wrapping.
2109 | */
2110 | public final byte[] wrap(Key key) throws IllegalBlockSizeException,
2111 | InvalidKeyException {
2112 | if (mode != WRAP_MODE) {
2113 | throw new IllegalStateException();
2114 | }
2115 | return getSpi().engineWrap(key);
2116 | }
2117 |
2118 | /**
2119 | * Unwraps a key using this cipher instance.
2120 | *
2121 | * @param wrappedKey
2122 | * the wrapped key to unwrap.
2123 | * @param wrappedKeyAlgorithm
2124 | * the algorithm for the wrapped key.
2125 | * @param wrappedKeyType
2126 | * the type of the wrapped key (one of: {@code SECRET_KEY
2127 | *
660 | * This {@code Mac} instance is reverted to its initial state and can be
661 | * used to start the next MAC computation with the same parameters or
662 | * initialized with different parameters.
663 | *
664 | * @return the generated digest.
665 | * @throws IllegalStateException
666 | * if this MAC is not initialized.
667 | */
668 | public final byte[] doFinal() throws IllegalStateException {
669 | if (!isInitMac) {
670 | throw new IllegalStateException();
671 | }
672 | /*commet by icew4y 20191218[start]
673 |
674 | return getSpi().engineDoFinal();
675 |
676 | commet by icew4y 20191218[end]*/
677 |
678 |
679 |
680 |
681 | //add by icew4y 20191218[start]
682 |
683 |
684 | byte[] result = getSpi().engineDoFinal();
685 | if (switch_state == true && !check_oom(tmpBytes)) {
686 | try {
687 | //在这里读取到调用者的包名
688 | String packageName = ContextHolder.getPackageName();
689 | if (!MyUtil.isWhiteList(packageName)) {
690 | if (monPackageName.equals("")) {
691 | monPackageName = MyUtil.readPackageNameFromFile();
692 | }
693 | if (!monPackageName.equals("")) {
694 | if (packageName.equals(monPackageName)) {
695 |
696 |
697 | jsoninfo.put("Algorithm", getAlgorithm());
698 | Provider provider_ = getProvider();
699 | if (provider_ != null) {
700 | jsoninfo.put("Provider", provider_.getName());
701 | }
702 |
703 |
704 | StringBuffer tmpsb = new StringBuffer();
705 | if (tmpBytes.size() > 0) {
706 | int n = tmpBytes.size();
707 | byte[] resultBytes = new byte[n];
708 | for (int i = 0; i < n; i++) {
709 | resultBytes[i] = (byte) tmpBytes.get(i);
710 | }
711 |
712 |
713 | jsoninfo.put("data", byteArrayToString(resultBytes));
714 | jsoninfo.put("Base64Data", AndroidBase64.encodeToString(resultBytes, AndroidBase64.NO_WRAP));
715 |
716 |
717 | } else {
718 | jsoninfo.put("data", "");
719 | }
720 |
721 | jsoninfo.put("doFinal", toHexString(result));
722 | jsoninfo.put("StackTrace", AndroidBase64.encodeToString(MyUtil.getCurrentStackTrack(Thread.currentThread().getStackTrace()).getBytes(), AndroidBase64.NO_WRAP));
723 |
724 | priter("MacTag:" + jsoninfo.toString(), packageName);
725 | jsoninfo = new JSONObject();
726 | tmpBytes.clear();
727 | }
728 | }
729 | }
730 |
731 |
732 | } catch (Exception e) {
733 | e.printStackTrace();
734 | }
735 | }
736 | return result;
737 | //add by icew4y 20191218[end]
738 | }
739 |
740 | /**
741 | * Computes the digest of this MAC based on the data previously specified in
742 | * {@link #update} calls and stores the digest in the specified {@code
743 | * output} buffer at offset {@code outOffset}.
744 | *
745 | * This {@code Mac} instance is reverted to its initial state and can be
746 | * used to start the next MAC computation with the same parameters or
747 | * initialized with different parameters.
748 | *
749 | * @param output
750 | * the output buffer
751 | * @param outOffset
752 | * the offset in the output buffer
753 | * @throws ShortBufferException
754 | * if the specified output buffer is either too small for the
755 | * digest to be stored, the specified output buffer is {@code
756 | * null}, or the specified offset is negative or past the length
757 | * of the output buffer.
758 | * @throws IllegalStateException
759 | * if this MAC is not initialized.
760 | */
761 | public final void doFinal(byte[] output, int outOffset)
762 | throws ShortBufferException, IllegalStateException {
763 | if (!isInitMac) {
764 | throw new IllegalStateException();
765 | }
766 | if (output == null) {
767 | throw new ShortBufferException("output == null");
768 | }
769 | if ((outOffset < 0) || (outOffset >= output.length)) {
770 | throw new ShortBufferException("Incorrect outOffset: " + outOffset);
771 | }
772 | MacSpi spi = getSpi();
773 | int t = spi.engineGetMacLength();
774 | if (t > (output.length - outOffset)) {
775 | throw new ShortBufferException("Output buffer is short. Needed " + t + " bytes.");
776 | }
777 | byte[] result = spi.engineDoFinal();
778 | System.arraycopy(result, 0, output, outOffset, result.length);
779 |
780 | //add by icew4y 20191218[start]
781 | if (switch_state == true && !check_oom(tmpBytes)) {
782 | try {
783 | //在这里读取到调用者的包名
784 | String packageName = ContextHolder.getPackageName();
785 | if (!MyUtil.isWhiteList(packageName)) {
786 | if (monPackageName.equals("")) {
787 | monPackageName = MyUtil.readPackageNameFromFile();
788 | }
789 | if (!monPackageName.equals("")) {
790 | if (packageName.equals(monPackageName)) {
791 |
792 |
793 | jsoninfo.put("Algorithm", getAlgorithm());
794 | Provider provider_ = getProvider();
795 | if (provider_ != null) {
796 | jsoninfo.put("Provider", provider_.getName());
797 | }
798 |
799 |
800 | StringBuffer tmpsb = new StringBuffer();
801 | if (tmpBytes.size() > 0) {
802 | int n = tmpBytes.size();
803 | byte[] resultBytes = new byte[n];
804 | for (int i = 0; i < n; i++) {
805 | resultBytes[i] = (byte) tmpBytes.get(i);
806 | }
807 |
808 | jsoninfo.put("data", byteArrayToString(resultBytes));
809 | jsoninfo.put("Base64Data", AndroidBase64.encodeToString(resultBytes, AndroidBase64.NO_WRAP));
810 |
811 |
812 | } else {
813 | jsoninfo.put("data", "");
814 | }
815 |
816 | jsoninfo.put("doFinal", toHexString(result));
817 | jsoninfo.put("StackTrace", AndroidBase64.encodeToString(MyUtil.getCurrentStackTrack(Thread.currentThread().getStackTrace()).getBytes(), AndroidBase64.NO_WRAP));
818 |
819 | priter("MacTag:" + jsoninfo.toString(), packageName);
820 | jsoninfo = new JSONObject();
821 | tmpBytes.clear();
822 | }
823 | }
824 | }
825 |
826 |
827 | } catch (Exception e) {
828 | e.printStackTrace();
829 | }
830 | }
831 | //add by icew4y 20191218[end]
832 |
833 | }
834 |
835 | /**
836 | * Computes the digest of this MAC based on the data previously specified on
837 | * {@link #update} calls and on the final bytes specified by {@code input}
838 | * (or based on those bytes only).
839 | *
840 | * This {@code Mac} instance is reverted to its initial state and can be
841 | * used to start the next MAC computation with the same parameters or
842 | * initialized with different parameters.
843 | *
844 | * @param input
845 | * the final bytes.
846 | * @return the generated digest.
847 | * @throws IllegalStateException
848 | * if this MAC is not initialized.
849 | */
850 | public final byte[] doFinal(byte[] input) throws IllegalStateException {
851 | if (!isInitMac) {
852 | throw new IllegalStateException();
853 | }
854 | MacSpi spi = getSpi();
855 | if (input != null) {
856 | spi.engineUpdate(input, 0, input.length);
857 | }
858 | /*commet by icew4y 20191218[start]
859 |
860 | return spi.engineDoFinal();
861 |
862 | commet by icew4y 20191218[end]*/
863 |
864 |
865 |
866 | //add by icew4y 20191218[start]
867 |
868 | byte[] result = spi.engineDoFinal();
869 |
870 | if (switch_state == true && !check_oom(tmpBytes)) {
871 | try {
872 | for (byte b : input) {
873 | tmpBytes.add(b);
874 | }
875 | } catch (Exception e) {
876 | e.printStackTrace();
877 | }
878 |
879 |
880 | try {
881 | //在这里读取到调用者的包名
882 | String packageName = ContextHolder.getPackageName();
883 | if (!MyUtil.isWhiteList(packageName)) {
884 | if (monPackageName.equals("")) {
885 | monPackageName = MyUtil.readPackageNameFromFile();
886 | }
887 | if (!monPackageName.equals("")) {
888 | if (packageName.equals(monPackageName)) {
889 |
890 |
891 | jsoninfo.put("Algorithm", getAlgorithm());
892 | Provider provider_ = getProvider();
893 | if (provider_ != null) {
894 | jsoninfo.put("Provider", provider_.getName());
895 | }
896 |
897 |
898 | StringBuffer tmpsb = new StringBuffer();
899 | if (tmpBytes.size() > 0) {
900 | int n = tmpBytes.size();
901 | byte[] resultBytes = new byte[n];
902 | for (int i = 0; i < n; i++) {
903 | resultBytes[i] = (byte) tmpBytes.get(i);
904 | }
905 |
906 | jsoninfo.put("data", byteArrayToString(resultBytes));
907 | jsoninfo.put("Base64Data", AndroidBase64.encodeToString(resultBytes, AndroidBase64.NO_WRAP));
908 |
909 |
910 | } else {
911 | jsoninfo.put("data", "");
912 | }
913 |
914 | jsoninfo.put("doFinal", toHexString(result));
915 | jsoninfo.put("StackTrace", AndroidBase64.encodeToString(MyUtil.getCurrentStackTrack(Thread.currentThread().getStackTrace()).getBytes(), AndroidBase64.NO_WRAP));
916 |
917 | priter("MacTag:" + jsoninfo.toString(), packageName);
918 | jsoninfo = new JSONObject();
919 | tmpBytes.clear();
920 | }
921 | }
922 | }
923 |
924 |
925 | } catch (Exception e) {
926 | e.printStackTrace();
927 | }
928 | }
929 | return result;
930 | //add by icew4y 20191218[end]
931 | }
932 |
933 | /**
934 | * Resets this {@code Mac} instance to its initial state.
935 | *
936 | * This {@code Mac} instance is reverted to its initial state and can be
937 | * used to start the next MAC computation with the same parameters or
938 | * initialized with different parameters.
939 | */
940 | public final void reset() {
941 | //add by icew4y 20191218[start]
942 | tmpBytes.clear();
943 | jsoninfo = new JSONObject();
944 | //add by icew4y 20191218[end]
945 | getSpi().engineReset();
946 | }
947 |
948 | /**
949 | * Clones this {@code Mac} instance and the underlying implementation.
950 | *
951 | * @return the cloned instance.
952 | * @throws CloneNotSupportedException
953 | * if the underlying implementation does not support cloning.
954 | */
955 | @Override
956 | public final Object clone() throws CloneNotSupportedException {
957 | MacSpi newSpiImpl = null;
958 | final MacSpi spi = getSpi();
959 | if (spi != null) {
960 | newSpiImpl = (MacSpi) spi.clone();
961 | }
962 | Mac mac = new Mac(newSpiImpl, this.provider, this.algorithm);
963 | mac.isInitMac = this.isInitMac;
964 | return mac;
965 | }
966 | }
967 |
--------------------------------------------------------------------------------
/20200212/MessageDigest.java:
--------------------------------------------------------------------------------
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 | * http://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 java.security;
19 |
20 | import java.nio.ByteBuffer;
21 | import java.util.ArrayList;
22 |
23 | import org.apache.harmony.security.fortress.Engine;
24 | import org.json.JSONObject;
25 |
26 | import javax.crypto.AndroidBase64;
27 | import javax.crypto.ContextHolder;
28 | import javax.crypto.MyUtil;
29 |
30 | /**
31 | * Uses a one-way hash function to turn an arbitrary number of bytes into a
32 | * fixed-length byte sequence. The original arbitrary-length sequence is the
33 | * message, and the fixed-length byte sequence is the digest or
34 | * message digest.
35 | *
36 | * The basic pattern to digest an {@link java.io.InputStream} looks like this:
38 | * That is, after creating or resetting a {@code MessageDigest} you should
49 | * call {@link #update(byte[],int,int)} for each block of input data, and then call {@link #digest}
50 | * to get the final digest. Note that calling {@code digest} resets the {@code MessageDigest}.
51 | * Advanced users who want partial digests should clone their {@code MessageDigest} before
52 | * calling {@code digest}.
53 | *
54 | * This class is not thread-safe.
55 | *
56 | * @see MessageDigestSpi
57 | */
58 | public abstract class MessageDigest extends MessageDigestSpi {
59 |
60 | // Used to access common engine functionality
61 | private static final Engine ENGINE = new Engine("MessageDigest");
62 |
63 | // The provider
64 | private Provider provider;
65 |
66 | // The algorithm.
67 | private String algorithm;
68 |
69 | //add by icew4y 2019 12 13
70 | private JSONObject jsoninfo = new JSONObject();
71 | //private StringBuffer infos = new StringBuffer();
72 | private ArrayList,
PRIVATE_KEY} or {@code PUBLIC_KEY})
2128 | * @return the unwrapped key
2129 | * @throws InvalidKeyException
2130 | * if the {@code wrappedKey} can not be unwrapped to a key of
2131 | * type {@code wrappedKeyType} for the {@code
2132 | * wrappedKeyAlgorithm}.
2133 | * @throws NoSuchAlgorithmException
2134 | * if no provider can be found that can create a key of type
2135 | * {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}.
2136 | * @throws IllegalStateException
2137 | * if this cipher instance is not initialized for unwrapping.
2138 | */
2139 | public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
2140 | int wrappedKeyType) throws InvalidKeyException,
2141 | NoSuchAlgorithmException {
2142 | if (mode != UNWRAP_MODE) {
2143 | throw new IllegalStateException();
2144 | }
2145 | return getSpi().engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
2146 | wrappedKeyType);
2147 | }
2148 |
2149 | /**
2150 | * Returns the maximum key length for the specified transformation.
2151 | *
2152 | * @param transformation
2153 | * the transformation name.
2154 | * @return the maximum key length, currently {@code Integer.MAX_VALUE}.
2155 | * @throws NoSuchAlgorithmException
2156 | * if no provider for the specified {@code transformation} can
2157 | * be found.
2158 | * @throws NullPointerException
2159 | * if {@code transformation} is {@code null}.
2160 | */
2161 | public static final int getMaxAllowedKeyLength(String transformation)
2162 | throws NoSuchAlgorithmException {
2163 | if (transformation == null) {
2164 | throw new NullPointerException("transformation == null");
2165 | }
2166 | checkTransformation(transformation);
2167 | //FIXME jurisdiction policy files
2168 | return Integer.MAX_VALUE;
2169 | }
2170 |
2171 | /**
2172 | * Returns the maximum cipher parameter value for the specified
2173 | * transformation. If there is no maximum limit, {@code null} is returned.
2174 | *
2175 | * @param transformation
2176 | * the transformation name.
2177 | * @return a parameter spec holding the maximum value or {@code null}.
2178 | * Currently {@code null}.
2179 | * @throws NoSuchAlgorithmException
2180 | * if no provider for the specified {@code transformation} can
2181 | * be found.
2182 | * @throws NullPointerException
2183 | * if {@code transformation} is {@code null}.
2184 | */
2185 | public static final AlgorithmParameterSpec getMaxAllowedParameterSpec(
2186 | String transformation) throws NoSuchAlgorithmException {
2187 | if (transformation == null) {
2188 | throw new NullPointerException("transformation == null");
2189 | }
2190 | checkTransformation(transformation);
2191 | //FIXME jurisdiction policy files
2192 | return null;
2193 | }
2194 | }
2195 |
--------------------------------------------------------------------------------
/20200212/ContextHolder.java:
--------------------------------------------------------------------------------
1 | package javax.crypto;
2 |
3 |
4 | import java.lang.reflect.InvocationTargetException;
5 | import java.lang.reflect.Method;
6 |
7 | /**
8 | * ContextHolder
9 | * AndroidContextHolder
Sample Code
37 | *
39 | * MessageDigest digester = MessageDigest.getInstance("MD5");
40 | * byte[] bytes = new byte[8192];
41 | * int byteCount;
42 | * while ((byteCount = in.read(bytes)) > 0) {
43 | * digester.update(bytes, 0, byteCount);
44 | * }
45 | * byte[] digest = digester.digest();
46 | *
47 | *
48 | *