Loading ...

Secure Your Android Keys: The “No-Leak” Guide for Kotlin DSL

Sharing is caring, but never when it comes to your Android Keystore. If you push your .jks file or your passwords to GitHub, you’ve essentially handed the keys to your digital house to the public. Even if you delete the commit later, the data lives on in your Git history.
If you are using Compose and Kotlin DSL (build.gradle.kts), here is the professional way to keep your keys safe for local manual builds.

1. The Golden Rule: Stay Outside the Fence

The most common mistake is keeping the keystore file inside your project folder. Even with a .gitignore file, accidents happen.
The Solution: Store your keystore file in a folder above your project or in your user home directory.

Path Example:

/Users/username/developer/keystores/my-app.jks

2. Use local.properties as your Vault

Android projects come with a file called local.properties. This file is ignored by Git by default. It is designed to hold machine-specific information, making it the perfect place for secrets.
Add your credentials there:

# Never commit this file!
RELEASE_STORE_PATH=/Users/yourname/keystores/production-key.jks
RELEASE_STORE_PASSWORD=super_secret_password
RELEASE_KEY_ALIAS=my_app_alias
RELEASE_KEY_PASSWORD=another_secret_password

3. Configure the Kotlin DSL (build.gradle.kts)

Now, we need to tell Gradle how to read these secrets. Open your app/build.gradle.kts and add this logic. This approach is “fail-safe”—it won’t crash your IDE if the keys are missing; it will simply skip signing.

import java.util.Properties
import java.io.FileInputStream

// 1. Safely load the properties file
val keystoreProperties = Properties().apply {
    val propertiesFile = rootProject.file("local.properties")
    if (propertiesFile.exists()) {
        propertiesFile.inputStream().use { load(it) }
    }
}

android {
    signingConfigs {
        create("release") {
            // 2. Map the properties to the signing config
            val path = keystoreProperties["RELEASE_STORE_PATH"] as String?
            if (!path.isNullOrEmpty()) {
                storeFile = file(path)
                storePassword = keystoreProperties["RELEASE_STORE_PASSWORD"] as String?
                keyAlias = keystoreProperties["RELEASE_KEY_ALIAS"] as String?
                keyPassword = keystoreProperties["RELEASE_KEY_PASSWORD"] as String?
            }
        }
    }

    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            // 3. Attach the config to the release build
            signingConfig = signingConfigs.getByName("release")
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}

4. Final Security Checklist

✅ The .gitignore Check

Ensure your .gitignore in the project root includes these lines:

local.properties
*.jks
*.keystore

✅ The Backup Rule

Since your keystore is now only on your local machine, it is vulnerable to hardware failure.

Warning: If you lose your production keystore, you cannot update your app on the Google Play Store. Period.

Back it up to a encrypted physical drive or a secure password manager like Bitwarden or 1Password.

✅ The “Fail-Soft” Benefit

By using the if (!path.isNullOrEmpty()) check in your Gradle file, other developers (or you on a different machine) can still clone the project and run the debug version without needing your private secrets.

Summary

By moving the file out of the project and using local.properties to bridge the gap, you create a workflow that is both convenient and bulletproof. Keep your keys close, and your source code closer!