mirror of
https://github.com/ReVanced/revanced-library.git
synced 2026-01-11 13:56: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)
|
## [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/io/OutputStream;Ljava/lang/String;Ljava/util/Set;)V
|
||||||
public final fun newKeyStore (Ljava/util/Set;)Ljava/security/KeyStore;
|
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 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 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 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 final class app/revanced/library/ApkSigner$KeyStoreEntry {
|
||||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)V
|
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 getAlias ()Ljava/lang/String;
|
||||||
public final fun getPassword ()Ljava/lang/String;
|
public final fun getPassword ()Ljava/lang/String;
|
||||||
public final fun getPrivateKeyCertificatePair ()Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;
|
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 final class app/revanced/library/ApkUtils {
|
||||||
public static final field INSTANCE Lapp/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 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;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;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 {
|
public final class app/revanced/library/ApkUtils$SigningOptions {
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ kotlin {
|
|||||||
|
|
||||||
java {
|
java {
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
|
||||||
|
withSourcesJar()
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
org.gradle.parallel = true
|
org.gradle.parallel = true
|
||||||
org.gradle.caching = true
|
org.gradle.caching = true
|
||||||
kotlin.code.style = official
|
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.security.cert.X509Certificate
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.logging.Logger
|
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.
|
* 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 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(
|
fun newPrivateKeyCertificatePair(
|
||||||
commonName: String = "ReVanced",
|
commonName: String,
|
||||||
validUntil: Date = Date(System.currentTimeMillis() + (365.days * 8).inWholeMilliseconds * 24),
|
validUntil: Date,
|
||||||
): PrivateKeyCertificatePair {
|
): PrivateKeyCertificatePair {
|
||||||
logger.fine("Creating certificate for $commonName")
|
logger.fine("Creating certificate for $commonName")
|
||||||
|
|
||||||
@@ -80,8 +142,11 @@ object ApkSigner {
|
|||||||
* @return The read [PrivateKeyCertificatePair].
|
* @return The read [PrivateKeyCertificatePair].
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException If the keystore does not contain the given alias or the password is invalid.
|
* @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,
|
keyStore: KeyStore,
|
||||||
keyStoreEntryAlias: String,
|
keyStoreEntryAlias: String,
|
||||||
keyStoreEntryPassword: String,
|
keyStoreEntryPassword: String,
|
||||||
@@ -89,7 +154,7 @@ object ApkSigner {
|
|||||||
logger.fine("Reading key and certificate pair from keystore entry $keyStoreEntryAlias")
|
logger.fine("Reading key and certificate pair from keystore entry $keyStoreEntryAlias")
|
||||||
|
|
||||||
if (!keyStore.containsAlias(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.
|
// Read the private key and certificate from the keystore.
|
||||||
@@ -106,80 +171,6 @@ object ApkSigner {
|
|||||||
return PrivateKeyCertificatePair(privateKey, certificate)
|
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].
|
* 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].
|
* Create a new [Signer].
|
||||||
*
|
*
|
||||||
@@ -216,13 +242,7 @@ object ApkSigner {
|
|||||||
* @see PrivateKeyCertificatePair
|
* @see PrivateKeyCertificatePair
|
||||||
* @see Signer
|
* @see Signer
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Deprecated("This method will be removed in the future.")
|
||||||
@Deprecated(
|
|
||||||
"This method will be removed in the future.",
|
|
||||||
ReplaceWith(
|
|
||||||
"newApkSigner(\"ReVanced\", privateKeyCertificatePair)",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
fun newApkSigner(privateKeyCertificatePair: PrivateKeyCertificatePair) =
|
fun newApkSigner(privateKeyCertificatePair: PrivateKeyCertificatePair) =
|
||||||
Signer(
|
Signer(
|
||||||
SigningExtension(
|
SigningExtension(
|
||||||
@@ -249,6 +269,7 @@ object ApkSigner {
|
|||||||
* @see KeyStore
|
* @see KeyStore
|
||||||
* @see Signer
|
* @see Signer
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("This method will be removed in the future.")
|
||||||
fun newApkSigner(
|
fun newApkSigner(
|
||||||
signer: String,
|
signer: String,
|
||||||
keyStore: KeyStore,
|
keyStore: KeyStore,
|
||||||
@@ -268,13 +289,7 @@ object ApkSigner {
|
|||||||
* @see KeyStore
|
* @see KeyStore
|
||||||
* @see Signer
|
* @see Signer
|
||||||
*/
|
*/
|
||||||
@Deprecated(
|
@Deprecated("This method will be removed in the future.")
|
||||||
"This method will be removed in the future.",
|
|
||||||
ReplaceWith(
|
|
||||||
"newApkSigner(\"ReVanced\", readKeyCertificatePair(keyStore, keyStoreEntryAlias, keyStoreEntryPassword))",
|
|
||||||
"app.revanced.library.ApkSigner.newApkSigner",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
fun newApkSigner(
|
fun newApkSigner(
|
||||||
keyStore: KeyStore,
|
keyStore: KeyStore,
|
||||||
keyStoreEntryAlias: String,
|
keyStoreEntryAlias: String,
|
||||||
@@ -293,7 +308,7 @@ object ApkSigner {
|
|||||||
class KeyStoreEntry(
|
class KeyStoreEntry(
|
||||||
val alias: String,
|
val alias: String,
|
||||||
val password: String,
|
val password: String,
|
||||||
val privateKeyCertificatePair: PrivateKeyCertificatePair = newPrivateKeyCertificatePair(),
|
val privateKeyCertificatePair: PrivateKeyCertificatePair,
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -316,6 +331,12 @@ object ApkSigner {
|
|||||||
signingExtension = null
|
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.")
|
@Deprecated("This constructor will be removed in the future.")
|
||||||
internal constructor(signingExtension: SigningExtension) {
|
internal constructor(signingExtension: SigningExtension) {
|
||||||
signerBuilder = null
|
signerBuilder = null
|
||||||
@@ -344,11 +365,5 @@ object ApkSigner {
|
|||||||
|
|
||||||
signingExtension?.register(apkZFile)
|
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
|
package app.revanced.library
|
||||||
|
|
||||||
|
import app.revanced.library.ApkSigner.newPrivateKeyCertificatePair
|
||||||
import app.revanced.patcher.PatcherResult
|
import app.revanced.patcher.PatcherResult
|
||||||
import com.android.tools.build.apkzlib.zip.AlignmentRules
|
import com.android.tools.build.apkzlib.zip.AlignmentRules
|
||||||
import com.android.tools.build.apkzlib.zip.StoredEntry
|
import com.android.tools.build.apkzlib.zip.StoredEntry
|
||||||
import com.android.tools.build.apkzlib.zip.ZFile
|
import com.android.tools.build.apkzlib.zip.ZFile
|
||||||
import com.android.tools.build.apkzlib.zip.ZFileOptions
|
import com.android.tools.build.apkzlib.zip.ZFileOptions
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
import java.util.logging.Logger
|
import java.util.logging.Logger
|
||||||
|
import kotlin.time.Duration.Companion.days
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility functions to work with APK files.
|
* 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()) {
|
@Deprecated("This method will be removed in the future.")
|
||||||
ApkSigner.readKeyStore(
|
fun newPrivateKeyCertificatePair(
|
||||||
signingOptions.keyStore.inputStream(),
|
privateKeyCertificatePairDetails: PrivateKeyCertificatePairDetails,
|
||||||
signingOptions.keyStorePassword ?: "",
|
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 {
|
* Reads the private key and certificate pair from an existing keystore.
|
||||||
store(
|
*
|
||||||
signingOptions.keyStore.outputStream(),
|
* @param keyStoreDetails The details for the keystore.
|
||||||
signingOptions.keyStorePassword?.toCharArray(),
|
*
|
||||||
)
|
* @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.
|
* Signs the apk file with the given options.
|
||||||
*
|
*
|
||||||
* @param signingOptions The options to use for signing.
|
* @param signingOptions The options to use for signing.
|
||||||
*/
|
*/
|
||||||
@Deprecated("Use sign(File, File, SigningOptions) instead.")
|
@Deprecated("This method will be removed in the future.")
|
||||||
fun File.sign(signingOptions: SigningOptions) {
|
fun File.sign(signingOptions: SigningOptions) = ApkSigner.newApkSigner(
|
||||||
val keyStore = readOrNewKeyStore(signingOptions)
|
signingOptions.signer,
|
||||||
|
readOrNewPrivateKeyCertificatePair(signingOptions),
|
||||||
@Suppress("DEPRECATION")
|
).signApk(this)
|
||||||
ApkSigner.newApkSigner(
|
|
||||||
keyStore,
|
|
||||||
signingOptions.alias,
|
|
||||||
signingOptions.password,
|
|
||||||
).signApk(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signs [inputApkFile] with the given options and saves the signed apk to [outputApkFile].
|
* 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 outputApkFile The file to save the signed apk to.
|
||||||
* @param signingOptions The options to use for signing.
|
* @param signingOptions The options to use for signing.
|
||||||
*/
|
*/
|
||||||
fun sign(inputApkFile: File, outputApkFile: File, signingOptions: SigningOptions) {
|
@Deprecated("This method will be removed in the future.")
|
||||||
val keyStore = readOrNewKeyStore(signingOptions)
|
fun sign(inputApkFile: File, outputApkFile: File, signingOptions: SigningOptions) = sign(
|
||||||
|
inputApkFile,
|
||||||
ApkSigner.newApkSigner(
|
outputApkFile,
|
||||||
signingOptions.signer,
|
signingOptions.signer,
|
||||||
keyStore,
|
readOrNewPrivateKeyCertificatePair(signingOptions),
|
||||||
signingOptions.alias,
|
)
|
||||||
signingOptions.password,
|
|
||||||
).signApk(inputApkFile, outputApkFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options for signing an apk.
|
* Options for signing an apk.
|
||||||
@@ -158,6 +244,7 @@ object ApkUtils {
|
|||||||
* @param password The password for recovering the signing key.
|
* @param password The password for recovering the signing key.
|
||||||
* @param signer The name of the signer.
|
* @param signer The name of the signer.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("This class will be removed in the future.")
|
||||||
class SigningOptions(
|
class SigningOptions(
|
||||||
val keyStore: File,
|
val keyStore: File,
|
||||||
val keyStorePassword: String?,
|
val keyStorePassword: String?,
|
||||||
@@ -165,4 +252,30 @@ object ApkUtils {
|
|||||||
val password: String = "",
|
val password: String = "",
|
||||||
val signer: String = "ReVanced",
|
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 =
|
internal val MOUNT_SCRIPT =
|
||||||
"""
|
"""
|
||||||
#!/system/bin/sh
|
#!/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 [ "$( getprop sys.boot_completed )" = 1 ]; do sleep 3; done
|
||||||
until [ -d "/sdcard/Android" ]; do sleep 1; 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
|
$UMOUNT
|
||||||
|
|
||||||
base_path="$PATCHED_APK_PATH"
|
base_path="$PATCHED_APK_PATH"
|
||||||
@@ -44,7 +48,7 @@ internal object Constants {
|
|||||||
chcon u:object_r:apk_data_file:s0 ${'$'}base_path
|
chcon u:object_r:apk_data_file:s0 ${'$'}base_path
|
||||||
mount -o bind ${'$'}MIRROR${'$'}base_path ${'$'}stock_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
|
$KILL
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user