Skip to content

Instantly share code, notes, and snippets.

@Kr328
Created June 30, 2023 20:44
Show Gist options
  • Save Kr328/b7c450b420bbba50a7e93cd5d0adeecb to your computer and use it in GitHub Desktop.
Save Kr328/b7c450b420bbba50a7e93cd5d0adeecb to your computer and use it in GitHub Desktop.
BugReport decrypt tools for clash-multiplatform.
#!/usr/bin/env kotlin
/*
BugReport decrypt tools for clash-multiplatform.
Usage:
kotlin bugreport-decrypt.main.kts <path/to/signing.properties> <path/to/bugreport-archive>
Output:
<password of archive>
*/
@file:DependsOn("net.lingala.zip4j:zip4j:2.11.5")
import net.lingala.zip4j.ZipFile
import java.nio.file.Files
import java.nio.file.Path
import java.security.Key
import java.security.KeyStore
import java.util.*
import javax.crypto.Cipher
val signingPropPath = args.getOrNull(0) ?: throw IllegalArgumentException("signing.properties not found")
val archivePath = args.getOrNull(1) ?: throw IllegalArgumentException("archivePath not found")
val signingProp = Properties().also {
Files.newInputStream(Path.of(signingPropPath)).use { input ->
it.load(input)
}
}
val keystorePath = signingProp.getProperty("keystore.path") ?: throw IllegalArgumentException("keystore.path not found")
val keystorePassword = signingProp.getProperty("keystore.password") ?: throw IllegalArgumentException("keystore.password not found")
val keystore: KeyStore = KeyStore.getInstance(KeyStore.getDefaultType()).also {
Files.newInputStream(Path.of(keystorePath)).use { input ->
it.load(input, keystorePassword.toCharArray())
}
}
val keyAlias = signingProp.getProperty("key.alias") ?: throw IllegalArgumentException("key.alias not found")
val keyPassword = signingProp.getProperty("key.password") ?: throw IllegalArgumentException("key.password not found")
val key: Key = keystore.getKey(keyAlias, keystorePassword.toCharArray())
val cipher: Cipher = Cipher.getInstance(key.algorithm).also {
it.init(Cipher.DECRYPT_MODE, key)
}
val encryptedPassword = ZipFile(archivePath).use { zip ->
zip.comment.lines()
.map { it.split(":", limit = 2) }
.filter { it.size == 2 }
.associate { it[0].trim() to it[1].trim() }
.getOrElse("archive.password") {
throw IllegalArgumentException("$archivePath not a encrypted archive")
}
}
val password: ByteArray = cipher.doFinal(HexFormat.of().parseHex(encryptedPassword))
println(password.toString(Charsets.UTF_8))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment