chore: Merge branch dev to main (#35)

This commit is contained in:
oSumAtrIX
2024-03-09 04:34:48 +01:00
committed by GitHub
7 changed files with 178 additions and 46 deletions

View File

@@ -1,3 +1,16 @@
# [2.2.0-dev.1](https://github.com/ReVanced/revanced-library/compare/v2.1.0...v2.2.0-dev.1) (2024-03-09)
### Bug Fixes
* Make property private ([51109c4](https://github.com/ReVanced/revanced-library/commit/51109c476837828535dcd395a5222d2fcf7fc22c))
* Sign APKs using `apksig` ([f59ecbc](https://github.com/ReVanced/revanced-library/commit/f59ecbccd14a08d87d4f18c3c0cc47a884088b99))
### Features
* Increase default expiration date of certificate ([f2bd3f5](https://github.com/ReVanced/revanced-library/commit/f2bd3f5eeee14ca32094be0d41c32b231a16bcc3))
# [2.1.0](https://github.com/ReVanced/revanced-library/compare/v2.0.0...v2.1.0) (2024-03-04)

View File

@@ -1,6 +1,8 @@
public final class app/revanced/library/ApkSigner {
public static final field INSTANCE Lapp/revanced/library/ApkSigner;
public final fun newApkSigner (Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)Lapp/revanced/library/ApkSigner$Signer;
public final fun newApkSigner (Ljava/lang/String;Lapp/revanced/library/ApkSigner$PrivateKeyCertificatePair;)Lapp/revanced/library/ApkSigner$Signer;
public final fun newApkSigner (Ljava/lang/String;Ljava/security/KeyStore;Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/library/ApkSigner$Signer;
public final fun newApkSigner (Ljava/security/KeyStore;Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/library/ApkSigner$Signer;
public final fun newKeyStore (Ljava/io/OutputStream;Ljava/lang/String;Ljava/util/Set;)V
public final fun newKeyStore (Ljava/util/Set;)Ljava/security/KeyStore;
@@ -25,15 +27,16 @@ public final class app/revanced/library/ApkSigner$PrivateKeyCertificatePair {
}
public final class app/revanced/library/ApkSigner$Signer {
public final fun getSigningExtension ()Lcom/android/tools/build/apkzlib/sign/SigningExtension;
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 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 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 class app/revanced/library/ApkUtils$SigningOptions {

View File

@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.kotlin)
alias(libs.plugins.binary.compatibility.validator)
@@ -27,6 +29,7 @@ dependencies {
implementation(libs.jadb) // Fork with Shell v2 support.
implementation(libs.jackson.module.kotlin)
implementation(libs.apkzlib)
implementation(libs.apksig)
implementation(libs.bcpkix.jdk15on)
implementation(libs.guava)
@@ -43,10 +46,14 @@ tasks {
}
}
kotlin { jvmToolchain(11) }
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11)
}
}
java {
withSourcesJar()
targetCompatibility = JavaVersion.VERSION_11
}
publishing {

View File

@@ -1,4 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official
version = 2.1.0
version = 2.2.0-dev.1

View File

@@ -7,6 +7,7 @@ binary-compatibility-validator = "0.14.0"
apkzlib = "8.3.0"
bcpkix-jdk15on = "1.70"
guava = "33.0.0-jre"
apksig = "8.3.0"
[libraries]
jackson-module-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson-module-kotlin" }
@@ -17,6 +18,7 @@ revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "re
apkzlib = { module = "com.android.tools.build:apkzlib", version.ref = "apkzlib" }
bcpkix-jdk15on = { module = "org.bouncycastle:bcpkix-jdk15on", version.ref = "bcpkix-jdk15on" }
guava = { module = "com.google.guava:guava", version.ref = "guava" }
apksig = { module = "com.android.tools.build:apksig", version.ref = "apksig" }
[plugins]
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }

View File

@@ -1,5 +1,6 @@
package app.revanced.library
import com.android.apksig.ApkSigner.SignerConfig
import com.android.tools.build.apkzlib.sign.SigningExtension
import com.android.tools.build.apkzlib.sign.SigningOptions
import com.android.tools.build.apkzlib.zip.ZFile
@@ -43,35 +44,28 @@ object ApkSigner {
*/
fun newPrivateKeyCertificatePair(
commonName: String = "ReVanced",
validUntil: Date = Date(System.currentTimeMillis() + 356.days.inWholeMilliseconds * 24),
validUntil: Date = Date(System.currentTimeMillis() + (365.days * 8).inWholeMilliseconds * 24),
): PrivateKeyCertificatePair {
logger.fine("Creating certificate for $commonName")
// Generate a new key pair.
val keyPair =
KeyPairGenerator.getInstance("RSA").apply {
val keyPair = KeyPairGenerator.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME).apply {
initialize(4096)
}.generateKeyPair()
var serialNumber: BigInteger
do serialNumber = BigInteger.valueOf(SecureRandom().nextLong())
while (serialNumber < BigInteger.ZERO)
val contentSigner = JcaContentSignerBuilder("SHA256withRSA").build(keyPair.private)
val name = X500Name("CN=$commonName")
// Create a new certificate.
val certificate =
JcaX509CertificateConverter().getCertificate(
X509v3CertificateBuilder(
val certificateHolder = X509v3CertificateBuilder(
name,
serialNumber,
BigInteger.valueOf(SecureRandom().nextLong()),
Date(System.currentTimeMillis()),
validUntil,
Locale.ENGLISH,
name,
SubjectPublicKeyInfo.getInstance(keyPair.public.encoded),
).build(JcaContentSignerBuilder("SHA256withRSA").build(keyPair.private)),
)
).build(contentSigner)
val certificate = JcaX509CertificateConverter().getCertificate(certificateHolder)
return PrivateKeyCertificatePair(keyPair.private, certificate)
}
@@ -189,6 +183,7 @@ object ApkSigner {
/**
* Create a new [Signer].
*
* @param signer The name of the signer.
* @param privateKeyCertificatePair The private key and certificate pair to use for signing.
*
* @return The new [Signer].
@@ -196,6 +191,38 @@ object ApkSigner {
* @see PrivateKeyCertificatePair
* @see Signer
*/
fun newApkSigner(
signer: String,
privateKeyCertificatePair: PrivateKeyCertificatePair,
) = Signer(
com.android.apksig.ApkSigner.Builder(
listOf(
SignerConfig.Builder(
signer,
privateKeyCertificatePair.privateKey,
listOf(privateKeyCertificatePair.certificate),
).build(),
),
),
)
/**
* Create a new [Signer].
*
* @param privateKeyCertificatePair The private key and certificate pair to use for signing.
*
* @return The new [Signer].
*
* @see PrivateKeyCertificatePair
* @see Signer
*/
@Suppress("DEPRECATION")
@Deprecated(
"This method will be removed in the future.",
ReplaceWith(
"newApkSigner(\"ReVanced\", privateKeyCertificatePair)",
),
)
fun newApkSigner(privateKeyCertificatePair: PrivateKeyCertificatePair) =
Signer(
SigningExtension(
@@ -212,6 +239,7 @@ object ApkSigner {
/**
* Create a new [Signer].
*
* @param signer The name of the signer.
* @param keyStore The keystore to use for signing.
* @param keyStoreEntryAlias The alias of the key store entry to use for signing.
* @param keyStoreEntryPassword The password for recovering the signing key.
@@ -222,10 +250,36 @@ object ApkSigner {
* @see Signer
*/
fun newApkSigner(
signer: String,
keyStore: KeyStore,
keyStoreEntryAlias: String,
keyStoreEntryPassword: String,
) = newApkSigner(readKeyCertificatePair(keyStore, keyStoreEntryAlias, keyStoreEntryPassword))
) = newApkSigner(signer, readKeyCertificatePair(keyStore, keyStoreEntryAlias, keyStoreEntryPassword))
/**
* Create a new [Signer].
*
* @param keyStore The keystore to use for signing.
* @param keyStoreEntryAlias The alias of the key store entry to use for signing.
* @param keyStoreEntryPassword The password for recovering the signing key.
*
* @return The new [Signer].
*
* @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",
),
)
fun newApkSigner(
keyStore: KeyStore,
keyStoreEntryAlias: String,
keyStoreEntryPassword: String,
) = newApkSigner("ReVanced", readKeyCertificatePair(keyStore, keyStoreEntryAlias, keyStoreEntryPassword))
/**
* An entry in a keystore.
@@ -253,23 +307,48 @@ object ApkSigner {
val certificate: X509Certificate,
)
class Signer internal constructor(val signingExtension: SigningExtension) {
class Signer {
private val signerBuilder: com.android.apksig.ApkSigner.Builder?
private val signingExtension: SigningExtension?
internal constructor(signerBuilder: com.android.apksig.ApkSigner.Builder) {
this.signerBuilder = signerBuilder
signingExtension = null
}
@Deprecated("This constructor will be removed in the future.")
internal constructor(signingExtension: SigningExtension) {
signerBuilder = null
this.signingExtension = signingExtension
}
/**
* Sign an APK file.
*
* @param apkFile The APK file to sign.
*/
fun signApk(apkFile: File) = ZFile.openReadWrite(apkFile).use { signApk(it) }
@Deprecated("This method will be removed in the future.")
fun signApk(apkFile: File) = ZFile.openReadWrite(apkFile).use {
@Suppress("DEPRECATION")
signApk(it)
}
/**
* Sign an APK file.
*
* @param apkZFile The APK [ZFile] to sign.
*/
@Deprecated("This method will be removed in the future.")
fun signApk(apkZFile: ZFile) {
logger.info("Signing ${apkZFile.file.name}")
signingExtension.register(apkZFile)
signingExtension?.register(apkZFile)
}
fun signApk(inputApkFile: File, outputApkFile: File) {
logger.info("Signing APK")
signerBuilder?.setInputApk(inputApkFile)?.setOutputApk(outputApkFile)?.build()?.sign()
}
}
}

View File

@@ -84,7 +84,7 @@ object ApkUtils {
}
}
logger.info("Aligning ${apkFile.name}")
logger.info("Aligning APK")
targetApkZFile.realign()
@@ -93,20 +93,20 @@ object ApkUtils {
}
/**
* Signs the apk file with the given options.
* Reads an existing or creates a new keystore.
*
* @param signingOptions The options to use for signing.
*/
fun File.sign(signingOptions: SigningOptions) {
// Get the keystore from the file or create a new one.
val keyStore =
if (signingOptions.keyStore.exists()) {
ApkSigner.readKeyStore(signingOptions.keyStore.inputStream(), signingOptions.keyStorePassword ?: "")
private fun readOrNewKeyStore(signingOptions: SigningOptions) = if (signingOptions.keyStore.exists()) {
ApkSigner.readKeyStore(
signingOptions.keyStore.inputStream(),
signingOptions.keyStorePassword ?: "",
)
} else {
val entries = setOf(ApkSigner.KeyStoreEntry(signingOptions.alias, signingOptions.password))
val entry = ApkSigner.KeyStoreEntry(signingOptions.alias, signingOptions.password)
// Create a new keystore with a new keypair and saves it.
ApkSigner.newKeyStore(entries).apply {
ApkSigner.newKeyStore(setOf(entry)).apply {
store(
signingOptions.keyStore.outputStream(),
signingOptions.keyStorePassword?.toCharArray(),
@@ -114,6 +114,16 @@ object ApkUtils {
}
}
/**
* 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,
@@ -121,6 +131,24 @@ object ApkUtils {
).signApk(this)
}
/**
* 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 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)
}
/**
* Options for signing an apk.
*