Skip to content

Commit

Permalink
Support devices runing KitKat (API 19) patrickfav#6
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmigloz committed Jul 9, 2018
1 parent 42f14d6 commit 70fca34
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 12 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ android {
buildToolsVersion rootProject.ext.buildToolsVersion

defaultConfig {
minSdkVersion 21
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionNameApp
Expand All @@ -22,7 +22,7 @@ android {
}

dependencies {
implementation 'at.favre.lib:armadillo:0.4.3'
implementation project(':armadillo')
implementation "com.android.support:appcompat-v7:$rootProject.ext.dependencies.support"
testImplementation "junit:junit:$rootProject.ext.dependencies.junit"
androidTestImplementation 'com.android.support.test:runner:1.0.2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
import java.nio.ByteBuffer;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import at.favre.lib.bytes.Bytes;

import static at.favre.lib.armadillo.Utils.isKitKat;

/**
* Implements AES (Advanced Encryption Standard) with Galois/Counter Mode (GCM), which is a mode of
* operation for symmetric key cryptographic block ciphers that has been widely adopted because of
Expand All @@ -31,11 +35,12 @@
* @author Patrick Favre-Bulle
* @since 18.12.2017
*/
@SuppressWarnings("WeakerAccess")
@SuppressWarnings({"WeakerAccess", "SameParameterValue"})
final class AesGcmEncryption implements AuthenticatedEncryption {

private static final String ALGORITHM = "AES/GCM/NoPadding";
private static final int TAG_LENGTH_BIT = 128;
private static final int IV_LENGTH_BYTE = 12;
private static final int TAG_LENGTH_BYTES = 16;
private static final int IV_LENGTH_BYTES = 12;

private final SecureRandom secureRandom;
private final Provider provider;
Expand All @@ -61,13 +66,14 @@ public byte[] encrypt(byte[] rawEncryptionKey, byte[] rawData, @Nullable byte[]
}

try {
byte[] iv = new byte[IV_LENGTH_BYTE];
byte[] iv = new byte[IV_LENGTH_BYTES];
secureRandom.nextBytes(iv);

final Cipher cipher = getCipher();
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(rawEncryptionKey, "AES"), new GCMParameterSpec(TAG_LENGTH_BIT, iv));
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(rawEncryptionKey, "AES"), getParams(iv));

if (associatedData != null) {
if (associatedData != null && associatedData.length != 0 && !isKitKat()) {
// associated data is not available on Android KitKat
cipher.updateAAD(associatedData);
}

Expand Down Expand Up @@ -99,8 +105,9 @@ public byte[] decrypt(byte[] rawEncryptionKey, byte[] encryptedData, @Nullable b
byteBuffer.get(encrypted);

final Cipher cipher = getCipher();
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(rawEncryptionKey, "AES"), new GCMParameterSpec(TAG_LENGTH_BIT, iv));
if (associatedData != null) {
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(rawEncryptionKey, "AES"), getParams(iv));
if (associatedData != null && associatedData.length != 0 && !isKitKat()) {
// associated data is not available on Android KitKat
cipher.updateAAD(associatedData);
}
return cipher.doFinal(encrypted);
Expand Down Expand Up @@ -132,4 +139,18 @@ private Cipher getCipher() {
}
return cipher;
}

private AlgorithmParameterSpec getParams(final byte[] iv) {
return getParams(iv, 0, iv.length);
}

private AlgorithmParameterSpec getParams(final byte[] buf, int offset, int len) {
if (isKitKat()) {
// GCMParameterSpec should always be present in Java 7 or newer, but it's missing on
// some Android devices with API level <= 19. Fortunately, we can initialize the cipher
// with just an IvParameterSpec. It will use a tag size of 128 bits.
return new IvParameterSpec(buf, offset, len);
}
return new GCMParameterSpec(TAG_LENGTH_BYTES * 8, buf, offset, len);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ public interface AuthenticatedEncryption {
*
* @param rawEncryptionKey to use as encryption key material
* @param rawData to encrypt
* @param associatedData additional data used to create the auth tag and will be subject to integrity/authentication check
* @param associatedData additional data used to create the auth tag and will be subject to
* integrity/authentication check (associatedData is not available on
* Android KitKat (API level 19), it will be ignored)
* @return encrypted content
* @throws AuthenticatedEncryptionException if any crypto fails
*/
Expand All @@ -51,7 +53,8 @@ public interface AuthenticatedEncryption {
* @param rawEncryptionKey to use as decryption key material
* @param encryptedData to decrypt
* @param associatedData additional data used to create the auth tag; must be same as provided
* in the encrypt step
* in the encrypt step (associatedData is not available on Android KitKat
* (API level 19), it will be ignored)
* @return decrypted, original data
* @throws AuthenticatedEncryptionException if any crypto fails
*/
Expand Down
17 changes: 17 additions & 0 deletions armadillo/src/main/java/at/favre/lib/armadillo/Utils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package at.favre.lib.armadillo;

import android.os.Build;

class Utils {

private Utils() {
// Utility class
}

/**
* Checks whether the device runs Android KitKat (API level 19).
*/
static boolean isKitKat() {
return Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT;
}
}

0 comments on commit 70fca34

Please sign in to comment.