diff --git a/README.md b/README.md index 0276049..e8f2204 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,33 @@ +[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-AndroidEncryptionExample-green.svg?style=true)](https://android-arsenal.com/details/3/4886) + Android Encryption Example ======================== +This example encrypts the inputted string using AES, encrypts the key via RSA, and does the reverse when +the decrypt button is clicked. + +We start by encrypting the plain text with AES + +```java +byte[] iv = AESEncryptDecrypt.aesEncrypt(plainTextInputStream, + "secret key".toCharArray(), + "AES/ECB/PKCS5PADDING", + encOutputStream); +``` +We then combine the outputted IV and the key we used: + +```java +byte[] combined = Util.concat("secret key".getBytes(), iv); +``` + +Lastly we encryt the IV and key using an RSA public key: + +```java +byte[] encryptedAESKeyIV = RSAEncryptDecrypt.encryptRSA(combined, rsaKey.getPublic()); +``` + +======================== + This is an encryption example of RSA and AES (CBC, ECB, CTR) 256 bit key on android with unit tests. I have tried to provide a good and secure example by showcasing: @@ -12,8 +39,9 @@ tried to provide a good and secure example by showcasing: * RSA 2048 bit * Spongy Castle (Android version of Bouncy Castle encryption library) -The example encrypts the inputted string using AES, encrypts the key via RSA, and does the reverse when -the decrypt button is clicked. + +![AndroidEncryptionExample](https://github.com/brianPlummer/AndroidEncryptionExample/raw/master/assets/encryption_sample.gif "AndroidEncryptionExample") + Prerequisite ======================== diff --git a/app/build.gradle b/app/build.gradle index ef1f0b1..892f8e1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:1.2.2' + classpath 'com.android.tools.build:gradle:2.2.3' } } @@ -14,12 +14,12 @@ buildscript { apply plugin: 'com.android.application' android { - compileSdkVersion 23 - buildToolsVersion "23.0.2" + compileSdkVersion 25 + buildToolsVersion "25.0.1" defaultConfig { minSdkVersion 14 - targetSdkVersion 23 + targetSdkVersion 25 versionCode 1 versionName "1.0" } @@ -32,10 +32,10 @@ android { dependencies { - compile 'com.android.support:appcompat-v7:23.+' + compile 'com.android.support:appcompat-v7:25.0.1' compile 'org.ow2.util.base64:base64:2.0.0' - compile 'com.madgag.spongycastle:prov:1.51.0.0' - compile 'com.android.support:support-annotations:23.0.2' + compile 'com.madgag.spongycastle:prov:1.54.0.0' + compile 'com.android.support:support-annotations:25.1.0' testCompile 'junit:junit:4.12' testCompile 'org.apache.commons:commons-io:1.3.2' testCompile 'bouncycastle:bouncycastle-jce-jdk13:112' diff --git a/app/src/main/java/com/codemonkeylabs/encryptionexample/app/AESEncryptDecrypt.java b/app/src/main/java/com/codemonkeylabs/encryptionexample/app/AESEncryptDecrypt.java index d46e760..f995327 100644 --- a/app/src/main/java/com/codemonkeylabs/encryptionexample/app/AESEncryptDecrypt.java +++ b/app/src/main/java/com/codemonkeylabs/encryptionexample/app/AESEncryptDecrypt.java @@ -26,7 +26,6 @@ /** * AES Helper Encryption Class - * Created by brianplummer on 4/29/14. */ public class AESEncryptDecrypt { @@ -64,7 +63,8 @@ public static void setProvider(Provider provider, String providerName) { public enum AESCipherType { AES_CIPHER_CTR_NOPADDING("AES/CTR/NOPADDING"), AES_CIPHER_ECB_PKCS5PADDING("AES/ECB/PKCS5PADDING"), - AES_CBC_PKCS5PADDING("AES/CBC/PKCS5Padding"); + AES_CBC_PKCS5PADDING("AES/CBC/PKCS5Padding"), + AES_CBC_PKCS7Padding("AES/CBC/PKCS7Padding"); private final String value; diff --git a/app/src/main/java/com/codemonkeylabs/encryptionexample/app/RSAEncryptDecrypt.java b/app/src/main/java/com/codemonkeylabs/encryptionexample/app/RSAEncryptDecrypt.java index a1f73a4..5894e24 100644 --- a/app/src/main/java/com/codemonkeylabs/encryptionexample/app/RSAEncryptDecrypt.java +++ b/app/src/main/java/com/codemonkeylabs/encryptionexample/app/RSAEncryptDecrypt.java @@ -11,7 +11,6 @@ import javax.crypto.Cipher; /** * RSA Helper Encryption Class - * Created by brianplummer on 4/29/14. */ public class RSAEncryptDecrypt { diff --git a/app/src/test/java/com/codemonkeylabs/encryptionsexample/EncryptionTest.java b/app/src/test/java/com/codemonkeylabs/encryptionsexample/EncryptionTest.java index 2ff5992..c3a007e 100644 --- a/app/src/test/java/com/codemonkeylabs/encryptionsexample/EncryptionTest.java +++ b/app/src/test/java/com/codemonkeylabs/encryptionsexample/EncryptionTest.java @@ -1,34 +1,25 @@ package com.codemonkeylabs.encryptionsexample; -import android.test.InstrumentationTestCase; - import com.codemonkeylabs.encryptionexample.app.AESEncryptDecrypt; import com.codemonkeylabs.encryptionexample.app.RSAEncryptDecrypt; import com.codemonkeylabs.encryptionexample.app.Util; import org.apache.commons.io.IOUtils; +import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; - -import org.bouncycastle.jce.provider.BouncyCastleProvider; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.UnsupportedEncodingException; -import java.net.URL; import java.security.KeyPair; import java.util.Arrays; -/** - * Created by brianplummer on 9/2/14. - */ +import static org.junit.Assert.assertTrue; + public class EncryptionTest { private String testText = null; @@ -79,6 +70,34 @@ public void testAESEncryptionCBC() throws UnsupportedEncodingException } + @Test + public void testAESEncryptionCBCPadding7() throws UnsupportedEncodingException + { + + ByteArrayInputStream plainTextInputStream = new ByteArrayInputStream(testText.getBytes("UTF-8")); + ByteArrayOutputStream encOutputStream = new ByteArrayOutputStream(1024 * 100); + + byte[] iv = AESEncryptDecrypt.aesEncrypt(plainTextInputStream, + AESEncryptDecrypt.NOT_SECRET_ENCRYPTION_KEY.toCharArray(), + AESEncryptDecrypt.AESCipherType.AES_CBC_PKCS7Padding, + encOutputStream); + + + ByteArrayInputStream encInputStream = new ByteArrayInputStream(encOutputStream.toByteArray()); + ByteArrayOutputStream plainTextOutputStream = new ByteArrayOutputStream(1024 * 100); + + AESEncryptDecrypt.aesDecrypt(encInputStream, + AESEncryptDecrypt.NOT_SECRET_ENCRYPTION_KEY.toCharArray(), + iv, + AESEncryptDecrypt.AESCipherType.AES_CBC_PKCS7Padding, + plainTextOutputStream); + + + String unencryptedString = new String(plainTextOutputStream.toByteArray(),"UTF-8"); + + assertTrue(unencryptedString.startsWith("All this while Tashtego, Daggoo, and Queequeg")); + } + @Test public void testAESEncryptionCTR() throws UnsupportedEncodingException { diff --git a/assets/encryption_sample.gif b/assets/encryption_sample.gif new file mode 100644 index 0000000..d583003 Binary files /dev/null and b/assets/encryption_sample.gif differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 73e4a60..620d03c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Dec 28 21:16:45 EST 2014 +#Thu Jan 12 22:00:50 EST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..335e724 --- /dev/null +++ b/license.txt @@ -0,0 +1,19 @@ +Copyright (c) <2017> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.