Skip to content

feat: Support customize signing levels #49

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions api/android/revanced-library.api
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,20 @@ public final class app/revanced/library/ApkSigner$Signer {
public final fun signApk (Lcom/android/tools/build/apkzlib/zip/ZFile;)V
public final fun signApk (Ljava/io/File;)V
public final fun signApk (Ljava/io/File;Ljava/io/File;)V
public final fun signApk (Ljava/io/File;Ljava/io/File;Ljava/util/Set;)V
}

public final class app/revanced/library/ApkUtils {
public static final field INSTANCE Lapp/revanced/library/ApkUtils;
public final fun applyTo (Lapp/revanced/patcher/PatcherResult;Ljava/io/File;)V
public final fun newPrivateKeyCertificatePair (Lapp/revanced/library/ApkUtils$PrivateKeyCertificatePairDetails;Lapp/revanced/library/ApkUtils$KeyStoreDetails;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
public final fun readPrivateKeyCertificatePairFromKeyStore (Lapp/revanced/library/ApkUtils$KeyStoreDetails;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
public final fun readSigningLevels (Ljava/io/File;)Ljava/util/Set;
public final fun sign (Ljava/io/File;Lapp/revanced/library/ApkUtils$SigningOptions;)V
public final fun sign (Ljava/io/File;Ljava/io/File;Lapp/revanced/library/ApkUtils$SigningOptions;)V
public final fun sign (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)V
public final fun signApk (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Lapp/revanced/library/ApkUtils$KeyStoreDetails;)V
public final fun signApk (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Lapp/revanced/library/ApkUtils$KeyStoreDetails;Ljava/util/Set;)V
}

public final class app/revanced/library/ApkUtils$KeyStoreDetails {
Expand Down
3 changes: 3 additions & 0 deletions api/jvm/revanced-library.api
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,20 @@ public final class app/revanced/library/ApkSigner$Signer {
public final fun signApk (Lcom/android/tools/build/apkzlib/zip/ZFile;)V
public final fun signApk (Ljava/io/File;)V
public final fun signApk (Ljava/io/File;Ljava/io/File;)V
public final fun signApk (Ljava/io/File;Ljava/io/File;Ljava/util/Set;)V
}

public final class app/revanced/library/ApkUtils {
public static final field INSTANCE Lapp/revanced/library/ApkUtils;
public final fun applyTo (Lapp/revanced/patcher/PatcherResult;Ljava/io/File;)V
public final fun newPrivateKeyCertificatePair (Lapp/revanced/library/ApkUtils$PrivateKeyCertificatePairDetails;Lapp/revanced/library/ApkUtils$KeyStoreDetails;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
public final fun readPrivateKeyCertificatePairFromKeyStore (Lapp/revanced/library/ApkUtils$KeyStoreDetails;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
public final fun readSigningLevels (Ljava/io/File;)Ljava/util/Set;
public final fun sign (Ljava/io/File;Lapp/revanced/library/ApkUtils$SigningOptions;)V
public final fun sign (Ljava/io/File;Ljava/io/File;Lapp/revanced/library/ApkUtils$SigningOptions;)V
public final fun sign (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)V
public final fun signApk (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Lapp/revanced/library/ApkUtils$KeyStoreDetails;)V
public final fun signApk (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Lapp/revanced/library/ApkUtils$KeyStoreDetails;Ljava/util/Set;)V
}

public final class app/revanced/library/ApkUtils$KeyStoreDetails {
Expand Down
14 changes: 13 additions & 1 deletion src/commonMain/kotlin/app/revanced/library/ApkSigner.kt
Original file line number Diff line number Diff line change
Expand Up @@ -331,12 +331,24 @@ object ApkSigner {
signingExtension = null
}

fun signApk(inputApkFile: File, outputApkFile: File) {
fun signApk(inputApkFile: File, outputApkFile: File, signingLevels: Set<Int>) {
logger.info("Signing APK")

if (signingLevels.isNotEmpty() && signerBuilder != null) {
signerBuilder.setV1SigningEnabled(signingLevels.contains(1))
signerBuilder.setV2SigningEnabled(signingLevels.contains(2))
signerBuilder.setV3SigningEnabled(signingLevels.contains(3))
signerBuilder.setV4SigningEnabled(signingLevels.contains(4))
}

signerBuilder?.setInputApk(inputApkFile)?.setOutputApk(outputApkFile)?.build()?.sign()
}

@Deprecated("This constructor will be removed in the future.")
fun signApk(inputApkFile: File, outputApkFile: File) {
signApk(inputApkFile, outputApkFile, setOf())
}

@Deprecated("This constructor will be removed in the future.")
internal constructor(signingExtension: SigningExtension) {
signerBuilder = null
Expand Down
44 changes: 43 additions & 1 deletion src/commonMain/kotlin/app/revanced/library/ApkUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package app.revanced.library

import app.revanced.library.ApkSigner.newPrivateKeyCertificatePair
import app.revanced.patcher.PatcherResult
import com.android.apksig.ApkVerifier
import com.android.tools.build.apkzlib.zip.AlignmentRules
import com.android.tools.build.apkzlib.zip.StoredEntry
import com.android.tools.build.apkzlib.zip.ZFile
Expand Down Expand Up @@ -153,20 +154,40 @@ object ApkUtils {
* @param outputApkFile The file to save the signed apk to.
* @param signer The name of the signer.
* @param keyStoreDetails The details for the keystore.
* @param signingLevels Signature levels, empty to default.
*/
fun signApk(
inputApkFile: File,
outputApkFile: File,
signer: String,
keyStoreDetails: KeyStoreDetails,
signingLevels: Set<Int>,
) = ApkSigner.newApkSigner(
signer,
if (keyStoreDetails.keyStore.exists()) {
readPrivateKeyCertificatePairFromKeyStore(keyStoreDetails)
} else {
newPrivateKeyCertificatePair(PrivateKeyCertificatePairDetails(), keyStoreDetails)
},
).signApk(inputApkFile, outputApkFile)
).signApk(inputApkFile, outputApkFile, signingLevels)

/**
* Signs [inputApkFile] with the given options and saves the signed apk to [outputApkFile].
* If [KeyStoreDetails.keyStore] does not exist,
* a new private key and certificate pair will be created and saved to the keystore.
*
* @param inputApkFile The apk file to sign.
* @param outputApkFile The file to save the signed apk to.
* @param signer The name of the signer.
* @param keyStoreDetails The details for the keystore.
*/
@Deprecated("This method will be removed in the future.")
fun signApk(
inputApkFile: File,
outputApkFile: File,
signer: String,
keyStoreDetails: KeyStoreDetails,
) = signApk(inputApkFile, outputApkFile, signer, keyStoreDetails, setOf())

@Deprecated("This method will be removed in the future.")
private fun readOrNewPrivateKeyCertificatePair(
Expand Down Expand Up @@ -235,6 +256,27 @@ object ApkUtils {
readOrNewPrivateKeyCertificatePair(signingOptions),
)

/**
* Read apk signature levels.
*
* Note: a well-signed apk is required.
*/
fun readSigningLevels(apkFile: File): Set<Int> {
val verify = ApkVerifier.Builder(apkFile).build().verify()
if (!verify.isVerified)
return setOf()
val result = mutableSetOf<Int>()
if (verify.v1SchemeSigners.isNotEmpty())
result.add(1)
if (verify.v2SchemeSigners.isNotEmpty())
result.add(2)
if (verify.v3SchemeSigners.isNotEmpty())
result.add(3)
if (verify.v4SchemeSigners.isNotEmpty())
result.add(4)
return result
}

/**
* Options for signing an apk.
*
Expand Down