mirror of
https://github.com/ReVanced/revanced-library.git
synced 2026-01-11 05:46:17 +00:00
chore: Merge branch dev to main (#38)
This commit is contained in:
28
CHANGELOG.md
28
CHANGELOG.md
@@ -1,3 +1,31 @@
|
||||
# [2.3.0-dev.3](https://github.com/ReVanced/revanced-library/compare/v2.3.0-dev.2...v2.3.0-dev.3) (2024-03-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Improve exception message ([b15efa4](https://github.com/ReVanced/revanced-library/commit/b15efa41f8dc7d73865d0eab15be274b9ee3d7a3))
|
||||
|
||||
# [2.3.0-dev.2](https://github.com/ReVanced/revanced-library/compare/v2.3.0-dev.1...v2.3.0-dev.2) (2024-03-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Simplify signing utility API ([4c6a636](https://github.com/ReVanced/revanced-library/commit/4c6a6360cf83659d1f5c3a7c5710ac54426e9235))
|
||||
|
||||
# [2.3.0-dev.1](https://github.com/ReVanced/revanced-library/compare/v2.2.2-dev.1...v2.3.0-dev.1) (2024-03-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add utility function around key certificate pairs ([2df3484](https://github.com/ReVanced/revanced-library/commit/2df3484b68ed72338a52e76fb4b7ceb9c9c644ed))
|
||||
|
||||
## [2.2.2-dev.1](https://github.com/ReVanced/revanced-library/compare/v2.2.1...v2.2.2-dev.1) (2024-03-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Support mounting even when Magisk is not installed ([2a30845](https://github.com/ReVanced/revanced-library/commit/2a30845f61d5f77ded7a72ee3d6ab55b4c512d52))
|
||||
|
||||
## [2.2.1](https://github.com/ReVanced/revanced-library/compare/v2.2.0...v2.2.1) (2024-03-09)
|
||||
|
||||
|
||||
|
||||
@@ -7,14 +7,13 @@ public final class app/revanced/library/ApkSigner {
|
||||
public final fun newKeyStore (Ljava/io/OutputStream;Ljava/lang/String;Ljava/util/Set;)V
|
||||
public final fun newKeyStore (Ljava/util/Set;)Ljava/security/KeyStore;
|
||||
public final fun newPrivateKeyCertificatePair (Ljava/lang/String;Ljava/util/Date;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||
public static synthetic fun newPrivateKeyCertificatePair$default (Lapp/revanced/library/ApkSigner;Ljava/lang/String;Ljava/util/Date;ILjava/lang/Object;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||
public final fun readKeyCertificatePair (Ljava/security/KeyStore;Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||
public final fun readKeyStore (Ljava/io/InputStream;Ljava/lang/String;)Ljava/security/KeyStore;
|
||||
public final fun readPrivateKeyCertificatePair (Ljava/security/KeyStore;Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||
}
|
||||
|
||||
public final class app/revanced/library/ApkSigner$KeyStoreEntry {
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getAlias ()Ljava/lang/String;
|
||||
public final fun getPassword ()Ljava/lang/String;
|
||||
public final fun getPrivateKeyCertificatePair ()Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
||||
@@ -35,8 +34,29 @@ public final class app/revanced/library/ApkSigner$Signer {
|
||||
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 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 class app/revanced/library/ApkUtils$KeyStoreDetails {
|
||||
public fun <init> (Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
|
||||
public synthetic fun <init> (Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getAlias ()Ljava/lang/String;
|
||||
public final fun getKeyStore ()Ljava/io/File;
|
||||
public final fun getKeyStorePassword ()Ljava/lang/String;
|
||||
public final fun getPassword ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class app/revanced/library/ApkUtils$PrivateKeyCertificatePairDetails {
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/String;Ljava/util/Date;)V
|
||||
public synthetic fun <init> (Ljava/lang/String;Ljava/util/Date;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getCommonName ()Ljava/lang/String;
|
||||
public final fun getValidUntil ()Ljava/util/Date;
|
||||
}
|
||||
|
||||
public final class app/revanced/library/ApkUtils$SigningOptions {
|
||||
|
||||
@@ -54,6 +54,8 @@ kotlin {
|
||||
|
||||
java {
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
publishing {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
org.gradle.parallel = true
|
||||
org.gradle.caching = true
|
||||
kotlin.code.style = official
|
||||
version = 2.2.1
|
||||
version = 2.3.0-dev.3
|
||||
|
||||
@@ -19,7 +19,6 @@ import java.security.*
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.*
|
||||
import java.util.logging.Logger
|
||||
import kotlin.time.Duration.Companion.days
|
||||
|
||||
/**
|
||||
* Utility class for reading or writing keystore files and entries as well as signing APK files.
|
||||
@@ -34,17 +33,80 @@ object ApkSigner {
|
||||
}
|
||||
}
|
||||
|
||||
private fun newKeyStoreInstance() = KeyStore.getInstance("BKS", BouncyCastleProvider.PROVIDER_NAME)
|
||||
|
||||
/**
|
||||
* Create a new [PrivateKeyCertificatePair].
|
||||
* Create a new keystore with a new keypair.
|
||||
*
|
||||
* @param entries The entries to add to the keystore.
|
||||
*
|
||||
* @return The created keystore.
|
||||
*
|
||||
* @see KeyStoreEntry
|
||||
* @see KeyStore
|
||||
*/
|
||||
fun newKeyStore(entries: Set<KeyStoreEntry>): KeyStore {
|
||||
logger.fine("Creating keystore")
|
||||
|
||||
return newKeyStoreInstance().apply {
|
||||
load(null)
|
||||
|
||||
entries.forEach { entry ->
|
||||
// Add all entries to the keystore.
|
||||
setKeyEntry(
|
||||
entry.alias,
|
||||
entry.privateKeyCertificatePair.privateKey,
|
||||
entry.password.toCharArray(),
|
||||
arrayOf(entry.privateKeyCertificatePair.certificate),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a keystore from the given [keyStoreInputStream].
|
||||
*
|
||||
* @param keyStoreInputStream The stream to read the keystore from.
|
||||
* @param keyStorePassword The password for the keystore.
|
||||
*
|
||||
* @return The keystore.
|
||||
*
|
||||
* @throws IllegalArgumentException If the keystore password is invalid.
|
||||
*
|
||||
* @see KeyStore
|
||||
*/
|
||||
fun readKeyStore(
|
||||
keyStoreInputStream: InputStream,
|
||||
keyStorePassword: String?,
|
||||
): KeyStore {
|
||||
logger.fine("Reading keystore")
|
||||
|
||||
return newKeyStoreInstance().apply {
|
||||
try {
|
||||
load(keyStoreInputStream, keyStorePassword?.toCharArray())
|
||||
} catch (exception: IOException) {
|
||||
if (exception.cause is UnrecoverableKeyException) {
|
||||
throw IllegalArgumentException("Invalid keystore password")
|
||||
} else {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new private key and certificate pair.
|
||||
*
|
||||
* @param commonName The common name of the certificate.
|
||||
* @param validUntil The date until the certificate is valid.
|
||||
* @param validUntil The date until which the certificate is valid.
|
||||
*
|
||||
* @return The created [PrivateKeyCertificatePair].
|
||||
* @return The newly created private key and certificate pair.
|
||||
*
|
||||
* @see PrivateKeyCertificatePair
|
||||
*/
|
||||
fun newPrivateKeyCertificatePair(
|
||||
commonName: String = "ReVanced",
|
||||
validUntil: Date = Date(System.currentTimeMillis() + (365.days * 8).inWholeMilliseconds * 24),
|
||||
commonName: String,
|
||||
validUntil: Date,
|
||||
): PrivateKeyCertificatePair {
|
||||
logger.fine("Creating certificate for $commonName")
|
||||
|
||||
@@ -80,8 +142,11 @@ object ApkSigner {
|
||||
* @return The read [PrivateKeyCertificatePair].
|
||||
*
|
||||
* @throws IllegalArgumentException If the keystore does not contain the given alias or the password is invalid.
|
||||
*
|
||||
* @see PrivateKeyCertificatePair
|
||||
* @see KeyStore
|
||||
*/
|
||||
fun readKeyCertificatePair(
|
||||
fun readPrivateKeyCertificatePair(
|
||||
keyStore: KeyStore,
|
||||
keyStoreEntryAlias: String,
|
||||
keyStoreEntryPassword: String,
|
||||
@@ -89,7 +154,7 @@ object ApkSigner {
|
||||
logger.fine("Reading key and certificate pair from keystore entry $keyStoreEntryAlias")
|
||||
|
||||
if (!keyStore.containsAlias(keyStoreEntryAlias)) {
|
||||
throw IllegalArgumentException("Keystore does not contain alias $keyStoreEntryAlias")
|
||||
throw IllegalArgumentException("Keystore does not contain entry with alias $keyStoreEntryAlias")
|
||||
}
|
||||
|
||||
// Read the private key and certificate from the keystore.
|
||||
@@ -106,80 +171,6 @@ object ApkSigner {
|
||||
return PrivateKeyCertificatePair(privateKey, certificate)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new keystore with a new keypair.
|
||||
*
|
||||
* @param entries The entries to add to the keystore.
|
||||
*
|
||||
* @return The created keystore.
|
||||
*
|
||||
* @see KeyStoreEntry
|
||||
*/
|
||||
fun newKeyStore(entries: Set<KeyStoreEntry>): KeyStore {
|
||||
logger.fine("Creating keystore")
|
||||
|
||||
return newKeyStoreInstance().apply {
|
||||
load(null)
|
||||
|
||||
entries.forEach { entry ->
|
||||
// Add all entries to the keystore.
|
||||
setKeyEntry(
|
||||
entry.alias,
|
||||
entry.privateKeyCertificatePair.privateKey,
|
||||
entry.password.toCharArray(),
|
||||
arrayOf(entry.privateKeyCertificatePair.certificate),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun newKeyStoreInstance() = KeyStore.getInstance("BKS", BouncyCastleProvider.PROVIDER_NAME)
|
||||
|
||||
/**
|
||||
* Create a new keystore with a new keypair and saves it to the given [keyStoreOutputStream].
|
||||
*
|
||||
* @param keyStoreOutputStream The stream to write the keystore to.
|
||||
* @param keyStorePassword The password for the keystore.
|
||||
* @param entries The entries to add to the keystore.
|
||||
*/
|
||||
fun newKeyStore(
|
||||
keyStoreOutputStream: OutputStream,
|
||||
keyStorePassword: String,
|
||||
entries: Set<KeyStoreEntry>,
|
||||
) = newKeyStore(entries).store(
|
||||
keyStoreOutputStream,
|
||||
keyStorePassword.toCharArray(),
|
||||
)
|
||||
|
||||
/**
|
||||
* Read a keystore from the given [keyStoreInputStream].
|
||||
*
|
||||
* @param keyStoreInputStream The stream to read the keystore from.
|
||||
* @param keyStorePassword The password for the keystore.
|
||||
*
|
||||
* @return The keystore.
|
||||
*
|
||||
* @throws IllegalArgumentException If the keystore password is invalid.
|
||||
*/
|
||||
fun readKeyStore(
|
||||
keyStoreInputStream: InputStream,
|
||||
keyStorePassword: String?,
|
||||
): KeyStore {
|
||||
logger.fine("Reading keystore")
|
||||
|
||||
return newKeyStoreInstance().apply {
|
||||
try {
|
||||
load(keyStoreInputStream, keyStorePassword?.toCharArray())
|
||||
} catch (exception: IOException) {
|
||||
if (exception.cause is UnrecoverableKeyException) {
|
||||
throw IllegalArgumentException("Invalid keystore password")
|
||||
} else {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new [Signer].
|
||||
*
|
||||
@@ -206,6 +197,41 @@ object ApkSigner {
|
||||
),
|
||||
)
|
||||
|
||||
/**
|
||||
* Read a [PrivateKeyCertificatePair] from a keystore entry.
|
||||
*
|
||||
* @param keyStore The keystore to read the entry from.
|
||||
* @param keyStoreEntryAlias The alias of the key store entry to read.
|
||||
* @param keyStoreEntryPassword The password for recovering the signing key.
|
||||
*
|
||||
* @return The read [PrivateKeyCertificatePair].
|
||||
*
|
||||
* @throws IllegalArgumentException If the keystore does not contain the given alias or the password is invalid.
|
||||
*/
|
||||
@Deprecated("This method will be removed in the future.")
|
||||
fun readKeyCertificatePair(
|
||||
keyStore: KeyStore,
|
||||
keyStoreEntryAlias: String,
|
||||
keyStoreEntryPassword: String,
|
||||
) = readPrivateKeyCertificatePair(keyStore, keyStoreEntryAlias, keyStoreEntryPassword)
|
||||
|
||||
/**
|
||||
* Create a new keystore with a new keypair and saves it to the given [keyStoreOutputStream].
|
||||
*
|
||||
* @param keyStoreOutputStream The stream to write the keystore to.
|
||||
* @param keyStorePassword The password for the keystore.
|
||||
* @param entries The entries to add to the keystore.
|
||||
*/
|
||||
@Deprecated("This method will be removed in the future.")
|
||||
fun newKeyStore(
|
||||
keyStoreOutputStream: OutputStream,
|
||||
keyStorePassword: String?,
|
||||
entries: Set<KeyStoreEntry>,
|
||||
) = newKeyStore(entries).store(
|
||||
keyStoreOutputStream,
|
||||
keyStorePassword?.toCharArray(),
|
||||
)
|
||||
|
||||
/**
|
||||
* Create a new [Signer].
|
||||
*
|
||||
@@ -216,13 +242,7 @@ object ApkSigner {
|
||||
* @see PrivateKeyCertificatePair
|
||||
* @see Signer
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated(
|
||||
"This method will be removed in the future.",
|
||||
ReplaceWith(
|
||||
"newApkSigner(\"ReVanced\", privateKeyCertificatePair)",
|
||||
),
|
||||
)
|
||||
@Deprecated("This method will be removed in the future.")
|
||||
fun newApkSigner(privateKeyCertificatePair: PrivateKeyCertificatePair) =
|
||||
Signer(
|
||||
SigningExtension(
|
||||
@@ -249,6 +269,7 @@ object ApkSigner {
|
||||
* @see KeyStore
|
||||
* @see Signer
|
||||
*/
|
||||
@Deprecated("This method will be removed in the future.")
|
||||
fun newApkSigner(
|
||||
signer: String,
|
||||
keyStore: KeyStore,
|
||||
@@ -268,13 +289,7 @@ object ApkSigner {
|
||||
* @see KeyStore
|
||||
* @see Signer
|
||||
*/
|
||||
@Deprecated(
|
||||
"This method will be removed in the future.",
|
||||
ReplaceWith(
|
||||
"newApkSigner(\"ReVanced\", readKeyCertificatePair(keyStore, keyStoreEntryAlias, keyStoreEntryPassword))",
|
||||
"app.revanced.library.ApkSigner.newApkSigner",
|
||||
),
|
||||
)
|
||||
@Deprecated("This method will be removed in the future.")
|
||||
fun newApkSigner(
|
||||
keyStore: KeyStore,
|
||||
keyStoreEntryAlias: String,
|
||||
@@ -293,7 +308,7 @@ object ApkSigner {
|
||||
class KeyStoreEntry(
|
||||
val alias: String,
|
||||
val password: String,
|
||||
val privateKeyCertificatePair: PrivateKeyCertificatePair = newPrivateKeyCertificatePair(),
|
||||
val privateKeyCertificatePair: PrivateKeyCertificatePair,
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -316,6 +331,12 @@ object ApkSigner {
|
||||
signingExtension = null
|
||||
}
|
||||
|
||||
fun signApk(inputApkFile: File, outputApkFile: File) {
|
||||
logger.info("Signing APK")
|
||||
|
||||
signerBuilder?.setInputApk(inputApkFile)?.setOutputApk(outputApkFile)?.build()?.sign()
|
||||
}
|
||||
|
||||
@Deprecated("This constructor will be removed in the future.")
|
||||
internal constructor(signingExtension: SigningExtension) {
|
||||
signerBuilder = null
|
||||
@@ -344,11 +365,5 @@ object ApkSigner {
|
||||
|
||||
signingExtension?.register(apkZFile)
|
||||
}
|
||||
|
||||
fun signApk(inputApkFile: File, outputApkFile: File) {
|
||||
logger.info("Signing APK")
|
||||
|
||||
signerBuilder?.setInputApk(inputApkFile)?.setOutputApk(outputApkFile)?.build()?.sign()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package app.revanced.library
|
||||
|
||||
import app.revanced.library.ApkSigner.newPrivateKeyCertificatePair
|
||||
import app.revanced.patcher.PatcherResult
|
||||
import com.android.tools.build.apkzlib.zip.AlignmentRules
|
||||
import com.android.tools.build.apkzlib.zip.StoredEntry
|
||||
import com.android.tools.build.apkzlib.zip.ZFile
|
||||
import com.android.tools.build.apkzlib.zip.ZFileOptions
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import java.util.logging.Logger
|
||||
import kotlin.time.Duration.Companion.days
|
||||
|
||||
/**
|
||||
* Utility functions to work with APK files.
|
||||
@@ -93,43 +96,129 @@ object ApkUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an existing or creates a new keystore.
|
||||
* Creates a new private key and certificate pair and saves it to the keystore in [keyStoreDetails].
|
||||
*
|
||||
* @param signingOptions The options to use for signing.
|
||||
* @param privateKeyCertificatePairDetails The details for the private key and certificate pair.
|
||||
* @param keyStoreDetails The details for the keystore.
|
||||
*
|
||||
* @return The newly created private key and certificate pair.
|
||||
*/
|
||||
private fun readOrNewKeyStore(signingOptions: SigningOptions) = if (signingOptions.keyStore.exists()) {
|
||||
ApkSigner.readKeyStore(
|
||||
signingOptions.keyStore.inputStream(),
|
||||
signingOptions.keyStorePassword ?: "",
|
||||
@Deprecated("This method will be removed in the future.")
|
||||
fun newPrivateKeyCertificatePair(
|
||||
privateKeyCertificatePairDetails: PrivateKeyCertificatePairDetails,
|
||||
keyStoreDetails: KeyStoreDetails,
|
||||
) = newPrivateKeyCertificatePair(
|
||||
privateKeyCertificatePairDetails.commonName,
|
||||
privateKeyCertificatePairDetails.validUntil,
|
||||
).also { privateKeyCertificatePair ->
|
||||
ApkSigner.newKeyStore(
|
||||
setOf(
|
||||
ApkSigner.KeyStoreEntry(
|
||||
keyStoreDetails.alias,
|
||||
keyStoreDetails.password,
|
||||
privateKeyCertificatePair,
|
||||
),
|
||||
),
|
||||
).store(
|
||||
keyStoreDetails.keyStore.outputStream(),
|
||||
keyStoreDetails.keyStorePassword?.toCharArray(),
|
||||
)
|
||||
} else {
|
||||
val entry = ApkSigner.KeyStoreEntry(signingOptions.alias, signingOptions.password)
|
||||
}
|
||||
|
||||
// Create a new keystore with a new keypair and saves it.
|
||||
ApkSigner.newKeyStore(setOf(entry)).apply {
|
||||
store(
|
||||
signingOptions.keyStore.outputStream(),
|
||||
signingOptions.keyStorePassword?.toCharArray(),
|
||||
)
|
||||
/**
|
||||
* Reads the private key and certificate pair from an existing keystore.
|
||||
*
|
||||
* @param keyStoreDetails The details for the keystore.
|
||||
*
|
||||
* @return The private key and certificate pair.
|
||||
*/
|
||||
@Deprecated("This method will be removed in the future.")
|
||||
fun readPrivateKeyCertificatePairFromKeyStore(
|
||||
keyStoreDetails: KeyStoreDetails,
|
||||
) = ApkSigner.readPrivateKeyCertificatePair(
|
||||
ApkSigner.readKeyStore(
|
||||
keyStoreDetails.keyStore.inputStream(),
|
||||
keyStoreDetails.keyStorePassword,
|
||||
),
|
||||
keyStoreDetails.alias,
|
||||
keyStoreDetails.password,
|
||||
)
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
fun signApk(
|
||||
inputApkFile: File,
|
||||
outputApkFile: File,
|
||||
signer: String,
|
||||
keyStoreDetails: KeyStoreDetails,
|
||||
) = ApkSigner.newApkSigner(
|
||||
signer,
|
||||
if (keyStoreDetails.keyStore.exists()) {
|
||||
readPrivateKeyCertificatePairFromKeyStore(keyStoreDetails)
|
||||
} else {
|
||||
newPrivateKeyCertificatePair(PrivateKeyCertificatePairDetails(), keyStoreDetails)
|
||||
},
|
||||
).signApk(inputApkFile, outputApkFile)
|
||||
|
||||
@Deprecated("This method will be removed in the future.")
|
||||
private fun readOrNewPrivateKeyCertificatePair(
|
||||
signingOptions: SigningOptions,
|
||||
): ApkSigner.PrivateKeyCertificatePair {
|
||||
val privateKeyCertificatePairDetails = PrivateKeyCertificatePairDetails(
|
||||
signingOptions.alias,
|
||||
PrivateKeyCertificatePairDetails().validUntil,
|
||||
)
|
||||
val keyStoreDetails = KeyStoreDetails(
|
||||
signingOptions.keyStore,
|
||||
signingOptions.keyStorePassword,
|
||||
signingOptions.alias,
|
||||
signingOptions.password,
|
||||
)
|
||||
|
||||
return if (keyStoreDetails.keyStore.exists()) {
|
||||
readPrivateKeyCertificatePairFromKeyStore(keyStoreDetails)
|
||||
} else {
|
||||
newPrivateKeyCertificatePair(privateKeyCertificatePairDetails, keyStoreDetails)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs [inputApkFile] with the given options and saves the signed apk to [outputApkFile].
|
||||
*
|
||||
* @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 privateKeyCertificatePair The private key and certificate pair to use for signing.
|
||||
*/
|
||||
@Deprecated("This method will be removed in the future.")
|
||||
fun sign(
|
||||
inputApkFile: File,
|
||||
outputApkFile: File,
|
||||
signer: String,
|
||||
privateKeyCertificatePair: ApkSigner.PrivateKeyCertificatePair,
|
||||
) = ApkSigner.newApkSigner(
|
||||
signer,
|
||||
privateKeyCertificatePair,
|
||||
).signApk(inputApkFile, outputApkFile)
|
||||
|
||||
/**
|
||||
* Signs the apk file with the given options.
|
||||
*
|
||||
* @param signingOptions The options to use for signing.
|
||||
*/
|
||||
@Deprecated("Use sign(File, File, SigningOptions) instead.")
|
||||
fun File.sign(signingOptions: SigningOptions) {
|
||||
val keyStore = readOrNewKeyStore(signingOptions)
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
ApkSigner.newApkSigner(
|
||||
keyStore,
|
||||
signingOptions.alias,
|
||||
signingOptions.password,
|
||||
).signApk(this)
|
||||
}
|
||||
@Deprecated("This method will be removed in the future.")
|
||||
fun File.sign(signingOptions: SigningOptions) = ApkSigner.newApkSigner(
|
||||
signingOptions.signer,
|
||||
readOrNewPrivateKeyCertificatePair(signingOptions),
|
||||
).signApk(this)
|
||||
|
||||
/**
|
||||
* Signs [inputApkFile] with the given options and saves the signed apk to [outputApkFile].
|
||||
@@ -138,16 +227,13 @@ object ApkUtils {
|
||||
* @param outputApkFile The file to save the signed apk to.
|
||||
* @param signingOptions The options to use for signing.
|
||||
*/
|
||||
fun sign(inputApkFile: File, outputApkFile: File, signingOptions: SigningOptions) {
|
||||
val keyStore = readOrNewKeyStore(signingOptions)
|
||||
|
||||
ApkSigner.newApkSigner(
|
||||
signingOptions.signer,
|
||||
keyStore,
|
||||
signingOptions.alias,
|
||||
signingOptions.password,
|
||||
).signApk(inputApkFile, outputApkFile)
|
||||
}
|
||||
@Deprecated("This method will be removed in the future.")
|
||||
fun sign(inputApkFile: File, outputApkFile: File, signingOptions: SigningOptions) = sign(
|
||||
inputApkFile,
|
||||
outputApkFile,
|
||||
signingOptions.signer,
|
||||
readOrNewPrivateKeyCertificatePair(signingOptions),
|
||||
)
|
||||
|
||||
/**
|
||||
* Options for signing an apk.
|
||||
@@ -158,6 +244,7 @@ object ApkUtils {
|
||||
* @param password The password for recovering the signing key.
|
||||
* @param signer The name of the signer.
|
||||
*/
|
||||
@Deprecated("This class will be removed in the future.")
|
||||
class SigningOptions(
|
||||
val keyStore: File,
|
||||
val keyStorePassword: String?,
|
||||
@@ -165,4 +252,30 @@ object ApkUtils {
|
||||
val password: String = "",
|
||||
val signer: String = "ReVanced",
|
||||
)
|
||||
|
||||
/**
|
||||
* Details for a keystore.
|
||||
*
|
||||
* @param keyStore The file to save the keystore to.
|
||||
* @param keyStorePassword The password for the keystore.
|
||||
* @param alias The alias of the key store entry to use for signing.
|
||||
* @param password The password for recovering the signing key.
|
||||
*/
|
||||
class KeyStoreDetails(
|
||||
val keyStore: File,
|
||||
val keyStorePassword: String? = null,
|
||||
val alias: String = "ReVanced Key",
|
||||
val password: String = "",
|
||||
)
|
||||
|
||||
/**
|
||||
* Details for a private key and certificate pair.
|
||||
*
|
||||
* @param commonName The common name for the certificate saved in the keystore.
|
||||
* @param validUntil The date until which the certificate is valid.
|
||||
*/
|
||||
class PrivateKeyCertificatePairDetails(
|
||||
val commonName: String = "ReVanced",
|
||||
val validUntil: Date = Date(System.currentTimeMillis() + (365.days * 8).inWholeMilliseconds * 24),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -29,13 +29,17 @@ internal object Constants {
|
||||
internal val MOUNT_SCRIPT =
|
||||
"""
|
||||
#!/system/bin/sh
|
||||
MAGISKTMP="$( magisk --path )" || MAGISKTMP=/sbin
|
||||
MIRROR="${'$'}MAGISKTMP/.magisk/mirror"
|
||||
|
||||
# Use Magisk mirror, if possible.
|
||||
if command -v magisk &> /dev/null; then
|
||||
MIRROR="${'$'}(magisk --path)/.magisk/mirror"
|
||||
fi
|
||||
|
||||
# Wait for the system to boot.
|
||||
until [ "$( getprop sys.boot_completed )" = 1 ]; do sleep 3; done
|
||||
until [ -d "/sdcard/Android" ]; do sleep 1; done
|
||||
|
||||
# Unmount any existing mount as a safety measure
|
||||
# Unmount any existing mount as a safety measure.
|
||||
$UMOUNT
|
||||
|
||||
base_path="$PATCHED_APK_PATH"
|
||||
@@ -44,7 +48,7 @@ internal object Constants {
|
||||
chcon u:object_r:apk_data_file:s0 ${'$'}base_path
|
||||
mount -o bind ${'$'}MIRROR${'$'}base_path ${'$'}stock_path
|
||||
|
||||
# Kill the app to force it to restart the mounted APK in case it's already running
|
||||
# Kill the app to force it to restart the mounted APK in case it's currently running.
|
||||
$KILL
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user