From e1507b8962117227896265417f65ee1d7d31ee93 Mon Sep 17 00:00:00 2001 From: Chuck Greb Date: Thu, 14 Jul 2016 16:35:19 -0400 Subject: [PATCH] Remove client side encryption of production API keys (#680) * Removes `leyndo` dependency from `build.gradle`. * Removes `SimpleCrypt` class. * Removes encryption and `leyndo` installation scripts. * Updates `release-checklist.md` documentation for local production builds. * Updates `deploy.sh` script to assemble production APK on Circle CI. This patch removes client-side API key encryption for production builds. It is to be replaced by request signing and server-side validation prior to launch. https://github.com/mapzen/eraser-map/issues/679 Fixes #663 --- app/build.gradle | 5 - .../mapzen/erasermap/model/SimpleCrypt.java | 97 ------------------- .../com/mapzen/erasermap/model/ApiKeys.kt | 13 +-- release-checklist.md | 5 +- scripts/deploy.sh | 1 - scripts/encrypter.rb | 6 -- scripts/encrypter.sh | 18 ---- scripts/install-leyndo.sh | 5 - 8 files changed, 5 insertions(+), 145 deletions(-) delete mode 100644 app/src/main/java/com/mapzen/erasermap/model/SimpleCrypt.java delete mode 100755 scripts/encrypter.rb delete mode 100755 scripts/encrypter.sh delete mode 100755 scripts/install-leyndo.sh diff --git a/app/build.gradle b/app/build.gradle index d447e2d5..13b142a8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -150,9 +150,4 @@ dependencies { testCompile 'org.assertj:assertj-core:1.7.0' testCompile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" testCompile 'org.json:json:20160212' - - if (flavorType == 'Prod') { - println("Including production only dependencies...") - compile 'com.mapzen.android:leyndo:0.0.1-SNAPSHOT' - } } diff --git a/app/src/main/java/com/mapzen/erasermap/model/SimpleCrypt.java b/app/src/main/java/com/mapzen/erasermap/model/SimpleCrypt.java deleted file mode 100644 index e0fb4877..00000000 --- a/app/src/main/java/com/mapzen/erasermap/model/SimpleCrypt.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.mapzen.erasermap.model; - -import android.app.Application; -import android.util.Base64; - -import java.security.spec.AlgorithmParameterSpec; -import java.security.spec.KeySpec; - -import javax.crypto.Cipher; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; -import javax.crypto.spec.PBEParameterSpec; - -public class SimpleCrypt { - private static String defaultSalt = "default"; - private Cipher ecipher, dcipher; - private Application application; - - static { - try { - System.loadLibrary("leyndo"); - } catch (UnsatisfiedLinkError e) { - if ("Dalvik".equals(System.getProperty("java.vm.name"))) { - throw e; - } - } - } - - public native String getSalt(Application application); - public char[] getSaltMix() { - if ("Dalvik".equals(System.getProperty("java.vm.name"))) { - return getSalt(application).toCharArray(); - } else { - return defaultSalt.toCharArray(); - } - } - - /** - * Used by script {@code encrypter.rb} to create instance with custom salt value. - */ - public static SimpleCrypt withSpecialSalt(String specialSalt) { - SimpleCrypt.defaultSalt = specialSalt; - return new SimpleCrypt(); - } - - public SimpleCrypt(Application application) { - this.application = application; - init(); - } - - public SimpleCrypt() { - init(); - } - - private void init() { - byte[] salt = { - (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, - (byte) 0x56, (byte) 0x34, (byte) 0xE3, (byte) 0x03 - }; - int iterationCount = 19; - try { - KeySpec keySpec = new PBEKeySpec(getSaltMix(), salt, iterationCount); - SecretKey key = - SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec); - ecipher = Cipher.getInstance(key.getAlgorithm()); - dcipher = Cipher.getInstance(key.getAlgorithm()); - AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount); - ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); - dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec); - } catch (Exception e) { - System.out.println("SimpleCrypt error: " + e.getMessage()); - } - } - - public String encode(String str) { - try { - byte[] utf8 = str.getBytes("UTF8"); - byte[] enc = ecipher.doFinal(utf8); - return Base64.encodeToString(enc, Base64.DEFAULT); - } catch (Exception e) { - System.out.println("SimpleCrypt encoding error: " + e.getMessage()); - } - return null; - } - - public String decode(String gargle) { - byte[] encodedBytes = Base64.decode(gargle, Base64.DEFAULT); - try { - byte[] utf8 = dcipher.doFinal(encodedBytes); - return new String(utf8, "UTF8"); - } catch (Exception e) { - System.out.println("SimpleCrypt decoding error: " + e.getMessage()); - } - return null; - } -} diff --git a/app/src/main/kotlin/com/mapzen/erasermap/model/ApiKeys.kt b/app/src/main/kotlin/com/mapzen/erasermap/model/ApiKeys.kt index 5f0a3a0c..079749c6 100644 --- a/app/src/main/kotlin/com/mapzen/erasermap/model/ApiKeys.kt +++ b/app/src/main/kotlin/com/mapzen/erasermap/model/ApiKeys.kt @@ -31,15 +31,8 @@ class ApiKeys private constructor(val application: EraserMapApplication) { } private fun configureKeys() { - if (BuildConfig.DEBUG) { - tilesKey = BuildConfig.VECTOR_TILE_API_KEY - searchKey = BuildConfig.PELIAS_API_KEY - routingKey = BuildConfig.VALHALLA_API_KEY - } else { - val crypt = SimpleCrypt(application) - tilesKey = crypt.decode(BuildConfig.VECTOR_TILE_API_KEY) - searchKey = crypt.decode(BuildConfig.PELIAS_API_KEY) - routingKey = crypt.decode(BuildConfig.VALHALLA_API_KEY) - } + tilesKey = BuildConfig.VECTOR_TILE_API_KEY + searchKey = BuildConfig.PELIAS_API_KEY + routingKey = BuildConfig.VALHALLA_API_KEY } } diff --git a/release-checklist.md b/release-checklist.md index dc5b6eb4..11cb56e0 100644 --- a/release-checklist.md +++ b/release-checklist.md @@ -5,9 +5,8 @@ Eraser Map Release Checklist 1. Clone the production keystore from its private repository and copy it into your home folder. 2. Add the keystore credentials to `~/.gradle/gradle.properties`. -3. Copy the production API key values encoded using `encrypter.sh` into `~/.gradle/gradle.properties`. -4. Install the `leyndo` project into your local Maven repository. -5. Build release APK using `./gradlew clean installProdRelease`. +3. Copy the production API keys into `~/.gradle/gradle.properties`. +4. Build release APK using `./gradlew clean installProdRelease --refresh-dependencies`. ## Building a release APK on Circle CI diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 1b1c4bcc..1e11b9cb 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -7,7 +7,6 @@ if [ -z ${PERFORM_RELEASE} ] ./gradlew assembleDevDebug -PmintApiKey=$MINT_API_KEY -PvectorTileApiKey=$VECTOR_TILE_API_KEY -PpeliasApiKey=$PELIAS_API_KEY -PvalhallaApiKey=$VALHALLA_API_KEY -PbuildNumber=$CIRCLE_BRANCH-$CIRCLE_BUILD_NUM -PsearchBaseUrl="$SEARCH_BASE_URL" -ProuteBaseUrl="$ROUTE_BASE_URL" s3cmd put app/build/outputs/apk/app-dev-debug.apk s3://android.mapzen.com/erasermap-development/$CIRCLE_BRANCH-$CIRCLE_BUILD_NUM.apk else - scripts/install-leyndo.sh cd app && git clone $CONFIG_REPO cd .. ./gradlew clean assembleProdRelease --refresh-dependencies -PmintApiKey=$MINT_API_KEY -PvectorTileApiKey=$VECTOR_TILE_API_KEY_PROD -PpeliasApiKey=$PELIAS_API_KEY_PROD -PvalhallaApiKey=$VALHALLA_API_KEY_PROD -PbuildNumber=$RELEASE_TAG -PreleaseStoreFile=$RELEASE_STORE_FILE -PreleaseStorePassword="$RELEASE_STORE_PASSWORD" -PreleaseKeyAlias=$RELEASE_KEY_ALIAS -PreleaseKeyPassword="$RELEASE_KEY_PASSWORD" -PsearchBaseUrl="$SEARCH_BASE_URL" -ProuteBaseUrl="$ROUTE_BASE_URL" diff --git a/scripts/encrypter.rb b/scripts/encrypter.rb deleted file mode 100755 index 3d308e1e..00000000 --- a/scripts/encrypter.rb +++ /dev/null @@ -1,6 +0,0 @@ -require "android-all-4.4_r1-robolectric-0.jar" -$CLASSPATH << 'app/src/main/java' -special_salt = ARGV[0] -to_encode = ARGV[1] -simple_crypt = com.mapzen.erasermap.model.SimpleCrypt.withSpecialSalt(special_salt) -puts simple_crypt.encode(to_encode) diff --git a/scripts/encrypter.sh b/scripts/encrypter.sh deleted file mode 100755 index 0b3374e8..00000000 --- a/scripts/encrypter.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -# -# This script encrypts the specified raw value using the given salt value and SimpleCrypt.java -# -# Usage: -# encrypter.sh [salt] [raw_value_to_be_encrypted] -# -# Assumptions: -# java 7 -# jruby 1.7.12 - -wget http://central.maven.org/maven2/org/robolectric/android-all/4.4_r1-robolectric-0/android-all-4.4_r1-robolectric-0.jar -javac -cp android-all-4.4_r1-robolectric-0.jar app/src/main/java/com/mapzen/erasermap/model/SimpleCrypt.java - -jruby scripts/encrypter.rb $1 $2 - -rm android-all-4.4_r1-robolectric-0.jar -rm app/src/main/java/com/mapzen/erasermap/model/SimpleCrypt.class diff --git a/scripts/install-leyndo.sh b/scripts/install-leyndo.sh deleted file mode 100755 index a831a6b6..00000000 --- a/scripts/install-leyndo.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -export PATH="$PATH:$ANDROID_NDK" -git clone git@github.com:mapzen/leyndo.git -cd leyndo && ./install.sh