Compare commits

..

1 Commits

Author SHA1 Message Date
Pun Butrach
0673307204 docs: Use American spelling (#96) 2025-12-14 16:40:34 +01:00
13 changed files with 37 additions and 223 deletions

View File

@@ -109,9 +109,9 @@ You can find the contribution guidelines [here](CONTRIBUTING.md).
To build ReVanced Library, To build ReVanced Library,
you can follow the [ReVanced documentation](https://github.com/ReVanced/revanced-documentation). you can follow the [ReVanced documentation](https://github.com/ReVanced/revanced-documentation).
## 📜 Licence ## 📜 License
ReVanced Library is licensed under the GPLv3 license. Please see the [licence file](LICENSE) for more information. ReVanced Library is licensed under the GPLv3 license. Please see the [license file](LICENSE) for more information.
[tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and modify ReVanced Library as long as you track changes/dates in source files. [tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and modify ReVanced Library as long as you track changes/dates in source files.
Any modifications to ReVanced Library must also be made available under the GPL, Any modifications to ReVanced Library must also be made available under the GPL,
along with build & install instructions. along with build & install instructions.

View File

@@ -47,18 +47,6 @@ public final class app/revanced/library/ApkUtils$PrivateKeyCertificatePairDetail
public final fun getValidUntil ()Ljava/util/Date; public final fun getValidUntil ()Ljava/util/Date;
} }
public final class app/revanced/library/CryptographyKt {
public static final fun getPublicKey (Lorg/bouncycastle/openpgp/PGPPublicKeyRing;)Lorg/bouncycastle/openpgp/PGPPublicKey;
public static final fun getPublicKeyRing (Lorg/bouncycastle/openpgp/PGPPublicKeyRingCollection;J)Lorg/bouncycastle/openpgp/PGPPublicKeyRing;
public static final fun getPublicKeyRingCollection (Ljava/io/InputStream;)Lorg/bouncycastle/openpgp/PGPPublicKeyRingCollection;
public static final fun getSignature (Ljava/io/InputStream;)Lorg/bouncycastle/openpgp/PGPSignature;
public static final fun matchGitHub (Ldev/sigstore/fulcio/client/ImmutableFulcioCertificateMatcher$Builder;Ljava/lang/String;)Ldev/sigstore/fulcio/client/ImmutableFulcioCertificateMatcher$Builder;
public static final fun verificationOptions (Lkotlin/jvm/functions/Function1;)Ldev/sigstore/VerificationOptions;
public static final fun verifySLSA ([BLjava/io/InputStream;Ldev/sigstore/VerificationOptions;)Z
public static final fun verifySLSA ([BLjava/io/InputStream;Lkotlin/jvm/functions/Function1;)Z
public static final fun verifySignature ([BLorg/bouncycastle/openpgp/PGPSignature;Lorg/bouncycastle/openpgp/PGPPublicKey;)Z
}
public final class app/revanced/library/OptionsKt { public final class app/revanced/library/OptionsKt {
public static final fun setOptions (Ljava/util/Set;Ljava/util/Map;)V public static final fun setOptions (Ljava/util/Set;Ljava/util/Map;)V
} }
@@ -109,7 +97,7 @@ public abstract interface class app/revanced/library/installation/command/RunRes
public abstract fun getError ()Ljava/lang/String; public abstract fun getError ()Ljava/lang/String;
public abstract fun getExitCode ()I public abstract fun getExitCode ()I
public abstract fun getOutput ()Ljava/lang/String; public abstract fun getOutput ()Ljava/lang/String;
public fun waitFor ()V public abstract fun waitFor ()V
} }
public final class app/revanced/library/installation/command/RunResult$DefaultImpls { public final class app/revanced/library/installation/command/RunResult$DefaultImpls {

View File

@@ -47,18 +47,6 @@ public final class app/revanced/library/ApkUtils$PrivateKeyCertificatePairDetail
public final fun getValidUntil ()Ljava/util/Date; public final fun getValidUntil ()Ljava/util/Date;
} }
public final class app/revanced/library/CryptographyKt {
public static final fun getPublicKey (Lorg/bouncycastle/openpgp/PGPPublicKeyRing;)Lorg/bouncycastle/openpgp/PGPPublicKey;
public static final fun getPublicKeyRing (Lorg/bouncycastle/openpgp/PGPPublicKeyRingCollection;J)Lorg/bouncycastle/openpgp/PGPPublicKeyRing;
public static final fun getPublicKeyRingCollection (Ljava/io/InputStream;)Lorg/bouncycastle/openpgp/PGPPublicKeyRingCollection;
public static final fun getSignature (Ljava/io/InputStream;)Lorg/bouncycastle/openpgp/PGPSignature;
public static final fun matchGitHub (Ldev/sigstore/fulcio/client/ImmutableFulcioCertificateMatcher$Builder;Ljava/lang/String;)Ldev/sigstore/fulcio/client/ImmutableFulcioCertificateMatcher$Builder;
public static final fun verificationOptions (Lkotlin/jvm/functions/Function1;)Ldev/sigstore/VerificationOptions;
public static final fun verifySLSA ([BLjava/io/InputStream;Ldev/sigstore/VerificationOptions;)Z
public static final fun verifySLSA ([BLjava/io/InputStream;Lkotlin/jvm/functions/Function1;)Z
public static final fun verifySignature ([BLorg/bouncycastle/openpgp/PGPSignature;Lorg/bouncycastle/openpgp/PGPPublicKey;)Z
}
public final class app/revanced/library/OptionsKt { public final class app/revanced/library/OptionsKt {
public static final fun setOptions (Ljava/util/Set;Ljava/util/Map;)V public static final fun setOptions (Ljava/util/Set;Ljava/util/Map;)V
} }
@@ -85,7 +73,7 @@ public abstract interface class app/revanced/library/installation/command/RunRes
public abstract fun getError ()Ljava/lang/String; public abstract fun getError ()Ljava/lang/String;
public abstract fun getExitCode ()I public abstract fun getExitCode ()I
public abstract fun getOutput ()Ljava/lang/String; public abstract fun getOutput ()Ljava/lang/String;
public fun waitFor ()V public abstract fun waitFor ()V
} }
public final class app/revanced/library/installation/command/RunResult$DefaultImpls { public final class app/revanced/library/installation/command/RunResult$DefaultImpls {

View File

@@ -54,9 +54,7 @@ kotlin {
commonMain.dependencies { commonMain.dependencies {
implementation(libs.apksig) implementation(libs.apksig)
implementation(libs.apkzlib) implementation(libs.apkzlib)
implementation(libs.bouncycastle.bcpkix) implementation(libs.bcpkix.jdk18on)
implementation(libs.bouncycastle.pgp)
implementation(libs.sigstore.java)
implementation(libs.guava) implementation(libs.guava)
implementation(libs.jadb) implementation(libs.jadb)
implementation(libs.kotlin.reflect) implementation(libs.kotlin.reflect)
@@ -73,7 +71,7 @@ kotlin {
android { android {
namespace = "app.revanced.library" namespace = "app.revanced.library"
compileSdk = 36 compileSdk = 34
defaultConfig { defaultConfig {
minSdk = 26 minSdk = 26
} }

View File

@@ -1,4 +1,4 @@
version = 3.2.0-dev.2-local version = 3.2.0-dev.1
#Gradle #Gradle
org.gradle.jvmargs = -Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options="-Xmx2048M" org.gradle.jvmargs = -Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options="-Xmx2048M"
org.gradle.caching = true org.gradle.caching = true

View File

@@ -1,20 +1,20 @@
[versions] [versions]
android = "8.12.3" android = "8.5.2"
binary-compatibility-validator = "0.18.1" bcpkix-jdk18on = "1.77"
core-ktx = "1.17.0" binary-compatibility-validator = "0.15.1"
guava = "33.5.0-jre" core-ktx = "1.15.0"
guava = "33.2.1-jre"
jadb = "1.2.1.1" jadb = "1.2.1.1"
kotlin = "2.2.21" kotlin = "2.0.20"
kotlinx-coroutines = "1.10.2" kotlinx-coroutines = "1.8.1"
kotlinx-serialization = "1.9.0" kotlinx-serialization = "1.7.1"
libsu = "5.2.2" libsu = "5.2.2"
revanced-patcher = "22.0.0-local" revanced-patcher = "21.0.0"
bouncy-castle = "1.82"
sigstore = "2.0.0"
[libraries] [libraries]
apkzlib = { module = "com.android.tools.build:apkzlib", version.ref = "android" } apkzlib = { module = "com.android.tools.build:apkzlib", version.ref = "android" }
apksig = { module = "com.android.tools.build:apksig", version.ref = "android" } apksig = { module = "com.android.tools.build:apksig", version.ref = "android" }
bcpkix-jdk18on = { module = "org.bouncycastle:bcpkix-jdk18on", version.ref = "bcpkix-jdk18on" }
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" } core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
guava = { module = "com.google.guava:guava", version.ref = "guava" } guava = { module = "com.google.guava:guava", version.ref = "guava" }
jadb = { module = "app.revanced:jadb", version.ref = "jadb" } # Fork with Shell v2 support. jadb = { module = "app.revanced:jadb", version.ref = "jadb" } # Fork with Shell v2 support.
@@ -26,9 +26,6 @@ libsu-core = { module = "com.github.topjohnwu.libsu:core", version.ref = "libsu"
libsu-nio = { module = "com.github.topjohnwu.libsu:nio", version.ref = "libsu" } libsu-nio = { module = "com.github.topjohnwu.libsu:nio", version.ref = "libsu" }
libsu-service = { module = "com.github.topjohnwu.libsu:service", version.ref = "libsu" } libsu-service = { module = "com.github.topjohnwu.libsu:service", version.ref = "libsu" }
revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" } revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" }
bouncycastle-bcpkix = { module = "org.bouncycastle:bcpkix-jdk18on", version.ref = "bouncy-castle" }
bouncycastle-pgp = { module = "org.bouncycastle:bcpg-jdk18on", version.ref = "bouncy-castle" }
sigstore-java = { module = "dev.sigstore:sigstore-java", version.ref = "sigstore" }
[plugins] [plugins]
android-library = { id = "com.android.library", version.ref = "android" } android-library = { id = "com.android.library", version.ref = "android" }

Binary file not shown.

View File

@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

12
gradlew vendored
View File

@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# Copyright © 2015 the original authors. # Copyright © 2015-2021 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@@ -86,7 +86,8 @@ done
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum
@@ -114,6 +115,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;; NONSTOP* ) nonstop=true ;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@@ -171,6 +173,7 @@ fi
# For Cygwin or MSYS, switch paths to Windows format before running java # For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" ) JAVACMD=$( cygpath --unix "$JAVACMD" )
@@ -203,14 +206,15 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command: # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped. # and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line. # treated as '${Hostname}' itself on the command line.
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ -classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@" "$@"
# Stop when "xargs" is not available. # Stop when "xargs" is not available.

3
gradlew.bat vendored
View File

@@ -70,10 +70,11 @@ goto fail
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

View File

@@ -79,7 +79,7 @@ class LocalInstaller(
override suspend fun getInstallation(packageName: String) = try { override suspend fun getInstallation(packageName: String) = try {
val packageInfo = context.packageManager.getPackageInfo(packageName, 0) val packageInfo = context.packageManager.getPackageInfo(packageName, 0)
Installation(packageInfo.applicationInfo!!.sourceDir) Installation(packageInfo.applicationInfo.sourceDir)
} catch (e: PackageManager.NameNotFoundException) { } catch (e: PackageManager.NameNotFoundException) {
null null
} }

View File

@@ -1,7 +1,6 @@
package app.revanced.library package app.revanced.library
import com.android.apksig.ApkSigner.SignerConfig import com.android.apksig.ApkSigner.SignerConfig
import com.android.apksig.KeyConfig
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
import org.bouncycastle.cert.X509v3CertificateBuilder import org.bouncycastle.cert.X509v3CertificateBuilder
@@ -156,11 +155,12 @@ object ApkSigner {
// Read the private key and certificate from the keystore. // Read the private key and certificate from the keystore.
val privateKey = try { val privateKey =
keyStore.getKey(keyStoreEntryAlias, keyStoreEntryPassword.toCharArray()) as PrivateKey try {
} catch (exception: UnrecoverableKeyException) { keyStore.getKey(keyStoreEntryAlias, keyStoreEntryPassword.toCharArray()) as PrivateKey
throw IllegalArgumentException("Invalid password for keystore entry $keyStoreEntryAlias") } catch (exception: UnrecoverableKeyException) {
} throw IllegalArgumentException("Invalid password for keystore entry $keyStoreEntryAlias")
}
val certificate = keyStore.getCertificate(keyStoreEntryAlias) as X509Certificate val certificate = keyStore.getCertificate(keyStoreEntryAlias) as X509Certificate
@@ -186,7 +186,7 @@ object ApkSigner {
listOf( listOf(
SignerConfig.Builder( SignerConfig.Builder(
signer, signer,
KeyConfig.Jca(privateKeyCertificatePair.privateKey), privateKeyCertificatePair.privateKey,
listOf(privateKeyCertificatePair.certificate), listOf(privateKeyCertificatePair.certificate),
).build(), ).build(),
), ),

View File

@@ -1,163 +0,0 @@
@file:Suppress("unused")
package app.revanced.library
import dev.sigstore.KeylessVerifier
import dev.sigstore.VerificationOptions
import dev.sigstore.VerificationOptions.CertificateMatcher
import dev.sigstore.bundle.Bundle
import dev.sigstore.dsse.InTotoPayload
import dev.sigstore.fulcio.client.ImmutableFulcioCertificateMatcher.Builder
import dev.sigstore.strings.StringMatcher
import org.bouncycastle.openpgp.*
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator
import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider
import java.io.InputStream
// region PGP signature verification.
private val verifierBuilderProvider = BcPGPContentVerifierBuilderProvider()
private val fingerprintCalculator = BcKeyFingerprintCalculator()
/**
* Verifies the PGP signature of the provided bytes using the provided signature and public key.
*
* @param bytes The bytes to verify.
* @param signature The PGP signature.
* @param publicKey The PGP public key.
* @return True if the signature is valid, false otherwise.
*/
fun verifySignature(
bytes: ByteArray, signature: PGPSignature, publicKey: PGPPublicKey
) = signature.apply {
init(verifierBuilderProvider, publicKey)
update(bytes)
}.verify()
/**
* Gets the PGP signature from the provided signature input stream.
*
* @param signatureInputStream The input stream of the PGP signature.
* @return The PGP signature.
* @throws IllegalArgumentException if the signature format is invalid.
*/
fun getSignature(
signatureInputStream: InputStream
) = when (val pgpObject = PGPObjectFactory(
PGPUtil.getDecoderStream(signatureInputStream), fingerprintCalculator
).nextObject()) {
is PGPSignatureList -> pgpObject
is PGPCompressedData -> {
val compressedDataFactory = PGPObjectFactory(
pgpObject.dataStream, fingerprintCalculator
)
compressedDataFactory.nextObject() as PGPSignatureList
}
else -> throw IllegalArgumentException("Invalid PGP signature format.")
}.first()
/**
* Gets the PGP public key ring collection from the provided public key ring input stream.
*
* @param publicKeyRingInputStream The input stream of the public key ring.
* @return The PGP public key ring collection.
*/
fun getPublicKeyRingCollection(
publicKeyRingInputStream: InputStream
) = PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(publicKeyRingInputStream), fingerprintCalculator)
/**
* Gets the PGP public key ring with the specified key ID from the provided public key ring collection.
*
* @param publicKeyRingCollection The PGP public key ring collection.
* @param keyId The key ID of the public key ring to retrieve.
* @return The PGP public key ring with the specified key ID.
* @throws IllegalArgumentException if the public key ring with the specified key ID is not found.
*/
fun getPublicKeyRing(
publicKeyRingCollection: PGPPublicKeyRingCollection, keyId: Long
) = publicKeyRingCollection.getPublicKeyRing(keyId)
?: throw IllegalArgumentException("Can't find public key ring with ID $keyId.")
/**
* Gets the PGP public key from the provided public key ring.
*/
fun getPublicKey(publicKeyRing: PGPPublicKeyRing): PGPPublicKey = publicKeyRing.publicKey
// endregion
// region SLSA attestation verification.
private val keylessVerifier: KeylessVerifier = KeylessVerifier.builder().sigstorePublicDefaults().build()
private const val RUNNER_ENVIRONMENT_OID = "1.3.6.1.4.1.57264.1.11"
private const val PROVENANCE_PREDICATE_TYPE = "https://slsa.dev/provenance/v1"
/**
* Verifies the SLSA attestation of the provided digest using the provided attestation input stream and matcher.
*
* @param digest The digest to verify.
* @param attestationInputStream The input stream of the attestation.
* @param matcher The matcher to add to the verification options.
* @return True if the verification is successful, false otherwise.
*/
fun verifySLSA(
digest: ByteArray,
attestationInputStream: InputStream,
matcher: Builder.() -> Builder,
) = verifySLSA(digest, attestationInputStream, verificationOptions(matcher))
/**
* Verifies the SLSA attestation of the provided digest using the provided attestation input stream
* and verification options.
*
* @param digest The digest to verify.
* @param attestationInputStream The input stream of the attestation.
* @param verificationOptions The verification options to use.
* @return True if the verification is successful, false otherwise.
*/
fun verifySLSA(
digest: ByteArray,
attestationInputStream: InputStream,
verificationOptions: VerificationOptions,
) = runCatching {
val bundle = Bundle.from(attestationInputStream.reader())
val predicateType = InTotoPayload.from(bundle.dsseEnvelope.get()).predicateType
require(predicateType == PROVENANCE_PREDICATE_TYPE)
keylessVerifier.verify(digest, bundle, verificationOptions)
}.isSuccess
/**
* Creates verification options with the provided matcher.
*
* @param matcher The matcher to add to the verification options.
* @return The created verification options.
*/
fun verificationOptions(
matcher: Builder.() -> Builder
): VerificationOptions = VerificationOptions.builder().addCertificateMatchers(
CertificateMatcher.fulcio().matcher().build()
).build()
/**
* Adds GitHub-specific matching to the builder for the specified repository.
*
* @param repository The GitHub repository in the format "owner/repo".
* @return The updated builder with GitHub-specific matching.
*/
fun Builder.matchGitHub(
repository: String
): Builder = issuer(
StringMatcher.string("https://token.actions.githubusercontent.com")
).subjectAlternativeName(
StringMatcher.regex("(?i)^https://github.com/$repository")
).putOidDerAsn1Strings(RUNNER_ENVIRONMENT_OID, StringMatcher.string("github-hosted"))
// endregion