├── release
└── jealoussky-release.aar
├── src
├── main
│ ├── res
│ │ └── values
│ │ │ └── strings.xml
│ ├── AndroidManifest.xml
│ └── java
│ │ └── com
│ │ └── github
│ │ └── cirorizzo
│ │ └── JealousSky.java
├── test
│ └── java
│ │ └── com
│ │ └── github
│ │ └── cirorizzo
│ │ └── ExampleUnitTest.java
└── androidTest
│ └── java
│ └── com
│ └── github
│ └── cirorizzo
│ └── ApplicationTest.java
├── static
└── ic_jealoussky_logo.png
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .travis.yml
├── proguard-rules.pro
├── gradle.properties
├── gradlew.bat
├── README.md
└── gradlew
/release/jealoussky-release.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cirorizzo/JealousSky/HEAD/release/jealoussky-release.aar
--------------------------------------------------------------------------------
/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | JealousSky
3 |
4 |
--------------------------------------------------------------------------------
/static/ic_jealoussky_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cirorizzo/JealousSky/HEAD/static/ic_jealoussky_logo.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cirorizzo/JealousSky/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Nov 10 10:53:48 GMT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/test/java/com/github/cirorizzo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.github.cirorizzo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/src/androidTest/java/com/github/cirorizzo/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.github.cirorizzo;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | script: "./gradlew build"
3 | android:
4 | components:
5 | - platform-tools
6 | - tools
7 |
8 | # The BuildTools version used by your project
9 | - build-tools-23.0.2
10 |
11 | # The SDK version used to compile your project
12 | - android-23
13 |
14 | # Additional components
15 | - extra-google-google_play_services
16 | - extra-google-m2repository
17 | - extra-android-m2repository
18 |
19 | jdk:
20 | - oraclejdk8
21 | before_install:
22 | - chmod +x gradlew
23 | addons:
24 | apt:
25 | packages:
26 | - oracle-java8-installer
27 |
--------------------------------------------------------------------------------
/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/cirorizzo/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JealousSky
2 |
3 | [](https://www.android.com/)
4 | [](http://developer.android.com/about/versions/android-4.1.html)
5 | [](http://docs.oracle.com/javase/tutorial/java/nutsandbolts/index.html)
6 | [](http://www.gnu.org/licenses/gpl-3.0-standalone.html)
7 | [](https://bintray.com/)
8 | [](http://search.maven.org/)
9 | [](https://android-arsenal.com/details/1/2774)
10 |
11 | ##Encryption/Decryption Library for Android
12 |
13 |
14 | JealousSky is an efficient library to encrypt and decrypt data for Android.
15 |
16 | With JealousSky is possible to decrypt simple String or even image files as return a Bitmap.
17 |
18 | The project is still in progress and any contribuition is accepted.
19 |
20 | At the moment Jealous Sky support AES 128bit encryption.
21 |
22 |
23 | 
24 |
25 |
26 | Download
27 | --------
28 | You can download a jar from GitHub's [releases page][1].
29 |
30 | Or use Gradle:
31 |
32 | ```gradle
33 | repositories {
34 | jcenter()
35 | mavenCentral()
36 | }
37 |
38 | dependencies {
39 | compile 'com.github.cirorizzo:jealoussky:0.3'
40 | }
41 | ```
42 |
43 | Or Maven:
44 |
45 | ```xml
46 |
47 | com.github.cirorizzo
48 | jealoussky
49 | 0.3
50 |
51 | ```
52 |
53 | How do I use JealousSky?
54 | -------------------
55 | Checkout the [GitHub wiki][2] for pages on a variety of topics.
56 |
57 | Simple use cases will look something like this:
58 |
59 | ```java
60 | // For a image file decryption:
61 |
62 | JealousSky jealousSky = JealousSky.getInstance();
63 |
64 | jealousSky.initialize(
65 | "longestPasswordEverCreatedInAllTheUniverseOrMore",
66 | "FFD7BADF2FBB1999");
67 |
68 | InputStream isEncrypted = new FileInputStream(new File(epic_fail_image.png.enc));
69 |
70 | ImageView imageViewDecrypted = (ImageView) findViewById(R.id.imageView);
71 |
72 | // Decrypting the InputStream
73 | imageViewDecrypted.setImageBitmap(jealousSky.decryptToBitmap(isEncrypted));
74 |
75 | // Or Decrypting from the Assests
76 | imageViewDecrypted.setImageBitmap(jealousSky.decryptToBitmap(getAssets().open("spider-symbol.png.enc")));
77 | ```
78 |
79 | Android SDK Version
80 | -------------------
81 | JealousSky requires a minimum SDK version of 16.
82 |
83 | License
84 | -------
85 | GNU General Public License 3.0. See the [LICENSE][3] file for details.
86 |
87 | Status
88 | ------
89 | [*Version 0.2*] is a stable public pre-release library.
90 | Comments/bugs/questions/pull requests welcome!
91 |
92 | Getting Help
93 | ------------
94 | To report a specific problem or feature request, [open a new issue on Github][4]. For questions, suggestions, or
95 | anything else, join or email [JealousSky's discussion group][6]
96 |
97 | Author
98 | ------
99 | Ciro Rizzo - @JackRix
100 |
101 |
102 |
103 | [1]: https://github.com/cirorizzo/jealoussky/releases
104 | [2]: https://github.com/cirorizzo/JealousSky/wiki
105 | [3]: http://www.gnu.org/licenses/gpl-3.0-standalone.html
106 | [4]: https://github.com/cirorizzo/jealoussky/issues/new?body=**JealousSky%20Version/Integration%20library%20%28if%20any%29**%3A%0A**Device/Android%20Version**%3A%0A**Issue%20details/Repro%20steps/Use%20case%20background**%3A%0A%0A**JealousSky%20initialize%20lines**%3A%0A%60%60%60java%0AJealousSky%20jealousSky%20=%20JealousSky.getInstance%28%29%3B%0AjealousSky.initialize%28...%29%3B%0AjealousSky.encrypt%28...%29%3B%0AjealousSky.decrypt%28...%29%3B%0A%60%60%60%0A%0A**Layout%20XML**%3A%0A%60%60%60xml%0A%3C...Layout%3E%0A%20%20%20%20%3CImageView%20android%3AscaleType%3D%22...%22%20...%20/%3E%0A%3C/..Layout%3E%0A%60%60%60%0A%0A**Stack%20trace%20/%20LogCat**%3A%0A%60%60%60ruby%0Apaste%20stack%20trace%20here%0A%60%60%60
107 | [5]: https://developers.google.com/open-source/cla/individual
108 | [6]: https://groups.google.com/d/forum/jealoussky-library
109 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/src/main/java/com/github/cirorizzo/JealousSky.java:
--------------------------------------------------------------------------------
1 | package com.github.cirorizzo;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.util.Base64;
6 |
7 | import java.io.BufferedInputStream;
8 | import java.io.ByteArrayInputStream;
9 | import java.io.ByteArrayOutputStream;
10 | import java.io.File;
11 | import java.io.FileInputStream;
12 | import java.io.FileOutputStream;
13 | import java.io.IOException;
14 | import java.io.InputStream;
15 | import java.io.UnsupportedEncodingException;
16 | import java.security.InvalidAlgorithmParameterException;
17 | import java.security.InvalidKeyException;
18 | import java.security.MessageDigest;
19 | import java.security.NoSuchAlgorithmException;
20 | import java.security.SecureRandom;
21 | import java.security.spec.InvalidKeySpecException;
22 | import java.security.spec.KeySpec;
23 |
24 | import javax.crypto.BadPaddingException;
25 | import javax.crypto.Cipher;
26 | import javax.crypto.CipherInputStream;
27 | import javax.crypto.CipherOutputStream;
28 | import javax.crypto.IllegalBlockSizeException;
29 | import javax.crypto.NoSuchPaddingException;
30 | import javax.crypto.SecretKey;
31 | import javax.crypto.SecretKeyFactory;
32 | import javax.crypto.spec.IvParameterSpec;
33 | import javax.crypto.spec.PBEKeySpec;
34 | import javax.crypto.spec.SecretKeySpec;
35 |
36 | public class JealousSky {
37 | private final String TAG = JealousSky.class.getSimpleName();
38 |
39 | private static JealousSky instance = null;
40 |
41 | private final String INIT_ILLEGAL_ARG_KEY = "Invalid Key Argument";
42 | private final String INIT_ILLEGAL_ARG_SALT = "Invalid Salt Argument";
43 |
44 | private final int DEFAULT_ITERATIONS = 1024;
45 | private final int DEFAULT_KEY_LENGTH = 128;
46 |
47 | private final String SECURE_RANDOM_ALGORITHM = "SHA1PRNG";
48 |
49 | private final String SECRETKEY_DIGEST_SHA1 = "SHA1";
50 |
51 | private final String SECRETKEY_ALGORITHM_SHA1 = "PBKDF2WithHmacSHA1";
52 | private final String SECRETKEY_ALGORITHM_CBC = "PBEWithSHA256And256BitAES-CBC-BC";
53 | private final String ENCRYPTION_ALGORITHM_PCKS5 = "AES/CBC/PKCS5Padding";
54 | private final String ENCRYPTION_ALGORITHM_NOPAD = "AES/CBC/NoPadding";
55 |
56 | private String key;
57 | private byte[] salt;
58 | private byte[] iv;
59 |
60 | private SecureRandom secureRandom;
61 | private IvParameterSpec ivParameterSpec;
62 |
63 | protected JealousSky() {
64 | // Exists only to avoid instantiation.
65 | }
66 |
67 | public static JealousSky getInstance() {
68 | if (instance == null) {
69 | instance = new JealousSky();
70 | }
71 | return instance;
72 | }
73 |
74 | /**
75 | * Initialization for SecureRandom, IVParamSpec, Key (Password) and Salt
76 | * @param key Password used for Encryption/Decryption
77 | * @param salt Salt used Password derivation
78 | * @throws IllegalArgumentException
79 | * @throws NoSuchAlgorithmException
80 | */
81 | public void initialize(String key, String salt) throws IllegalArgumentException, NoSuchAlgorithmException {
82 |
83 | if (!isValidArgKey(key)) {
84 | throw new IllegalArgumentException(INIT_ILLEGAL_ARG_KEY);
85 | } else {
86 | this.key = key;
87 | }
88 | if (!isValidArg(salt)) {
89 | throw new IllegalArgumentException(INIT_ILLEGAL_ARG_SALT);
90 | } else {
91 | this.salt = hexStringToByteArray(salt);
92 | }
93 | this.iv = new byte[16];
94 |
95 | secureRandom = SecureRandom.getInstance(SECURE_RANDOM_ALGORITHM);
96 | ivParameterSpec = new IvParameterSpec(this.iv);
97 | }
98 |
99 | /**
100 | * Encryption Method
101 | * @param clearString String to Encrypt
102 | * @return Byte Array of Encrypted String
103 | * @throws IOException
104 | * @throws NoSuchAlgorithmException
105 | * @throws NoSuchPaddingException
106 | * @throws InvalidAlgorithmParameterException
107 | * @throws InvalidKeyException
108 | * @throws InvalidKeySpecException
109 | * @throws BadPaddingException
110 | * @throws IllegalBlockSizeException
111 | */
112 | public byte[] encrypt(String clearString)
113 | throws IOException, NoSuchAlgorithmException, NoSuchPaddingException,
114 | InvalidAlgorithmParameterException, InvalidKeyException, InvalidKeySpecException,
115 | BadPaddingException, IllegalBlockSizeException {
116 |
117 | if ((clearString == null) || (clearString.isEmpty())) {
118 | return null;
119 | }
120 |
121 | Cipher cipher = getCipher(Cipher.ENCRYPT_MODE);
122 |
123 | return cipher.doFinal(clearString.getBytes("UTF8"));
124 | }
125 |
126 | /**
127 | * Encryption Method Wrapper
128 | * @param clearString String to Encrypt
129 | * @return Encrypted String
130 | * @throws NoSuchPaddingException
131 | * @throws InvalidKeyException
132 | * @throws NoSuchAlgorithmException
133 | * @throws IOException
134 | * @throws BadPaddingException
135 | * @throws IllegalBlockSizeException
136 | * @throws InvalidAlgorithmParameterException
137 | * @throws InvalidKeySpecException
138 | */
139 | public String encryptToString(String clearString) throws NoSuchPaddingException,
140 | InvalidKeyException, NoSuchAlgorithmException, IOException, BadPaddingException,
141 | IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeySpecException {
142 |
143 | return Base64.encodeToString(encrypt(clearString), Base64.DEFAULT);
144 | }
145 |
146 | /**
147 | * Encryption Method Wrapper
148 | * @param fileInput InputStream of File to Encrypt
149 | * @return Byte Array of Encryped InputStream
150 | * @throws IOException
151 | * @throws NoSuchAlgorithmException
152 | * @throws NoSuchPaddingException
153 | * @throws InvalidAlgorithmParameterException
154 | * @throws InvalidKeyException
155 | * @throws InvalidKeySpecException
156 | * @throws BadPaddingException
157 | * @throws IllegalBlockSizeException
158 | */
159 | public byte[] encrypt(InputStream fileInput)
160 | throws IOException, NoSuchAlgorithmException, NoSuchPaddingException,
161 | InvalidAlgorithmParameterException, InvalidKeyException, InvalidKeySpecException,
162 | BadPaddingException, IllegalBlockSizeException {
163 |
164 | Cipher cipher = getCipher(Cipher.ENCRYPT_MODE);
165 |
166 | return getEncryptInputStream(fileInput, cipher);
167 | }
168 |
169 | /**
170 | * Encryption Method Wrapper
171 | * @param fileInput InputStream of File to Encrypt
172 | * @param fileNameOutput File name of Encrypted File
173 | * @return Encrypted File
174 | * @throws NoSuchPaddingException
175 | * @throws InvalidKeyException
176 | * @throws NoSuchAlgorithmException
177 | * @throws IOException
178 | * @throws BadPaddingException
179 | * @throws IllegalBlockSizeException
180 | * @throws InvalidAlgorithmParameterException
181 | * @throws InvalidKeySpecException
182 | */
183 | public File encryptToFile(InputStream fileInput, String fileNameOutput)
184 | throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException,
185 | IOException, BadPaddingException, IllegalBlockSizeException,
186 | InvalidAlgorithmParameterException, InvalidKeySpecException {
187 |
188 | if ((fileNameOutput == null) || (fileNameOutput.isEmpty())) {
189 | return null;
190 | }
191 |
192 | File fileOutput = new File(fileNameOutput);
193 | FileOutputStream out = new FileOutputStream(fileOutput);
194 |
195 | byte[] encrypted = encrypt(fileInput);
196 |
197 | out.write(encrypted);
198 |
199 | out.flush();
200 | out.close();
201 |
202 | return fileOutput;
203 | }
204 |
205 | /**
206 | * Decryption Method
207 | * @param encryptedString String to Decrypt
208 | * @return Byte Array of Decrypted String
209 | * @throws NoSuchAlgorithmException
210 | * @throws InvalidKeySpecException
211 | * @throws IOException
212 | * @throws NoSuchPaddingException
213 | * @throws InvalidAlgorithmParameterException
214 | * @throws InvalidKeyException
215 | * @throws BadPaddingException
216 | * @throws IllegalBlockSizeException
217 | */
218 | public byte[] decrypt(String encryptedString) throws NoSuchAlgorithmException,
219 | InvalidKeySpecException, IOException, NoSuchPaddingException,
220 | InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException,
221 | IllegalBlockSizeException {
222 |
223 | if ((encryptedString == null) || (encryptedString.isEmpty())) {
224 | return null;
225 | }
226 |
227 | Cipher cipher = getCipher(Cipher.DECRYPT_MODE);
228 |
229 | return cipher.doFinal(Base64.decode(encryptedString, Base64.DEFAULT));
230 | }
231 |
232 | /**
233 | * Decryption Method Wrapper
234 | * @param encryptedString String to Decrypt
235 | * @return Decrypted String
236 | * @throws NoSuchPaddingException
237 | * @throws InvalidKeyException
238 | * @throws NoSuchAlgorithmException
239 | * @throws IOException
240 | * @throws BadPaddingException
241 | * @throws IllegalBlockSizeException
242 | * @throws InvalidAlgorithmParameterException
243 | * @throws InvalidKeySpecException
244 | */
245 | public String decryptToString(String encryptedString) throws NoSuchPaddingException,
246 | InvalidKeyException, NoSuchAlgorithmException, IOException, BadPaddingException,
247 | IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeySpecException {
248 |
249 | return new String(decrypt(encryptedString));
250 | }
251 |
252 | /**
253 | * Decryption Method Wrapper
254 | * @param fileInput InputStream to Decrypt
255 | * @return Byte Array of Decrypted InputStream
256 | * @throws NoSuchAlgorithmException
257 | * @throws InvalidKeySpecException
258 | * @throws IOException
259 | * @throws NoSuchPaddingException
260 | * @throws InvalidAlgorithmParameterException
261 | * @throws InvalidKeyException
262 | * @throws BadPaddingException
263 | * @throws IllegalBlockSizeException
264 | */
265 | public byte[] decrypt(InputStream fileInput) throws NoSuchAlgorithmException,
266 | InvalidKeySpecException, IOException, NoSuchPaddingException,
267 | InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException,
268 | IllegalBlockSizeException {
269 |
270 | if ((fileInput == null) || (fileInput.available() == 0)) {
271 | return null;
272 | }
273 |
274 | Cipher cipher = getCipher(Cipher.DECRYPT_MODE);
275 |
276 | return getDecryptFromCipherInputStream(fileInput, cipher);
277 | }
278 |
279 | /**
280 | * Decryption Method Wrapper
281 | * @param fileInput InputStream to Decrypt
282 | * @param fileNameOutput File name of Decrypted File
283 | * @return Decrypted File
284 | * @throws NoSuchPaddingException
285 | * @throws InvalidKeyException
286 | * @throws NoSuchAlgorithmException
287 | * @throws IOException
288 | * @throws BadPaddingException
289 | * @throws IllegalBlockSizeException
290 | * @throws InvalidAlgorithmParameterException
291 | * @throws InvalidKeySpecException
292 | */
293 | public File decryptToFile(InputStream fileInput, String fileNameOutput)
294 | throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException,
295 | IOException, BadPaddingException, IllegalBlockSizeException,
296 | InvalidAlgorithmParameterException, InvalidKeySpecException {
297 |
298 | if ((fileNameOutput == null) || (fileNameOutput.isEmpty())) {
299 | return null;
300 | }
301 |
302 | File fileOutput = new File(fileNameOutput);
303 | FileOutputStream outdec = new FileOutputStream(fileOutput);
304 |
305 | byte[] decryptedStream = decrypt(fileInput);
306 | outdec.write(decryptedStream);
307 |
308 | outdec.flush();
309 | outdec.close();
310 |
311 | return fileOutput;
312 | }
313 |
314 | /**
315 | * Decryption Method Wrapper
316 | * @param fileInput InputStream to Decrypt
317 | * @return Bitmap of Decrypted InputStream
318 | * @throws NoSuchPaddingException
319 | * @throws InvalidKeyException
320 | * @throws NoSuchAlgorithmException
321 | * @throws IOException
322 | * @throws BadPaddingException
323 | * @throws IllegalBlockSizeException
324 | * @throws InvalidAlgorithmParameterException
325 | * @throws InvalidKeySpecException
326 | */
327 | public Bitmap decryptToBitmap(InputStream fileInput)
328 | throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException,
329 | IOException, BadPaddingException, IllegalBlockSizeException,
330 | InvalidAlgorithmParameterException, InvalidKeySpecException {
331 |
332 | return BitmapFactory.decodeStream(new ByteArrayInputStream(decrypt(fileInput)));
333 | }
334 |
335 |
336 | //----------------------------------------------------------------------------------------------
337 |
338 | private SecretKey getSecretKey(String secretKeyAlgorithm) throws NoSuchAlgorithmException,
339 | UnsupportedEncodingException, InvalidKeySpecException {
340 |
341 | SecretKeyFactory factory = SecretKeyFactory.getInstance(secretKeyAlgorithm);
342 | KeySpec spec = new PBEKeySpec(hashTheKey(key), salt, DEFAULT_ITERATIONS, DEFAULT_KEY_LENGTH);
343 | SecretKey tmp = factory.generateSecret(spec);
344 |
345 | return new SecretKeySpec(tmp.getEncoded(), "AES");
346 | }
347 |
348 | private char[] hashTheKey(String key) throws UnsupportedEncodingException, NoSuchAlgorithmException {
349 |
350 | MessageDigest messageDigest = MessageDigest.getInstance(SECRETKEY_DIGEST_SHA1);
351 | messageDigest.update(key.getBytes("UTF8"));
352 | return Base64.encodeToString(messageDigest.digest(), Base64.NO_WRAP).toCharArray();
353 | }
354 |
355 | private boolean isValidArgKey(String arg) {
356 |
357 | return ((arg != null) && (!arg.isEmpty()));
358 | }
359 |
360 | private boolean isValidArg(String arg) {
361 |
362 | return ((arg != null) && (!arg.isEmpty()) && ((arg.length() % 2) == 0) && (arg.length() >= 16)) ;
363 | }
364 |
365 | private byte[] hexStringToByteArray(String s) {
366 |
367 | int len = s.length();
368 | byte[] data = new byte[len / 2];
369 | for (int i = 0; i < len; i += 2) {
370 | data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
371 | + Character.digit(s.charAt(i+1), 16));
372 | }
373 | return data;
374 | }
375 |
376 | private Cipher getCipher(int operationMode) throws NoSuchAlgorithmException, InvalidKeySpecException,
377 | UnsupportedEncodingException, NoSuchPaddingException, InvalidAlgorithmParameterException,
378 | InvalidKeyException {
379 |
380 | Cipher cipher = Cipher.getInstance(ENCRYPTION_ALGORITHM_PCKS5);
381 |
382 | cipher.init(
383 | operationMode,
384 | getSecretKey(SECRETKEY_ALGORITHM_SHA1),
385 | ivParameterSpec,
386 | secureRandom);
387 | return cipher;
388 | }
389 |
390 |
391 |
392 | private byte[] getDecryptFromCipherInputStream(InputStream fis, Cipher cipher) throws IOException {
393 |
394 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
395 |
396 | CipherInputStream cis = new CipherInputStream(fis, cipher);
397 |
398 | byte data[] = new byte[16];
399 | int read;
400 | while ((read = cis.read(data)) != -1) {
401 | bos.write(data, 0, read);
402 | bos.flush();
403 | }
404 |
405 | if (bos != null) {
406 | bos.flush();
407 | bos.close();
408 | }
409 |
410 | if (fis != null) {
411 | fis.close();
412 | }
413 | if (cis != null) {
414 | cis.close();
415 | }
416 |
417 | return bos.toByteArray();
418 | }
419 |
420 | private byte[] getByteArrayFromFile(InputStream fileInput) throws IOException {
421 |
422 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
423 |
424 | while (fileInput.available() > 0) {
425 | bos.write(fileInput.read());
426 | }
427 |
428 | if (bos != null) {
429 | bos.flush();
430 | bos.close();
431 | }
432 |
433 | if (fileInput != null) {
434 | fileInput.close();
435 | }
436 |
437 | return bos.toByteArray();
438 | }
439 |
440 | private byte[] getByteArrayFromFile(File fileInput) throws IOException {
441 |
442 | InputStream fis = new BufferedInputStream(new FileInputStream(fileInput));
443 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
444 |
445 |
446 | while (fis.available() > 0) {
447 | bos.write(fis.read());
448 | }
449 |
450 | if (bos != null) {
451 | bos.flush();
452 | bos.close();
453 | }
454 |
455 | if (fis != null) {
456 | fis.close();
457 | }
458 |
459 | return bos.toByteArray();
460 | }
461 |
462 | private byte[] getEncryptInputStream(InputStream fis, Cipher cipher) throws IOException {
463 |
464 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
465 |
466 | CipherOutputStream cos = new CipherOutputStream(bos, cipher);
467 |
468 | byte[] data = new byte[16];
469 | int read;
470 | while ((read = fis.read(data)) != -1) {
471 | cos.write(data, 0, read);
472 | cos.flush();
473 | }
474 |
475 | if (cos != null) {
476 | cos.close();
477 | }
478 |
479 | if (bos != null) {
480 | bos.close();
481 | }
482 |
483 | if (fis != null) {
484 | fis.close();
485 | }
486 |
487 | return bos.toByteArray();
488 | }
489 |
490 | }
491 |
--------------------------------------------------------------------------------