Skip to content

Commit

Permalink
Merge pull request #3 from Keyri-Co/fix/extension_arguments
Browse files Browse the repository at this point in the history
Updated README, fixed params, changed APK path to App Bundle path, ch…
  • Loading branch information
AndrewKuliahin96 authored Jan 18, 2024
2 parents 5828fde + 4e32bb3 commit 94439c6
Show file tree
Hide file tree
Showing 12 changed files with 89 additions and 62 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ jobs:
distribution: 'adopt'
java-version: '17'

- name: Make gradlew executable
run: chmod +x ./gradlew

- name: lint
run: ./gradlew ktlint

- name: CheckStyle
run: ./gradlew checkJavaStyle
2 changes: 1 addition & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,29 @@ apply(plugin = "com.keyri.checksumchecker.plugin")

### **Usage**

[//]: # (TODO: Add implementation)
Add `keyriChecker` extension to your app `build.gradle` file:

```kotlin
android {
defaultConfig {
// ...
versionName = "1.0"
}

keyriChecker {
appKey = "[Your appKey]"
versionName = defaultConfig.versionName
bundleFullPath = "full/path/to/your/bundle"
}

// ...
}
```

After generating bundle call `keyriChecksumCheck` task:

```shell
./gradlew keyriChecksumCheck
```

This will calculate bundle checksum and automatically send it to server for next checks.
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ buildscript {

dependencies {
classpath("com.android.tools.build:gradle:8.2.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.22")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.20")
}
}

allprojects {
val kotlinLint by configurations.creating

dependencies {
kotlinLint("com.pinterest:ktlint:1.1.1") {
kotlinLint("com.pinterest:ktlint:0.50.0") {
attributes {
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
}
Expand Down
5 changes: 3 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#Thu Jan 18 15:24:44 EET 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
zipStorePath=wrapper/dists
8 changes: 8 additions & 0 deletions local.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Thu Jan 18 14:56:34 EET 2024
sdk.dir=C\:\\Users\\kulag\\AppData\\Local\\Android\\Sdk
13 changes: 6 additions & 7 deletions plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,18 @@ group = "com.keyri"
version = System.getenv("GRADLE_PUBLISH_VERSION")

gradlePlugin {
website.set("https://github.com/Keyri-Co/keyri-checksum-checker-plugin")
vcsUrl.set("https://github.com/Keyri-Co/keyri-checksum-checker-plugin.git")

plugins {
create("KeyriChecksumCheckerPlugin") {
id = "com.keyri.checksumchecker.plugin"
displayName = "Keyri Checksum Checker Plugin"
description =
"Gradle plugin for Android project to get and upload APK files checksums on Keyri. This should increase code tampering protection."
"Gradle plugin for Android project to get and upload App Bundle files checksums on Keyri. This should increase code tampering protection."
implementationClass = "com.keyri.checksumchecker.plugin.KeyriChecksumCheckerPlugin"

tags.set(listOf("Android", "Bundle", "Kotlin", "Security"))
}
}
}

pluginBundle {
website = "https://github.com/Keyri-Co/keyri-checksum-checker-plugin"
vcsUrl = "https://github.com/Keyri-Co/keyri-checksum-checker-plugin.git"
tags = listOf("Android", "APK", "Kotlin", "Security")
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package com.keyri.checksumchecker.plugin

open class KeyriCheckerExtension {
// TODO: Merge with bundle path
var apkFullPath: String? = null
// TODO: Replace with build version
var apkID: String? = null
var bundleFullPath: String? = null
var versionName: String? = null
var appKey: String? = null
internal set
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,54 @@ package com.keyri.checksumchecker.plugin

import com.google.gson.JsonArray
import com.google.gson.JsonObject
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction
import java.io.File
import java.net.HttpURLConnection
import java.net.URL
import java.security.MessageDigest
import java.util.*
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction


abstract class KeyriChecksumCheckTask : DefaultTask() {

@Internal
var appKey: String? = null

@Internal
var apkID: String? = null
var versionName: String? = null

@TaskAction
fun run() {
val apkPath = getApkPath()
val payload = getAPKChecksumsPayload(apkPath)
val bundlePath = getBundlePath()
val payload = getBundleChecksumsPayload(bundlePath)

uploadChecksums(payload)
}

private fun getApkPath(): String {
private fun getBundlePath(): String {
val keyriCheckerExt = project.extensions.getByType(KeyriCheckerExtension::class.java)

appKey = keyriCheckerExt.appKey ?: throw GradleException("You should provide valid App Key")
apkID = keyriCheckerExt.apkID ?: throw GradleException("You should provide valid APK ID")
appKey = keyriCheckerExt.appKey ?: throw GradleException("You should provide valid appKey")
versionName = keyriCheckerExt.versionName
?: throw GradleException("You should provide valid versionName")

return keyriCheckerExt.apkFullPath?.takeIf { File(it).exists() }
?: throw GradleException("You should provide valid APK path")
return keyriCheckerExt.bundleFullPath?.takeIf { File(it).exists() }
?: throw GradleException("You should provide valid App Bundle path")
}

private fun getAPKChecksumsPayload(apkPath: String): JsonObject {
private fun getBundleChecksumsPayload(bundlePath: String): JsonObject {
val result = JsonObject()
val checksums = JsonArray()

try {
val apkFiles = project.zipTree(apkPath).files

// TODO: Single hash?
val bundleFiles = project.zipTree(bundlePath).files

var fileName = ""
var fileDigest = ""

apkFiles.firstOrNull { it.name == "MANIFEST.MF" }?.readLines()?.asSequence()
bundleFiles.firstOrNull { it.name == "MANIFEST.MF" }?.readLines()?.asSequence()
?.forEach { line ->
if (line.contains("Name:")) {
fileName = line.removePrefix("Name: ")
Expand All @@ -62,63 +60,61 @@ abstract class KeyriChecksumCheckTask : DefaultTask() {
}

if (fileName.isNotEmpty() && fileDigest.isNotEmpty()) {
val apkFileEntity = JsonObject()
val bundleFileEntity = JsonObject()

apkFileEntity.addProperty(fileName, fileDigest)
checksums.add(apkFileEntity)
bundleFileEntity.addProperty(fileName, fileDigest)
checksums.add(bundleFileEntity)

fileName = ""
fileDigest = ""
}
} ?: apkFiles.forEach { apkFile ->
val apkFileEntity = JsonObject()
} ?: bundleFiles.forEach { bundleFile ->
val bundleFileEntity = JsonObject()

apkFileEntity.addProperty(apkFile.name, apkFile.digestAndStringBase64())
checksums.add(apkFileEntity)
bundleFileEntity.addProperty(bundleFile.name, bundleFile.digestAndStringBase64())
checksums.add(bundleFileEntity)
}

println("Get ${checksums.size()} APK Checksums")
println("Get ${checksums.size()} Bundle Checksums")

result.addProperty("osType", "Android")
result.addProperty("apkPath", apkPath)
result.addProperty("apkID", apkID)
result.addProperty("bundlePath", bundlePath)
result.addProperty("versionName", versionName)

result.add("checksums", checksums)

return result
} catch (e: Exception) {
throw GradleException(e.message ?: "Failed to read APK files checksums")
throw GradleException(e.message ?: "Failed to read App Bundle files checksums")
}
}

// TODO: Send payload to Zain
private fun uploadChecksums(payload: JsonObject) {
try {
// TODO Add url
val connection = (URL("").openConnection() as? HttpURLConnection)?.apply {
requestMethod = "POST"
setRequestProperty("Content-Type", "application/json; charset=UTF-8")
setRequestProperty("appKey", appKey)
doOutput = true
}

connection?.outputStream?.use { outputStream ->
val input = payload.toString().toByteArray(Charsets.UTF_8)

outputStream.write(input, 0, input.size)
outputStream.write(payload.toString().toByteArray(Charsets.UTF_8))
}

if (connection?.responseCode == 200) {
val result = connection.inputStream?.readAllBytes()?.decodeToString()

println("APK Checksums uploaded: $result")
println("App Bundle Checksums uploaded: $result")
} else {
throw GradleException("Failed to send APK checksums request with message: " + connection?.responseMessage)
throw GradleException("Failed to send App Bundle checksums request with message: " + connection?.responseMessage)
}
} catch (e: Exception) {
if (e is GradleException) {
throw e
} else {
throw GradleException("Failed to send APK checksums request with message: " + e.message)
throw GradleException("Failed to send App Bundle checksums request with message: " + e.message)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import org.gradle.api.Project

class KeyriChecksumCheckerPlugin : Plugin<Project> {

override fun apply(target: Project) {
target.extensions.create("keyriChecker", KeyriCheckerExtension::class.java)
target.tasks.register("keyriChecksumCheck", KeyriChecksumCheckTask::class.java)
override fun apply(project: Project) {
project.extensions.create("keyriChecker", KeyriCheckerExtension::class.java)
project.tasks.register("keyriChecksumCheck", KeyriChecksumCheckTask::class.java)
}
}

0 comments on commit 94439c6

Please sign in to comment.