From a3a68e98479059db3092e9135b9e426c6be6695b Mon Sep 17 00:00:00 2001 From: Benjamin AIMONE Date: Mon, 14 Sep 2020 15:48:34 +0200 Subject: [PATCH 1/3] Preapre repository for public release: version 0.1.0, clearer README, promote Klaxit usage, travis ci config --- .travis.yml | 18 ++++++++++++++ README.md | 24 +++++++++++-------- build.gradle.kts | 7 +++++- .../hiddensecrets/HiddenSecretsPlugin.kt | 7 +++--- .../kotlin/com/klaxit/hiddensecrets/Utils.kt | 4 +++- src/test/kotlin/HiddenSecretsTest.kt | 17 ------------- src/test/kotlin/UtilsTest.kt | 7 ++++++ 7 files changed, 51 insertions(+), 33 deletions(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..211c6bc --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: java +install: skip + +os: linux +dist: trusty +jdk: oraclejdk8 + +script: + - ./gradlew test --info --build-cache + +before_cache: + - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock + - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ + +cache: + directories: + - $HOME/.gradle/caches/ + - $HOME/.gradle/wrapper/ diff --git a/README.md b/README.md index c802121..55e4732 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +![travis ci status](https://travis-ci.com/klaxit/hidden-secrets-gradle-plugin.svg?branch=master) + +https://travis-ci.com/klaxit/hidden-secrets-gradle-plugin.svg?branch=master + # Gradle plugin to deeply hide secrets on Android This repository is the gradle plugin version of this POC : [HiddenSecrets](https://github.com/klaxit/HiddenSecrets) @@ -17,19 +21,19 @@ This project is also a demonstration on how to create a full Kotlin gradle plugi ## Compatibility This gradle plugin can be used with any Android project in Java or Kotlin. -# 1 - Get the plugin - -You can build the `.jar` file from the code as explained below, or directly get it from [releases](https://github.com/klaxit/hidden-secrets-gradle-plugin/releases). -## Build it -Checkout the code and run `gradle build` to create the `.jar` file in `/build/libs/`. +## Integrated in Klaxit's production application +The `HiddenSecretsPlugin` is already used by our Android application : [Klaxit - Covoiturage quotidien](https://play.google.com/store/apps/details?id=com.wayzup.wayzupapp). +This is a french carpooling app that let our users share there rides to work or other location. 265 companies and 30 client cities are trusting us by using our carpooling solution. +We are using this plugin to secure keys that we want to hide from easy attacks based on apk extraction and reverse engineering. +This is why this repository will be well maintained by our engineering team to ensure **Klaxit**'s Android app security. -## Copy the plugin -Copy `HiddenSecretsPlugin-1.0.0.jar` from the gradle plugin folder `/build/libs/` to your Android project in `/app/libs/`. +# 1 - Install the plugin -## Enable the plugin in your project +Get the latest version of the plugin from [releases](https://github.com/klaxit/hidden-secrets-gradle-plugin/releases). +Copy `HiddenSecretsPlugin-0.1.0.jar` to your Android project in `/app/libs/` folder. -Add these line in your app level `build.gradle`: +Add these lines in your app level `build.gradle`: ```gradle buildscript { @@ -39,7 +43,7 @@ buildscript { } // Add dependency to HiddenSecretsPlugin dependencies { - classpath("com.klaxit.hiddensecrets.gradle:HiddenSecretsPlugin:1.0.0") + classpath("com.klaxit.hiddensecrets.gradle:HiddenSecretsPlugin:0.1.0") } } diff --git a/build.gradle.kts b/build.gradle.kts index 79364b0..4797576 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } group = "com.klaxit.hiddensecrets" -version = "1.0.0" +version = "0.1.0" repositories { mavenCentral() @@ -32,6 +32,11 @@ gradlePlugin { } } +tasks.withType { + //Required by Gradle 7.0 + duplicatesStrategy = DuplicatesStrategy.INCLUDE +} + tasks.withType { useJUnitPlatform() } \ No newline at end of file diff --git a/src/main/kotlin/com/klaxit/hiddensecrets/HiddenSecretsPlugin.kt b/src/main/kotlin/com/klaxit/hiddensecrets/HiddenSecretsPlugin.kt index b1cc2a0..668c072 100644 --- a/src/main/kotlin/com/klaxit/hiddensecrets/HiddenSecretsPlugin.kt +++ b/src/main/kotlin/com/klaxit/hiddensecrets/HiddenSecretsPlugin.kt @@ -53,7 +53,7 @@ open class HiddenSecretsPlugin : Plugin { */ @Input fun getKeyParam(): String { - var key = "" + val key: String if (project.hasProperty("key")) { //From command line key = project.property("key") as String @@ -69,7 +69,7 @@ open class HiddenSecretsPlugin : Plugin { @Input fun getPackageNameParam(): String { //From config - var packageName : String? = null + var packageName: String? = null if (project.hasProperty("package")) { //From command line packageName = project.property("package") as String? @@ -138,8 +138,7 @@ open class HiddenSecretsPlugin : Plugin { /** * Unzip plugin into tmp directory */ - project.tasks.create(TASK_UNZIP_HIDDEN_SECRETS, Copy:: - class.java, + project.tasks.create(TASK_UNZIP_HIDDEN_SECRETS, Copy::class.java, object : Action { @TaskAction override fun execute(copy: Copy) { diff --git a/src/main/kotlin/com/klaxit/hiddensecrets/Utils.kt b/src/main/kotlin/com/klaxit/hiddensecrets/Utils.kt index 7259d5d..7d672a5 100644 --- a/src/main/kotlin/com/klaxit/hiddensecrets/Utils.kt +++ b/src/main/kotlin/com/klaxit/hiddensecrets/Utils.kt @@ -1,5 +1,6 @@ package com.klaxit.hiddensecrets +import com.google.common.annotations.VisibleForTesting import java.nio.charset.Charset import java.security.MessageDigest import kotlin.experimental.xor @@ -26,7 +27,8 @@ class Utils { /** * Encode string to sha256 */ - private fun sha256(toHash: String): String { + @VisibleForTesting + fun sha256(toHash: String): String { val bytes = toHash.toByteArray() val md = MessageDigest.getInstance("SHA-256") val digest = md.digest(bytes) diff --git a/src/test/kotlin/HiddenSecretsTest.kt b/src/test/kotlin/HiddenSecretsTest.kt index decfcd6..08e5d17 100644 --- a/src/test/kotlin/HiddenSecretsTest.kt +++ b/src/test/kotlin/HiddenSecretsTest.kt @@ -1,22 +1,9 @@ -import com.klaxit.hiddensecrets.HiddenSecretsPlugin -import io.kotlintest.shouldNotBe import io.kotlintest.specs.WordSpec -import org.gradle.testfixtures.ProjectBuilder import org.gradle.testkit.runner.GradleRunner import org.junit.rules.TemporaryFolder class HiddenSecretsTest : WordSpec({ - "Using the Plugin ID" should { - "Apply the Plugin" { - val project = ProjectBuilder.builder().build() - project.pluginManager.apply("com.klaxit.HiddenSecrets") - - val plugin = project.plugins.getPlugin(HiddenSecretsPlugin::class.java) - plugin shouldNotBe null - } - } - "Apply the plugin" should { val testProjectDir = TemporaryFolder() testProjectDir.create() @@ -35,9 +22,5 @@ class HiddenSecretsTest : WordSpec({ val result = gradleRunner.withArguments("copyCpp").build() println(result.output) } - "Make command copyKotlin works" { - val result = gradleRunner.withArguments("copyCpp").build() - println(result.output) - } } }) \ No newline at end of file diff --git a/src/test/kotlin/UtilsTest.kt b/src/test/kotlin/UtilsTest.kt index 3718527..55415df 100644 --- a/src/test/kotlin/UtilsTest.kt +++ b/src/test/kotlin/UtilsTest.kt @@ -11,6 +11,13 @@ class UtilsTest : WordSpec({ } } + "Using sha256()" should { + "encode String in sha256" { + val key = "youCanNotFindMySecret!" + Utils.sha256(key) shouldBe "7bdc2b5992ef7b4cce0e06295f564f4fad0c96e5f82a0bcf9cd8323d3a3bcfbd" + } + } + "Using encodeSecret()" should { "encode String with a seed" { val key = "keyToEncode" From c77808a08548c1f56f3752873f2742f240c3df4d Mon Sep 17 00:00:00 2001 From: Benjamin AIMONE Date: Mon, 28 Sep 2020 10:43:25 +0200 Subject: [PATCH 2/3] Fix special characters enconding in keys --- README.md | 2 -- src/main/kotlin/com/klaxit/hiddensecrets/Utils.kt | 4 +--- src/test/kotlin/UtilsTest.kt | 7 ++++++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 55e4732..90d7669 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ ![travis ci status](https://travis-ci.com/klaxit/hidden-secrets-gradle-plugin.svg?branch=master) -https://travis-ci.com/klaxit/hidden-secrets-gradle-plugin.svg?branch=master - # Gradle plugin to deeply hide secrets on Android This repository is the gradle plugin version of this POC : [HiddenSecrets](https://github.com/klaxit/HiddenSecrets) diff --git a/src/main/kotlin/com/klaxit/hiddensecrets/Utils.kt b/src/main/kotlin/com/klaxit/hiddensecrets/Utils.kt index 7d672a5..82b30fb 100644 --- a/src/main/kotlin/com/klaxit/hiddensecrets/Utils.kt +++ b/src/main/kotlin/com/klaxit/hiddensecrets/Utils.kt @@ -41,7 +41,6 @@ class Utils { fun encodeSecret(key: String, packageName: String): String { //Generate the obfuscator as the SHA256 of the app package name val obfuscator = sha256(packageName) - //println("SHA 256 = " + obfuscator) val obfuscatorBytes = obfuscator.toByteArray() //Generate the obfuscated secret bytes array by applying a XOR between the secret and the obfuscator @@ -57,13 +56,12 @@ class Utils { val iterator: Iterator = obfuscatedSecretBytes.iterator() while (iterator.hasNext()) { val item = iterator.next() - encoded += "0x" + Integer.toHexString(item.toInt()) + encoded += "0x" + Integer.toHexString(item.toInt() and 0xff) if (iterator.hasNext()) { encoded += ", " } } encoded += " }" - return encoded } } diff --git a/src/test/kotlin/UtilsTest.kt b/src/test/kotlin/UtilsTest.kt index 55415df..2239e41 100644 --- a/src/test/kotlin/UtilsTest.kt +++ b/src/test/kotlin/UtilsTest.kt @@ -22,7 +22,12 @@ class UtilsTest : WordSpec({ "encode String with a seed" { val key = "keyToEncode" val packageName = "com.klaxit.test" - Utils.encodeSecret(key,packageName) shouldBe "{ 0x5b, 0x6, 0x18, 0x31, 0xb, 0x72, 0x57, 0x5, 0x5d, 0x57, 0x3 }" + Utils.encodeSecret(key, packageName) shouldBe "{ 0x5b, 0x6, 0x18, 0x31, 0xb, 0x72, 0x57, 0x5, 0x5d, 0x57, 0x3 }" + } + "encode String with special characters" { + val key = "@&é(§èçà)-ù,;:=#°_*%£?./+" + val packageName = "com.klaxit.test" + Utils.encodeSecret(key, packageName) shouldBe "{ 0x70, 0x45, 0xa2, 0xcc, 0x4c, 0xf5, 0x9e, 0xa5, 0x9a, 0xf0, 0xc1, 0xa6, 0x92, 0x4a, 0x4e, 0xa6, 0x8a, 0x1a, 0xc, 0x5e, 0x5, 0x14, 0xf7, 0x86, 0x6b, 0x13, 0x40, 0xf5, 0x9a, 0xc, 0x16, 0x16, 0x19 }" } } }) \ No newline at end of file From 30e3f4362b9fd98cd585a6e217fd4f7cd188efd3 Mon Sep 17 00:00:00 2001 From: Cyrille Courtiere Date: Mon, 28 Sep 2020 11:03:07 +0200 Subject: [PATCH 3/3] improve README --- README.md | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 90d7669..371d5f9 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,15 @@ # Gradle plugin to deeply hide secrets on Android -This repository is the gradle plugin version of this POC : [HiddenSecrets](https://github.com/klaxit/HiddenSecrets) - -It is highly inspired from https://www.splinter.com.au/2014/09/16/storing-secret-keys/ +This plugin allows any Android developer to deeply hide secrets in its project. It is an OSS equivalent of what [DexGuard](https://www.guardsquare.com/en/products/dexguard) can offer to prevent **credentials harvesting**. It uses a combination of obfuscation techniques to do so : - secret is obfuscated using the reversible XOR operator so it never appears in plain sight, - obfuscated secret is stored in a NDK binary as an hexadecimal array, so it is really hard to spot / put together from a disassembly, -- the obfuscating string is not persisted in the binary to force runtime evaluation (ie : prevent the compiler from disclosing the secret by optimizing the de-obfuscation logic). +- the obfuscating string is not persisted in the binary to force runtime evaluation (ie : prevent the compiler from disclosing the secret by optimizing the de-obfuscation logic), +- optionnaly, anyone can provide it's own encoding / decoding algorithm when using the plugin to add an additional security layer. + +This plugin is **used in production** at [Klaxit - Covoiturage quotidien](https://play.google.com/store/apps/details?id=com.wayzup.wayzupapp). Our engineering team at Klaxit will provide its best effort to maintain this project. ⚠️ Nothing on the client-side is unbreakable. So generally speaking, **keeping a secret in a mobile package is not a smart idea**. But when you absolutely need to, this is the best method we have found to hide it. @@ -19,17 +20,10 @@ This project is also a demonstration on how to create a full Kotlin gradle plugi ## Compatibility This gradle plugin can be used with any Android project in Java or Kotlin. - -## Integrated in Klaxit's production application -The `HiddenSecretsPlugin` is already used by our Android application : [Klaxit - Covoiturage quotidien](https://play.google.com/store/apps/details?id=com.wayzup.wayzupapp). -This is a french carpooling app that let our users share there rides to work or other location. 265 companies and 30 client cities are trusting us by using our carpooling solution. -We are using this plugin to secure keys that we want to hide from easy attacks based on apk extraction and reverse engineering. -This is why this repository will be well maintained by our engineering team to ensure **Klaxit**'s Android app security. - # 1 - Install the plugin Get the latest version of the plugin from [releases](https://github.com/klaxit/hidden-secrets-gradle-plugin/releases). -Copy `HiddenSecretsPlugin-0.1.0.jar` to your Android project in `/app/libs/` folder. +Copy `HiddenSecretsPlugin-X.Y.Z.jar` to your Android project in `/app/libs/` folder. Add these lines in your app level `build.gradle`: @@ -41,7 +35,7 @@ buildscript { } // Add dependency to HiddenSecretsPlugin dependencies { - classpath("com.klaxit.hiddensecrets.gradle:HiddenSecretsPlugin:0.1.0") + classpath("com.klaxit.hiddensecrets.gradle:HiddenSecretsPlugin:X.Y.Z") } } @@ -141,6 +135,8 @@ gradle obfuscate -Pkey=yourKeyToObfuscate [-Ppackage=com.your.package] Pull Requests are very welcome! +To get started, checkout the code and run `gradle build` to create the `.jar` file in `/build/libs/`. + Please make sure that you have tested your code carefully before opening a PR, and make sure as well that you have no style issues. ## Authors