├── .gitignore
├── .idea
├── codeStyles
│ └── Project.xml
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── runConfigurations.xml
└── vcs.xml
├── LICENSE
├── README.md
├── android-sample-app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
├── signing_confs
│ └── sample_conf.gradle
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── mobapphome
│ │ └── simpleencryptorlib
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── mobapphome
│ │ │ └── simpleencryptorlib
│ │ │ └── sample
│ │ │ ├── SampleActivityJava.java
│ │ │ └── SampleActivityKotlin.kt
│ └── res
│ │ ├── drawable-hdpi
│ │ ├── ic_keyboard_arrow_down_black_24dp.png
│ │ └── ic_keyboard_arrow_up_black_24dp.png
│ │ ├── drawable-mdpi
│ │ ├── ic_arrow_downward_black_48dp.png
│ │ ├── ic_arrow_upward_black_48dp.png
│ │ ├── ic_keyboard_arrow_down_black_24dp.png
│ │ └── ic_keyboard_arrow_up_black_24dp.png
│ │ ├── drawable-xhdpi
│ │ ├── ic_arrow_downward_black_48dp.png
│ │ ├── ic_arrow_upward_black_48dp.png
│ │ ├── ic_keyboard_arrow_down_black_24dp.png
│ │ └── ic_keyboard_arrow_up_black_24dp.png
│ │ ├── drawable-xxhdpi
│ │ ├── ic_arrow_downward_black_48dp.png
│ │ ├── ic_arrow_upward_black_48dp.png
│ │ ├── ic_keyboard_arrow_down_black_24dp.png
│ │ └── ic_keyboard_arrow_up_black_24dp.png
│ │ ├── drawable-xxxhdpi
│ │ ├── ic_arrow_downward_black_48dp.png
│ │ ├── ic_arrow_upward_black_48dp.png
│ │ ├── ic_keyboard_arrow_down_black_24dp.png
│ │ └── ic_keyboard_arrow_up_black_24dp.png
│ │ ├── drawable
│ │ └── forkme_green.png
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── mobapphome
│ └── simpleencryptorlib
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── imgs
├── google-play-badge.png
├── green_star.png
├── img_create
│ ├── ic_launcher
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ └── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ └── web_hi_res_512.png
│ ├── mah_android_updater_head_img.jpg
│ ├── mah_android_updater_head_img.psd
│ ├── mah_android_updater_logo.ai
│ ├── mah_android_updater_logo.png
│ └── screenshots
│ │ ├── Screenshot_2016-09-08-17-01-59.png
│ │ └── Screenshot_2016-09-08-17-02-03.png
├── mahencryptor_google_play_url_qr_code.jpg
├── main_activity.png
├── main_activity_small.png
└── yellow_star.png
├── java-sample-app
├── .gitignore
├── build.gradle
└── src
│ └── main
│ └── java
│ └── com
│ └── mobapphome
│ └── simpleencryptorlib_javasample
│ ├── SampleEncryptorJavaSample.java
│ └── SampleEncryptorKotlinSample.kt
├── key
└── .gitignore
├── projectFilesBackup
└── .idea
│ └── workspace.xml
├── settings.gradle
└── simple-encryptor-lib
├── .gitignore
├── build.gradle
├── conf_for_maven
├── bintrayv1.gradle
└── installv1.gradle
└── src
└── main
└── java
└── com
└── mobapphome
└── simpleencryptorlib
├── Base64.java
├── Constants.java
└── SimpleEncryptor.java
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | /.idea/misc.xml
7 | /.idea/modules.xml
8 | /.idea/caches
9 | .DS_Store
10 | /build
11 | /captures
12 |
13 | /android-sample-app/signing_confs/conf.gradle
14 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
Free, open source, third party Android library and PC library for encryption and decryption strings on Android apps and pc Java applications. Library is 100% compatible with Kotlin and Java applications. Contains sample in both Kotlin and Java. Check out the wiki. To support,
14 |
15 |
Uses "The Base64 Alphabet" as specified in Table 1 of 52 | * RFC 4648 and RFC 2045 for encoding and decoding operation. 53 | * The encoder does not add any line feed (line separator) 54 | * character. The decoder rejects data that contains characters 55 | * outside the base64 alphabet.
Uses the "URL and Filename safe Base64 Alphabet" as specified 59 | * in Table 2 of RFC 4648 for encoding and decoding. The 60 | * encoder does not add any line feed (line separator) character. 61 | * The decoder rejects data that contains characters outside the 62 | * base64 alphabet.
Uses the "The Base64 Alphabet" as specified in Table 1 of 66 | * RFC 2045 for encoding and decoding operation. The encoded output 67 | * must be represented in lines of no more than 76 characters each 68 | * and uses a carriage return {@code '\r'} followed immediately by 69 | * a linefeed {@code '\n'} as the line separator. No line separator 70 | * is added to the end of the encoded output. All line separators 71 | * or other characters not found in the base64 alphabet table are 72 | * ignored in decoding operation.
Unless otherwise noted, passing a {@code null} argument to a 76 | * method of this class will cause a {@link NullPointerException 77 | * NullPointerException} to be thrown. 78 | * 79 | * @author Xueming Shen 80 | * @since 1.8 81 | */ 82 | 83 | public class Base64 { 84 | 85 | private Base64() {} 86 | 87 | /** 88 | * Returns a {@link Encoder} that encodes using the 89 | * Basic type base64 encoding scheme. 90 | * 91 | * @return A Base64 encoder. 92 | */ 93 | public static Encoder getEncoder() { 94 | return Encoder.RFC4648; 95 | } 96 | 97 | /** 98 | * Returns a {@link Encoder} that encodes using the 99 | * URL and Filename safe type base64 100 | * encoding scheme. 101 | * 102 | * @return A Base64 encoder. 103 | */ 104 | public static Encoder getUrlEncoder() { 105 | return Encoder.RFC4648_URLSAFE; 106 | } 107 | 108 | /** 109 | * Returns a {@link Encoder} that encodes using the 110 | * MIME type base64 encoding scheme. 111 | * 112 | * @return A Base64 encoder. 113 | */ 114 | public static Encoder getMimeEncoder() { 115 | return Encoder.RFC2045; 116 | } 117 | 118 | /** 119 | * Returns a {@link Encoder} that encodes using the 120 | * MIME type base64 encoding scheme 121 | * with specified line length and line separators. 122 | * 123 | * @param lineLength 124 | * the length of each output line (rounded down to nearest multiple 125 | * of 4). If {@code lineLength <= 0} the output will not be separated 126 | * in lines 127 | * @param lineSeparator 128 | * the line separator for each output line 129 | * 130 | * @return A Base64 encoder. 131 | * 132 | * @throws IllegalArgumentException if {@code lineSeparator} includes any 133 | * character of "The Base64 Alphabet" as specified in Table 1 of 134 | * RFC 2045. 135 | */ 136 | public static Encoder getMimeEncoder(int lineLength, byte[] lineSeparator) { 137 | Objects.requireNonNull(lineSeparator); 138 | int[] base64 = Decoder.fromBase64; 139 | for (byte b : lineSeparator) { 140 | if (base64[b & 0xff] != -1) 141 | throw new IllegalArgumentException( 142 | "Illegal base64 line separator character 0x" + Integer.toString(b, 16)); 143 | } 144 | if (lineLength <= 0) { 145 | return Encoder.RFC4648; 146 | } 147 | return new Encoder(false, lineSeparator, lineLength >> 2 << 2, true); 148 | } 149 | 150 | /** 151 | * Returns a {@link Decoder} that decodes using the 152 | * Basic type base64 encoding scheme. 153 | * 154 | * @return A Base64 decoder. 155 | */ 156 | public static Decoder getDecoder() { 157 | return Decoder.RFC4648; 158 | } 159 | 160 | /** 161 | * Returns a {@link Decoder} that decodes using the 162 | * URL and Filename safe type base64 163 | * encoding scheme. 164 | * 165 | * @return A Base64 decoder. 166 | */ 167 | public static Decoder getUrlDecoder() { 168 | return Decoder.RFC4648_URLSAFE; 169 | } 170 | 171 | /** 172 | * Returns a {@link Decoder} that decodes using the 173 | * MIME type base64 decoding scheme. 174 | * 175 | * @return A Base64 decoder. 176 | */ 177 | public static Decoder getMimeDecoder() { 178 | return Decoder.RFC2045; 179 | } 180 | 181 | /** 182 | * This class implements an encoder for encoding byte data using 183 | * the Base64 encoding scheme as specified in RFC 4648 and RFC 2045. 184 | * 185 | *
Instances of {@link Encoder} class are safe for use by 186 | * multiple concurrent threads. 187 | * 188 | *
Unless otherwise noted, passing a {@code null} argument to 189 | * a method of this class will cause a 190 | * {@link NullPointerException NullPointerException} to 191 | * be thrown. 192 | * 193 | * @see Decoder 194 | * @since 1.8 195 | */ 196 | public static class Encoder { 197 | 198 | private final byte[] newline; 199 | private final int linemax; 200 | private final boolean isURL; 201 | private final boolean doPadding; 202 | 203 | private Encoder(boolean isURL, byte[] newline, int linemax, boolean doPadding) { 204 | this.isURL = isURL; 205 | this.newline = newline; 206 | this.linemax = linemax; 207 | this.doPadding = doPadding; 208 | } 209 | 210 | /** 211 | * This array is a lookup table that translates 6-bit positive integer 212 | * index values into their "Base64 Alphabet" equivalents as specified 213 | * in "Table 1: The Base64 Alphabet" of RFC 2045 (and RFC 4648). 214 | */ 215 | private static final char[] toBase64 = { 216 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 217 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 218 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 219 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 220 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' 221 | }; 222 | 223 | /** 224 | * It's the lookup table for "URL and Filename safe Base64" as specified 225 | * in Table 2 of the RFC 4648, with the '+' and '/' changed to '-' and 226 | * '_'. This table is used when BASE64_URL is specified. 227 | */ 228 | private static final char[] toBase64URL = { 229 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 230 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 231 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 232 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 233 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' 234 | }; 235 | 236 | private static final int MIMELINEMAX = 76; 237 | private static final byte[] CRLF = new byte[] {'\r', '\n'}; 238 | 239 | static final Encoder RFC4648 = new Encoder(false, null, -1, true); 240 | static final Encoder RFC4648_URLSAFE = new Encoder(true, null, -1, true); 241 | static final Encoder RFC2045 = new Encoder(false, CRLF, MIMELINEMAX, true); 242 | 243 | private final int outLength(int srclen) { 244 | int len = 0; 245 | if (doPadding) { 246 | len = 4 * ((srclen + 2) / 3); 247 | } else { 248 | int n = srclen % 3; 249 | len = 4 * (srclen / 3) + (n == 0 ? 0 : n + 1); 250 | } 251 | if (linemax > 0) // line separators 252 | len += (len - 1) / linemax * newline.length; 253 | return len; 254 | } 255 | 256 | /** 257 | * Encodes all bytes from the specified byte array into a newly-allocated 258 | * byte array using the {@link Base64} encoding scheme. The returned byte 259 | * array is of the length of the resulting bytes. 260 | * 261 | * @param src 262 | * the byte array to encode 263 | * @return A newly-allocated byte array containing the resulting 264 | * encoded bytes. 265 | */ 266 | public byte[] encode(byte[] src) { 267 | int len = outLength(src.length); // dst array size 268 | byte[] dst = new byte[len]; 269 | int ret = encode0(src, 0, src.length, dst); 270 | if (ret != dst.length) 271 | return Arrays.copyOf(dst, ret); 272 | return dst; 273 | } 274 | 275 | /** 276 | * Encodes all bytes from the specified byte array using the 277 | * {@link Base64} encoding scheme, writing the resulting bytes to the 278 | * given output byte array, starting at offset 0. 279 | * 280 | *
It is the responsibility of the invoker of this method to make 281 | * sure the output byte array {@code dst} has enough space for encoding 282 | * all bytes from the input byte array. No bytes will be written to the 283 | * output byte array if the output byte array is not big enough. 284 | * 285 | * @param src 286 | * the byte array to encode 287 | * @param dst 288 | * the output byte array 289 | * @return The number of bytes written to the output byte array 290 | * 291 | * @throws IllegalArgumentException if {@code dst} does not have enough 292 | * space for encoding all input bytes. 293 | */ 294 | public int encode(byte[] src, byte[] dst) { 295 | int len = outLength(src.length); // dst array size 296 | if (dst.length < len) 297 | throw new IllegalArgumentException( 298 | "Output byte array is too small for encoding all input bytes"); 299 | return encode0(src, 0, src.length, dst); 300 | } 301 | 302 | /** 303 | * Encodes the specified byte array into a String using the {@link Base64} 304 | * encoding scheme. 305 | * 306 | *
This method first encodes all input bytes into a base64 encoded 307 | * byte array and then constructs a new String by using the encoded byte 308 | * array and the {StandardCharsets#ISO_8859_1 309 | * ISO-8859-1} charset. 310 | * 311 | *
In other words, an invocation of this method has exactly the same 312 | * effect as invoking 313 | * {@code new String(encode(src), StandardCharsets.ISO_8859_1)}. 314 | * 315 | * @param src 316 | * the byte array to encode 317 | * @return A String containing the resulting Base64 encoded characters 318 | */ 319 | @SuppressWarnings("deprecation") 320 | public String encodeToString(byte[] src) { 321 | byte[] encoded = encode(src); 322 | return new String(encoded, 0, 0, encoded.length); 323 | } 324 | 325 | /** 326 | * Encodes all remaining bytes from the specified byte buffer into 327 | * a newly-allocated ByteBuffer using the {@link Base64} encoding 328 | * scheme. 329 | * 330 | * Upon return, the source buffer's position will be updated to 331 | * its limit; its limit will not have been changed. The returned 332 | * output buffer's position will be zero and its limit will be the 333 | * number of resulting encoded bytes. 334 | * 335 | * @param buffer 336 | * the source ByteBuffer to encode 337 | * @return A newly-allocated byte buffer containing the encoded bytes. 338 | */ 339 | public ByteBuffer encode(ByteBuffer buffer) { 340 | int len = outLength(buffer.remaining()); 341 | byte[] dst = new byte[len]; 342 | int ret = 0; 343 | if (buffer.hasArray()) { 344 | ret = encode0(buffer.array(), 345 | buffer.arrayOffset() + buffer.position(), 346 | buffer.arrayOffset() + buffer.limit(), 347 | dst); 348 | buffer.position(buffer.limit()); 349 | } else { 350 | byte[] src = new byte[buffer.remaining()]; 351 | buffer.get(src); 352 | ret = encode0(src, 0, src.length, dst); 353 | } 354 | if (ret != dst.length) 355 | dst = Arrays.copyOf(dst, ret); 356 | return ByteBuffer.wrap(dst); 357 | } 358 | 359 | /** 360 | * Wraps an output stream for encoding byte data using the {@link Base64} 361 | * encoding scheme. 362 | * 363 | *
It is recommended to promptly close the returned output stream after 364 | * use, during which it will flush all possible leftover bytes to the underlying 365 | * output stream. Closing the returned output stream will close the underlying 366 | * output stream. 367 | * 368 | * @param os 369 | * the output stream. 370 | * @return the output stream for encoding the byte data into the 371 | * specified Base64 encoded format 372 | */ 373 | public OutputStream wrap(OutputStream os) { 374 | Objects.requireNonNull(os); 375 | return new EncOutputStream(os, isURL ? toBase64URL : toBase64, 376 | newline, linemax, doPadding); 377 | } 378 | 379 | /** 380 | * Returns an encoder instance that encodes equivalently to this one, 381 | * but without adding any padding character at the end of the encoded 382 | * byte data. 383 | * 384 | *
The encoding scheme of this encoder instance is unaffected by 385 | * this invocation. The returned encoder instance should be used for 386 | * non-padding encoding operation. 387 | * 388 | * @return an equivalent encoder that encodes without adding any 389 | * padding character at the end 390 | */ 391 | public Encoder withoutPadding() { 392 | if (!doPadding) 393 | return this; 394 | return new Encoder(isURL, newline, linemax, false); 395 | } 396 | 397 | private int encode0(byte[] src, int off, int end, byte[] dst) { 398 | char[] base64 = isURL ? toBase64URL : toBase64; 399 | int sp = off; 400 | int slen = (end - off) / 3 * 3; 401 | int sl = off + slen; 402 | if (linemax > 0 && slen > linemax / 4 * 3) 403 | slen = linemax / 4 * 3; 404 | int dp = 0; 405 | while (sp < sl) { 406 | int sl0 = Math.min(sp + slen, sl); 407 | for (int sp0 = sp, dp0 = dp ; sp0 < sl0; ) { 408 | int bits = (src[sp0++] & 0xff) << 16 | 409 | (src[sp0++] & 0xff) << 8 | 410 | (src[sp0++] & 0xff); 411 | dst[dp0++] = (byte)base64[(bits >>> 18) & 0x3f]; 412 | dst[dp0++] = (byte)base64[(bits >>> 12) & 0x3f]; 413 | dst[dp0++] = (byte)base64[(bits >>> 6) & 0x3f]; 414 | dst[dp0++] = (byte)base64[bits & 0x3f]; 415 | } 416 | int dlen = (sl0 - sp) / 3 * 4; 417 | dp += dlen; 418 | sp = sl0; 419 | if (dlen == linemax && sp < end) { 420 | for (byte b : newline){ 421 | dst[dp++] = b; 422 | } 423 | } 424 | } 425 | if (sp < end) { // 1 or 2 leftover bytes 426 | int b0 = src[sp++] & 0xff; 427 | dst[dp++] = (byte)base64[b0 >> 2]; 428 | if (sp == end) { 429 | dst[dp++] = (byte)base64[(b0 << 4) & 0x3f]; 430 | if (doPadding) { 431 | dst[dp++] = '='; 432 | dst[dp++] = '='; 433 | } 434 | } else { 435 | int b1 = src[sp++] & 0xff; 436 | dst[dp++] = (byte)base64[(b0 << 4) & 0x3f | (b1 >> 4)]; 437 | dst[dp++] = (byte)base64[(b1 << 2) & 0x3f]; 438 | if (doPadding) { 439 | dst[dp++] = '='; 440 | } 441 | } 442 | } 443 | return dp; 444 | } 445 | } 446 | 447 | /** 448 | * This class implements a decoder for decoding byte data using the 449 | * Base64 encoding scheme as specified in RFC 4648 and RFC 2045. 450 | * 451 | *
The Base64 padding character {@code '='} is accepted and 452 | * interpreted as the end of the encoded byte data, but is not 453 | * required. So if the final unit of the encoded byte data only has 454 | * two or three Base64 characters (without the corresponding padding 455 | * character(s) padded), they are decoded as if followed by padding 456 | * character(s). If there is a padding character present in the 457 | * final unit, the correct number of padding character(s) must be 458 | * present, otherwise {@code IllegalArgumentException} ( 459 | * {@code IOException} when reading from a Base64 stream) is thrown 460 | * during decoding. 461 | * 462 | *
Instances of {@link Decoder} class are safe for use by 463 | * multiple concurrent threads. 464 | * 465 | *
Unless otherwise noted, passing a {@code null} argument to 466 | * a method of this class will cause a 467 | * {@link NullPointerException NullPointerException} to 468 | * be thrown. 469 | * 470 | * @see Encoder 471 | * @since 1.8 472 | */ 473 | public static class Decoder { 474 | 475 | private final boolean isURL; 476 | private final boolean isMIME; 477 | 478 | private Decoder(boolean isURL, boolean isMIME) { 479 | this.isURL = isURL; 480 | this.isMIME = isMIME; 481 | } 482 | 483 | /** 484 | * Lookup table for decoding unicode characters drawn from the 485 | * "Base64 Alphabet" (as specified in Table 1 of RFC 2045) into 486 | * their 6-bit positive integer equivalents. Characters that 487 | * are not in the Base64 alphabet but fall within the bounds of 488 | * the array are encoded to -1. 489 | * 490 | */ 491 | private static final int[] fromBase64 = new int[256]; 492 | static { 493 | Arrays.fill(fromBase64, -1); 494 | for (int i = 0; i < Encoder.toBase64.length; i++) 495 | fromBase64[Encoder.toBase64[i]] = i; 496 | fromBase64['='] = -2; 497 | } 498 | 499 | /** 500 | * Lookup table for decoding "URL and Filename safe Base64 Alphabet" 501 | * as specified in Table2 of the RFC 4648. 502 | */ 503 | private static final int[] fromBase64URL = new int[256]; 504 | 505 | static { 506 | Arrays.fill(fromBase64URL, -1); 507 | for (int i = 0; i < Encoder.toBase64URL.length; i++) 508 | fromBase64URL[Encoder.toBase64URL[i]] = i; 509 | fromBase64URL['='] = -2; 510 | } 511 | 512 | static final Decoder RFC4648 = new Decoder(false, false); 513 | static final Decoder RFC4648_URLSAFE = new Decoder(true, false); 514 | static final Decoder RFC2045 = new Decoder(false, true); 515 | 516 | /** 517 | * Decodes all bytes from the input byte array using the {@link Base64} 518 | * encoding scheme, writing the results into a newly-allocated output 519 | * byte array. The returned byte array is of the length of the resulting 520 | * bytes. 521 | * 522 | * @param src 523 | * the byte array to decode 524 | * 525 | * @return A newly-allocated byte array containing the decoded bytes. 526 | * 527 | * @throws IllegalArgumentException 528 | * if {@code src} is not in valid Base64 scheme 529 | */ 530 | public byte[] decode(byte[] src) { 531 | byte[] dst = new byte[outLength(src, 0, src.length)]; 532 | int ret = decode0(src, 0, src.length, dst); 533 | if (ret != dst.length) { 534 | dst = Arrays.copyOf(dst, ret); 535 | } 536 | return dst; 537 | } 538 | 539 | /** 540 | * Decodes a Base64 encoded String into a newly-allocated byte array 541 | * using the {@link Base64} encoding scheme. 542 | * 543 | *
An invocation of this method has exactly the same effect as invoking 544 | * {@code decode(src.getBytes(StandardCharsets.ISO_8859_1))} 545 | * 546 | * @param src 547 | * the string to decode 548 | * 549 | * @return A newly-allocated byte array containing the decoded bytes. 550 | * 551 | * @throws IllegalArgumentException 552 | * if {@code src} is not in valid Base64 scheme 553 | */ 554 | public byte[] decode(String src) { 555 | //return decode(src.getBytes(StandardCharsets.ISO_8859_1)); 556 | return decode(src.getBytes(Charset.forName("ISO-8859-1"))); 557 | 558 | } 559 | 560 | /** 561 | * Decodes all bytes from the input byte array using the {@link Base64} 562 | * encoding scheme, writing the results into the given output byte array, 563 | * starting at offset 0. 564 | * 565 | *
It is the responsibility of the invoker of this method to make 566 | * sure the output byte array {@code dst} has enough space for decoding 567 | * all bytes from the input byte array. No bytes will be be written to 568 | * the output byte array if the output byte array is not big enough. 569 | * 570 | *
If the input byte array is not in valid Base64 encoding scheme 571 | * then some bytes may have been written to the output byte array before 572 | * IllegalargumentException is thrown. 573 | * 574 | * @param src 575 | * the byte array to decode 576 | * @param dst 577 | * the output byte array 578 | * 579 | * @return The number of bytes written to the output byte array 580 | * 581 | * @throws IllegalArgumentException 582 | * if {@code src} is not in valid Base64 scheme, or {@code dst} 583 | * does not have enough space for decoding all input bytes. 584 | */ 585 | public int decode(byte[] src, byte[] dst) { 586 | int len = outLength(src, 0, src.length); 587 | if (dst.length < len) 588 | throw new IllegalArgumentException( 589 | "Output byte array is too small for decoding all input bytes"); 590 | return decode0(src, 0, src.length, dst); 591 | } 592 | 593 | /** 594 | * Decodes all bytes from the input byte buffer using the {@link Base64} 595 | * encoding scheme, writing the results into a newly-allocated ByteBuffer. 596 | * 597 | *
Upon return, the source buffer's position will be updated to 598 | * its limit; its limit will not have been changed. The returned 599 | * output buffer's position will be zero and its limit will be the 600 | * number of resulting decoded bytes 601 | * 602 | *
{@code IllegalArgumentException} is thrown if the input buffer 603 | * is not in valid Base64 encoding scheme. The position of the input 604 | * buffer will not be advanced in this case. 605 | * 606 | * @param buffer 607 | * the ByteBuffer to decode 608 | * 609 | * @return A newly-allocated byte buffer containing the decoded bytes 610 | * 611 | * @throws IllegalArgumentException 612 | * if {@code src} is not in valid Base64 scheme. 613 | */ 614 | public ByteBuffer decode(ByteBuffer buffer) { 615 | int pos0 = buffer.position(); 616 | try { 617 | byte[] src; 618 | int sp, sl; 619 | if (buffer.hasArray()) { 620 | src = buffer.array(); 621 | sp = buffer.arrayOffset() + buffer.position(); 622 | sl = buffer.arrayOffset() + buffer.limit(); 623 | buffer.position(buffer.limit()); 624 | } else { 625 | src = new byte[buffer.remaining()]; 626 | buffer.get(src); 627 | sp = 0; 628 | sl = src.length; 629 | } 630 | byte[] dst = new byte[outLength(src, sp, sl)]; 631 | return ByteBuffer.wrap(dst, 0, decode0(src, sp, sl, dst)); 632 | } catch (IllegalArgumentException iae) { 633 | buffer.position(pos0); 634 | throw iae; 635 | } 636 | } 637 | 638 | /** 639 | * Returns an input stream for decoding {@link Base64} encoded byte stream. 640 | * 641 | *
The {@code read} methods of the returned {@code InputStream} will 642 | * throw {@code IOException} when reading bytes that cannot be decoded. 643 | * 644 | *
Closing the returned input stream will close the underlying 645 | * input stream. 646 | * 647 | * @param is 648 | * the input stream 649 | * 650 | * @return the input stream for decoding the specified Base64 encoded 651 | * byte stream 652 | */ 653 | public InputStream wrap(InputStream is) { 654 | Objects.requireNonNull(is); 655 | return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME); 656 | } 657 | 658 | private int outLength(byte[] src, int sp, int sl) { 659 | int[] base64 = isURL ? fromBase64URL : fromBase64; 660 | int paddings = 0; 661 | int len = sl - sp; 662 | if (len == 0) 663 | return 0; 664 | if (len < 2) { 665 | if (isMIME && base64[0] == -1) 666 | return 0; 667 | throw new IllegalArgumentException( 668 | "Input byte[] should at least have 2 bytes for base64 bytes"); 669 | } 670 | if (isMIME) { 671 | // scan all bytes to fill out all non-alphabet. a performance 672 | // trade-off of pre-scan or Arrays.copyOf 673 | int n = 0; 674 | while (sp < sl) { 675 | int b = src[sp++] & 0xff; 676 | if (b == '=') { 677 | len -= (sl - sp + 1); 678 | break; 679 | } 680 | if ((b = base64[b]) == -1) 681 | n++; 682 | } 683 | len -= n; 684 | } else { 685 | if (src[sl - 1] == '=') { 686 | paddings++; 687 | if (src[sl - 2] == '=') 688 | paddings++; 689 | } 690 | } 691 | if (paddings == 0 && (len & 0x3) != 0) 692 | paddings = 4 - (len & 0x3); 693 | return 3 * ((len + 3) / 4) - paddings; 694 | } 695 | 696 | private int decode0(byte[] src, int sp, int sl, byte[] dst) { 697 | int[] base64 = isURL ? fromBase64URL : fromBase64; 698 | int dp = 0; 699 | int bits = 0; 700 | int shiftto = 18; // pos of first byte of 4-byte atom 701 | while (sp < sl) { 702 | int b = src[sp++] & 0xff; 703 | if ((b = base64[b]) < 0) { 704 | if (b == -2) { // padding byte '=' 705 | // = shiftto==18 unnecessary padding 706 | // x= shiftto==12 a dangling single x 707 | // x to be handled together with non-padding case 708 | // xx= shiftto==6&&sp==sl missing last = 709 | // xx=y shiftto==6 last is not = 710 | if (shiftto == 6 && (sp == sl || src[sp++] != '=') || 711 | shiftto == 18) { 712 | throw new IllegalArgumentException( 713 | "Input byte array has wrong 4-byte ending unit"); 714 | } 715 | break; 716 | } 717 | if (isMIME) // skip if for rfc2045 718 | continue; 719 | else 720 | throw new IllegalArgumentException( 721 | "Illegal base64 character " + 722 | Integer.toString(src[sp - 1], 16)); 723 | } 724 | bits |= (b << shiftto); 725 | shiftto -= 6; 726 | if (shiftto < 0) { 727 | dst[dp++] = (byte)(bits >> 16); 728 | dst[dp++] = (byte)(bits >> 8); 729 | dst[dp++] = (byte)(bits); 730 | shiftto = 18; 731 | bits = 0; 732 | } 733 | } 734 | // reached end of byte array or hit padding '=' characters. 735 | if (shiftto == 6) { 736 | dst[dp++] = (byte)(bits >> 16); 737 | } else if (shiftto == 0) { 738 | dst[dp++] = (byte)(bits >> 16); 739 | dst[dp++] = (byte)(bits >> 8); 740 | } else if (shiftto == 12) { 741 | // dangling single "x", incorrectly encoded. 742 | throw new IllegalArgumentException( 743 | "Last unit does not have enough valid bits"); 744 | } 745 | // anything left is invalid, if is not MIME. 746 | // if MIME, ignore all non-base64 character 747 | while (sp < sl) { 748 | if (isMIME && base64[src[sp++]] < 0) 749 | continue; 750 | throw new IllegalArgumentException( 751 | "Input byte array has incorrect ending byte at " + sp); 752 | } 753 | return dp; 754 | } 755 | } 756 | 757 | /* 758 | * An output stream for encoding bytes into the Base64. 759 | */ 760 | private static class EncOutputStream extends FilterOutputStream { 761 | 762 | private int leftover = 0; 763 | private int b0, b1, b2; 764 | private boolean closed = false; 765 | 766 | private final char[] base64; // byte->base64 mapping 767 | private final byte[] newline; // line separator, if needed 768 | private final int linemax; 769 | private final boolean doPadding;// whether or not to pad 770 | private int linepos = 0; 771 | 772 | EncOutputStream(OutputStream os, char[] base64, 773 | byte[] newline, int linemax, boolean doPadding) { 774 | super(os); 775 | this.base64 = base64; 776 | this.newline = newline; 777 | this.linemax = linemax; 778 | this.doPadding = doPadding; 779 | } 780 | 781 | @Override 782 | public void write(int b) throws IOException { 783 | byte[] buf = new byte[1]; 784 | buf[0] = (byte)(b & 0xff); 785 | write(buf, 0, 1); 786 | } 787 | 788 | private void checkNewline() throws IOException { 789 | if (linepos == linemax) { 790 | out.write(newline); 791 | linepos = 0; 792 | } 793 | } 794 | 795 | @Override 796 | public void write(byte[] b, int off, int len) throws IOException { 797 | if (closed) 798 | throw new IOException("Stream is closed"); 799 | if (off < 0 || len < 0 || off + len > b.length) 800 | throw new ArrayIndexOutOfBoundsException(); 801 | if (len == 0) 802 | return; 803 | if (leftover != 0) { 804 | if (leftover == 1) { 805 | b1 = b[off++] & 0xff; 806 | len--; 807 | if (len == 0) { 808 | leftover++; 809 | return; 810 | } 811 | } 812 | b2 = b[off++] & 0xff; 813 | len--; 814 | checkNewline(); 815 | out.write(base64[b0 >> 2]); 816 | out.write(base64[(b0 << 4) & 0x3f | (b1 >> 4)]); 817 | out.write(base64[(b1 << 2) & 0x3f | (b2 >> 6)]); 818 | out.write(base64[b2 & 0x3f]); 819 | linepos += 4; 820 | } 821 | int nBits24 = len / 3; 822 | leftover = len - (nBits24 * 3); 823 | while (nBits24-- > 0) { 824 | checkNewline(); 825 | int bits = (b[off++] & 0xff) << 16 | 826 | (b[off++] & 0xff) << 8 | 827 | (b[off++] & 0xff); 828 | out.write(base64[(bits >>> 18) & 0x3f]); 829 | out.write(base64[(bits >>> 12) & 0x3f]); 830 | out.write(base64[(bits >>> 6) & 0x3f]); 831 | out.write(base64[bits & 0x3f]); 832 | linepos += 4; 833 | } 834 | if (leftover == 1) { 835 | b0 = b[off++] & 0xff; 836 | } else if (leftover == 2) { 837 | b0 = b[off++] & 0xff; 838 | b1 = b[off++] & 0xff; 839 | } 840 | } 841 | 842 | @Override 843 | public void close() throws IOException { 844 | if (!closed) { 845 | closed = true; 846 | if (leftover == 1) { 847 | checkNewline(); 848 | out.write(base64[b0 >> 2]); 849 | out.write(base64[(b0 << 4) & 0x3f]); 850 | if (doPadding) { 851 | out.write('='); 852 | out.write('='); 853 | } 854 | } else if (leftover == 2) { 855 | checkNewline(); 856 | out.write(base64[b0 >> 2]); 857 | out.write(base64[(b0 << 4) & 0x3f | (b1 >> 4)]); 858 | out.write(base64[(b1 << 2) & 0x3f]); 859 | if (doPadding) { 860 | out.write('='); 861 | } 862 | } 863 | leftover = 0; 864 | out.close(); 865 | } 866 | } 867 | } 868 | 869 | /* 870 | * An input stream for decoding Base64 bytes 871 | */ 872 | private static class DecInputStream extends InputStream { 873 | 874 | private final InputStream is; 875 | private final boolean isMIME; 876 | private final int[] base64; // base64 -> byte mapping 877 | private int bits = 0; // 24-bit buffer for decoding 878 | private int nextin = 18; // next available "off" in "bits" for input; 879 | // -> 18, 12, 6, 0 880 | private int nextout = -8; // next available "off" in "bits" for output; 881 | // -> 8, 0, -8 (no byte for output) 882 | private boolean eof = false; 883 | private boolean closed = false; 884 | 885 | DecInputStream(InputStream is, int[] base64, boolean isMIME) { 886 | this.is = is; 887 | this.base64 = base64; 888 | this.isMIME = isMIME; 889 | } 890 | 891 | private byte[] sbBuf = new byte[1]; 892 | 893 | @Override 894 | public int read() throws IOException { 895 | return read(sbBuf, 0, 1) == -1 ? -1 : sbBuf[0] & 0xff; 896 | } 897 | 898 | @Override 899 | public int read(byte[] b, int off, int len) throws IOException { 900 | if (closed) 901 | throw new IOException("Stream is closed"); 902 | if (eof && nextout < 0) // eof and no leftover 903 | return -1; 904 | if (off < 0 || len < 0 || len > b.length - off) 905 | throw new IndexOutOfBoundsException(); 906 | int oldOff = off; 907 | if (nextout >= 0) { // leftover output byte(s) in bits buf 908 | do { 909 | if (len == 0) 910 | return off - oldOff; 911 | b[off++] = (byte)(bits >> nextout); 912 | len--; 913 | nextout -= 8; 914 | } while (nextout >= 0); 915 | bits = 0; 916 | } 917 | while (len > 0) { 918 | int v = is.read(); 919 | if (v == -1) { 920 | eof = true; 921 | if (nextin != 18) { 922 | if (nextin == 12) 923 | throw new IOException("Base64 stream has one un-decoded dangling byte."); 924 | // treat ending xx/xxx without padding character legal. 925 | // same logic as v == '=' below 926 | b[off++] = (byte)(bits >> (16)); 927 | len--; 928 | if (nextin == 0) { // only one padding byte 929 | if (len == 0) { // no enough output space 930 | bits >>= 8; // shift to lowest byte 931 | nextout = 0; 932 | } else { 933 | b[off++] = (byte) (bits >> 8); 934 | } 935 | } 936 | } 937 | if (off == oldOff) 938 | return -1; 939 | else 940 | return off - oldOff; 941 | } 942 | if (v == '=') { // padding byte(s) 943 | // = shiftto==18 unnecessary padding 944 | // x= shiftto==12 dangling x, invalid unit 945 | // xx= shiftto==6 && missing last '=' 946 | // xx=y or last is not '=' 947 | if (nextin == 18 || nextin == 12 || 948 | nextin == 6 && is.read() != '=') { 949 | throw new IOException("Illegal base64 ending sequence:" + nextin); 950 | } 951 | b[off++] = (byte)(bits >> (16)); 952 | len--; 953 | if (nextin == 0) { // only one padding byte 954 | if (len == 0) { // no enough output space 955 | bits >>= 8; // shift to lowest byte 956 | nextout = 0; 957 | } else { 958 | b[off++] = (byte) (bits >> 8); 959 | } 960 | } 961 | eof = true; 962 | break; 963 | } 964 | if ((v = base64[v]) == -1) { 965 | if (isMIME) // skip if for rfc2045 966 | continue; 967 | else 968 | throw new IOException("Illegal base64 character " + 969 | Integer.toString(v, 16)); 970 | } 971 | bits |= (v << nextin); 972 | if (nextin == 0) { 973 | nextin = 18; // clear for next 974 | nextout = 16; 975 | while (nextout >= 0) { 976 | b[off++] = (byte)(bits >> nextout); 977 | len--; 978 | nextout -= 8; 979 | if (len == 0 && nextout >= 0) { // don't clean "bits" 980 | return off - oldOff; 981 | } 982 | } 983 | bits = 0; 984 | } else { 985 | nextin -= 6; 986 | } 987 | } 988 | return off - oldOff; 989 | } 990 | 991 | @Override 992 | public int available() throws IOException { 993 | if (closed) 994 | throw new IOException("Stream is closed"); 995 | return is.available(); // TBD: 996 | } 997 | 998 | @Override 999 | public void close() throws IOException { 1000 | if (!closed) { 1001 | closed = true; 1002 | is.close(); 1003 | } 1004 | } 1005 | } 1006 | } 1007 | -------------------------------------------------------------------------------- /simple-encryptor-lib/src/main/java/com/mobapphome/simpleencryptorlib/Constants.java: -------------------------------------------------------------------------------- 1 | package com.mobapphome.simpleencryptorlib; 2 | 3 | /** 4 | * Created by settar on 2/6/17. 5 | */ 6 | 7 | public class Constants { 8 | public static final String MAH_ENCHRIPTOR_GITHUB_LINK = "https://github.com/hummatli/MAHEncryptorLib"; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /simple-encryptor-lib/src/main/java/com/mobapphome/simpleencryptorlib/SimpleEncryptor.java: -------------------------------------------------------------------------------- 1 | package com.mobapphome.simpleencryptorlib; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.security.InvalidKeyException; 5 | import java.security.NoSuchAlgorithmException; 6 | import java.security.spec.InvalidKeySpecException; 7 | 8 | import javax.crypto.BadPaddingException; 9 | import javax.crypto.Cipher; 10 | import javax.crypto.IllegalBlockSizeException; 11 | import javax.crypto.NoSuchPaddingException; 12 | import javax.crypto.SecretKey; 13 | import javax.crypto.SecretKeyFactory; 14 | import javax.crypto.spec.DESKeySpec; 15 | 16 | /** 17 | * This is SimpleEncryptor class. Main class of MAHEncryptorLib. 18 | * Created by Sattar Hummatli on 8/5/16. 19 | */ 20 | 21 | public class SimpleEncryptor { 22 | 23 | private SecretKey key; 24 | Base64.Encoder base64encoder; 25 | Base64.Decoder base64decoder; 26 | 27 | 28 | private SimpleEncryptor(String yourSecretKeyPhrase) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException { 29 | DESKeySpec keySpec = new DESKeySpec(yourSecretKeyPhrase.getBytes("UTF8"), 10); 30 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 31 | key = keyFactory.generateSecret(keySpec); 32 | base64encoder = Base64.getEncoder(); 33 | base64decoder = Base64.getDecoder(); 34 | } 35 | 36 | /** 37 | * Initializer of SimpleEncryptor 38 | * @param yourSecretKeyPhrase 39 | * @return SimpleEncryptor object or throughs exception 40 | * @throws InvalidKeySpecException 41 | * @throws NoSuchAlgorithmException 42 | * @throws InvalidKeyException 43 | * @throws UnsupportedEncodingException 44 | */ 45 | public static SimpleEncryptor newInstance(String yourSecretKeyPhrase) throws InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException { 46 | return new SimpleEncryptor(yourSecretKeyPhrase); 47 | } 48 | 49 | /** 50 | * Initializer of SimpleEncryptor 51 | * @param yourSecretKeyPhrase 52 | * @return SimpleEncryptor object or null if throughs exception 53 | */ 54 | public static SimpleEncryptor newInstanceOrRetunNull(String yourSecretKeyPhrase){ 55 | try { 56 | return new SimpleEncryptor(yourSecretKeyPhrase); 57 | } catch (Exception e) { 58 | e.printStackTrace(); 59 | return null; 60 | } 61 | } 62 | 63 | 64 | /** 65 | * Encode method 66 | * @param plainText 67 | * @return Encoded string 68 | * @throws UnsupportedEncodingException 69 | * @throws NoSuchPaddingException 70 | * @throws NoSuchAlgorithmException 71 | * @throws InvalidKeyException 72 | * @throws BadPaddingException 73 | * @throws IllegalBlockSizeException 74 | */ 75 | public String encode(String plainText) throws UnsupportedEncodingException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { 76 | 77 | // ENCODE plainText String 78 | byte[] cleartext = plainText.getBytes("UTF8"); 79 | 80 | Cipher cipher = Cipher.getInstance("DES"); // cipher is not thread safe 81 | cipher.init(Cipher.ENCRYPT_MODE, key); 82 | return base64encoder.encodeToString(cipher.doFinal(cleartext)); 83 | // now you can store it 84 | } 85 | 86 | /** 87 | * Encode method 88 | * @param plainText 89 | * @return Encoded string or null if throughs exception 90 | */ 91 | public String encodeOrReturnNull(String plainText) { 92 | try { 93 | return encode(plainText); 94 | } catch (Exception e) { 95 | e.printStackTrace(); 96 | return null; 97 | } 98 | } 99 | 100 | /** 101 | * Decode method 102 | * @param encryptedText 103 | * @return Decoded string 104 | * @throws NoSuchPaddingException 105 | * @throws NoSuchAlgorithmException 106 | * @throws InvalidKeyException 107 | * @throws BadPaddingException 108 | * @throws IllegalBlockSizeException 109 | * @throws UnsupportedEncodingException 110 | */ 111 | public String decode(String encryptedText) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException { 112 | 113 | // DECODE encryptedText String 114 | byte[] encrypedPwdBytes = base64decoder.decode(encryptedText); 115 | 116 | Cipher cipher = Cipher.getInstance("DES");// cipher is not thread safe 117 | cipher.init(Cipher.DECRYPT_MODE, key); 118 | return new String((cipher.doFinal(encrypedPwdBytes)), "UTF-8"); 119 | } 120 | 121 | /** 122 | * Decode method 123 | * @param encryptedText 124 | * @return Decoded string or null if throughs exception 125 | */ 126 | public String decodeOrReturnNull(String encryptedText) { 127 | try { 128 | return decode(encryptedText); 129 | } catch (Exception e) { 130 | e.printStackTrace(); 131 | return null; 132 | } 133 | } 134 | } --------------------------------------------------------------------------------