diff --git a/app/build.gradle b/app/build.gradle index f77b16b51..1c31f4126 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -65,7 +65,7 @@ dependencies { def vRoom = "2.1.0-alpha05" implementation "androidx.room:room-rxjava2:${vRoom}" - def markwonVersion = '3.0.0' + def markwonVersion = '3.0.1' implementation "ru.noties.markwon:core:${markwonVersion}" implementation "ru.noties.markwon:html:${markwonVersion}" implementation "ru.noties.markwon:image-svg:${markwonVersion}" @@ -97,13 +97,12 @@ dependencies { implementation "com.chibatching.kotpref:kotpref:${vKotpref}" implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'androidx.browser:browser:1.0.0' implementation 'androidx.preference:preference:1.0.0' - implementation 'androidx.recyclerview:recyclerview:1.1.0-alpha04' + implementation 'androidx.recyclerview:recyclerview:1.1.0-alpha05' implementation 'androidx.cardview:cardview:1.0.0' - implementation 'com.google.android.material:material:1.1.0-alpha05' + implementation 'com.google.android.material:material:1.1.0-alpha06' implementation 'androidx.work:work-runtime:2.0.1' - implementation 'androidx.transition:transition:1.1.0-beta01' + implementation 'androidx.transition:transition:1.2.0-alpha01' implementation 'androidx.multidex:multidex:2.0.1' } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 33f347808..86a43f8dd 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -16,12 +16,6 @@ # public *; #} -# BouncyCastle --keep,allowoptimization class org.bouncycastle.jcajce.provider.asymmetric.rsa.**SHA1** { *; } --keep,allowoptimization class org.bouncycastle.jcajce.provider.asymmetric.RSA** { *; } --keep,allowoptimization class org.bouncycastle.jcajce.provider.digest.SHA1** { *; } --dontwarn javax.naming.** - # Snet -keepclassmembers class com.topjohnwu.magisk.utils.ISafetyNetHelper { *; } -keep,allowobfuscation interface com.topjohnwu.magisk.utils.ISafetyNetHelper$Callback @@ -40,12 +34,6 @@ # BootSigner -keepclassmembers class com.topjohnwu.signing.BootSigner { *; } -# SVG --dontwarn com.caverock.androidsvg.SVGAndroidRenderer - -# RetroStreams --dontwarn java9.** - # Strip logging -assumenosideeffects class com.topjohnwu.magisk.utils.Logger { public *** debug(...); diff --git a/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.kt b/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.kt index e5b030905..43eae3da1 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/receiver/GeneralReceiver.kt @@ -10,8 +10,10 @@ import com.topjohnwu.magisk.data.database.base.su import com.topjohnwu.magisk.data.repository.AppRepository import com.topjohnwu.magisk.ui.surequest.SuRequestActivity import com.topjohnwu.magisk.utils.DownloadApp +import com.topjohnwu.magisk.utils.RootUtils import com.topjohnwu.magisk.utils.SuLogger import com.topjohnwu.magisk.utils.inject +import com.topjohnwu.magisk.utils.get import com.topjohnwu.magisk.view.Notifications import com.topjohnwu.magisk.view.Shortcuts import com.topjohnwu.superuser.Shell @@ -20,8 +22,15 @@ open class GeneralReceiver : BroadcastReceiver() { private val appRepo: AppRepository by inject() - private fun getPkg(i: Intent): String { - return if (i.data == null) "" else i.data!!.encodedSchemeSpecificPart + companion object { + const val REQUEST = "request" + const val LOG = "log" + const val NOTIFY = "notify" + const val TEST = "test" + } + + private fun getPkg(intent: Intent): String { + return intent.data?.encodedSchemeSpecificPart ?: "" } override fun onReceive(context: Context, intent: Intent?) { @@ -40,16 +49,17 @@ open class GeneralReceiver : BroadcastReceiver() { return } when (action) { - SuRequestActivity.REQUEST -> { + REQUEST -> { val i = Intent(context, ClassMap[SuRequestActivity::class.java]) - .setAction(action) - .putExtra("socket", intent.getStringExtra("socket")) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - .addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) + .setAction(action) + .putExtra("socket", intent.getStringExtra("socket")) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) context.startActivity(i) } - SuRequestActivity.LOG -> SuLogger.handleLogs(intent) - SuRequestActivity.NOTIFY -> SuLogger.handleNotify(intent) + LOG -> SuLogger.handleLogs(intent) + NOTIFY -> SuLogger.handleNotify(intent) + TEST -> Shell.su("magisk --use-broadcast").submit() } } Intent.ACTION_PACKAGE_REPLACED -> @@ -67,7 +77,7 @@ open class GeneralReceiver : BroadcastReceiver() { Config.managerLink = intent.getStringExtra(Const.Key.INTENT_SET_LINK) DownloadApp.upgrade(intent.getStringExtra(Const.Key.INTENT_SET_NAME)) } - Const.Key.BROADCAST_REBOOT -> Shell.su("/system/bin/reboot").submit() + Const.Key.BROADCAST_REBOOT -> RootUtils.reboot() } } } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt index 37750feef..aa8feafb1 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt @@ -69,7 +69,7 @@ class HomeViewModel( "" } - val safetyNetTitle = KObservableField(R.string.safetyNet_check_text.res()) + val safetyNetTitle = KObservableField(R.string.safetyNet_check_text) val ctsState = KObservableField(SafetyNetState.IDLE) val basicIntegrityState = KObservableField(SafetyNetState.IDLE) val safetyNetState = Observer(ctsState, basicIntegrityState) { @@ -121,7 +121,7 @@ class HomeViewModel( fun safetyNetPressed() { ctsState.value = SafetyNetState.LOADING basicIntegrityState.value = SafetyNetState.LOADING - safetyNetTitle.value = R.string.checking_safetyNet_status.res() + safetyNetTitle.value = R.string.checking_safetyNet_status UpdateSafetyNetEvent().publish() } @@ -130,7 +130,7 @@ class HomeViewModel( response and 0x0F == 0 -> { val hasCtsPassed = response and ISafetyNetHelper.CTS_PASS != 0 val hasBasicIntegrityPassed = response and ISafetyNetHelper.BASIC_PASS != 0 - safetyNetTitle.value = R.string.safetyNet_check_success.res() + safetyNetTitle.value = R.string.safetyNet_check_success ctsState.value = if (hasCtsPassed) { SafetyNetState.PASS } else { @@ -152,7 +152,7 @@ class HomeViewModel( safetyNetTitle.value = when (response) { ISafetyNetHelper.RESPONSE_ERR -> R.string.safetyNet_res_invalid else -> R.string.safetyNet_api_error - }.res() + } } } @@ -162,6 +162,9 @@ class HomeViewModel( .doOnSubscribeUi { magiskState.value = MagiskState.LOADING managerState.value = MagiskState.LOADING + ctsState.value = SafetyNetState.IDLE + basicIntegrityState.value = SafetyNetState.IDLE + safetyNetTitle.value = R.string.safetyNet_check_text } .subscribeK { it.app.let { diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt b/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt index 9ad1b2f62..dddf4d75a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/surequest/SuRequestActivity.kt @@ -10,6 +10,7 @@ import com.topjohnwu.magisk.R import com.topjohnwu.magisk.databinding.ActivityRequestBinding import com.topjohnwu.magisk.model.entity.Policy import com.topjohnwu.magisk.model.events.DieEvent +import com.topjohnwu.magisk.model.receiver.GeneralReceiver import com.topjohnwu.magisk.ui.base.MagiskActivity import com.topjohnwu.magisk.utils.SuLogger import org.koin.androidx.viewmodel.ext.android.viewModel @@ -31,15 +32,15 @@ open class SuRequestActivity : MagiskActivity + + @@ -225,7 +227,7 @@ android:layout_marginRight="@dimen/margin_generic" android:gravity="center" android:maxLines="1" - android:text="@{viewModel.safetyNetTitle}" + android:text="@{XStringKt.res(viewModel.safetyNetTitle)}" android:textStyle="bold" app:autoSizeMaxTextSize="14sp" app:autoSizeTextType="uniform" diff --git a/app/src/main/res/raw/nonroot_utils.sh b/app/src/main/res/raw/nonroot_utils.sh index a62f89039..7c8ae1812 100644 --- a/app/src/main/res/raw/nonroot_utils.sh +++ b/app/src/main/res/raw/nonroot_utils.sh @@ -1,9 +1,12 @@ mount_partitions() { - [ "`getprop ro.build.ab_update`" = "true" ] && SLOT=`getprop ro.boot.slot_suffix` || SLOT= + [ "`getprop ro.build.ab_update`" = "true" ] && SLOT=`getprop ro.boot.slot_suffix` [ "`getprop ro.build.system_root_image`" = "true" ] && SYSTEM_ROOT=true || SYSTEM_ROOT=false } get_flags() { $SYSTEM_ROOT && KEEPVERITY=true || KEEPVERITY=false [ "`getprop ro.crypto.state`" = "encrypted" ] && KEEPFORCEENCRYPT=true || KEEPFORCEENCRYPT=false + RECOVERYMODE=false } + +run_migrations() { return; } diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index 36181811e..e592c0feb 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -732,4 +732,7 @@ void boot_complete(int client) { install_apk("/data/magisk.apk"); } } + + // Test whether broadcast can be used or not + broadcast_test(); } diff --git a/native/jni/core/daemon.cpp b/native/jni/core/daemon.cpp index 719bec4a9..3e1f34b07 100644 --- a/native/jni/core/daemon.cpp +++ b/native/jni/core/daemon.cpp @@ -54,6 +54,7 @@ static void *request_handler(void *args) { case LATE_START: case BOOT_COMPLETE: case SQLITE_CMD: + case BROADCAST_ACK: if (credential.uid != 0) { write_int(client, ROOT_REQUIRED); close(client); @@ -90,6 +91,10 @@ static void *request_handler(void *args) { case SQLITE_CMD: exec_sql(client); break; + case BROADCAST_ACK: + LOGD("* Use broadcasts for su logging and notify\n"); + CONNECT_BROADCAST = true; + close(client); default: close(client); break; diff --git a/native/jni/core/db.cpp b/native/jni/core/db.cpp index 5ffb38eed..976e870b3 100644 --- a/native/jni/core/db.cpp +++ b/native/jni/core/db.cpp @@ -233,7 +233,7 @@ int get_db_strings(db_strings &str, int key) { return 0; } -int get_uid_policy(int uid, su_access &su) { +int get_uid_policy(su_access &su, int uid) { char query[256], *err; sprintf(query, "SELECT policy, logging, notification FROM policies " "WHERE uid=%d AND (until=0 OR until>%li)", uid, time(nullptr)); diff --git a/native/jni/core/magisk.cpp b/native/jni/core/magisk.cpp index 3468728cd..b14300f9f 100644 --- a/native/jni/core/magisk.cpp +++ b/native/jni/core/magisk.cpp @@ -12,6 +12,8 @@ #include #include +using namespace std::literals; + [[noreturn]] static void usage() { fprintf(stderr, FULL_VER(Magisk) " multi-call binary\n" @@ -33,6 +35,7 @@ " --clone-attr SRC DEST clone permission, owner, and selinux context\n" " --clone SRC DEST clone SRC to DEST\n" " --sqlite SQL exec SQL to Magisk database\n" + " --use-broadcast use broadcast for su logging and notify\n" "\n" "Supported init triggers:\n" " post-fs-data, service, boot-complete\n" @@ -48,66 +51,70 @@ int magisk_main(int argc, char *argv[]) { if (argc < 2) usage(); - if (strcmp(argv[1], "-c") == 0) { + if (argv[1] == "-c"sv) { printf(MAGISK_VERSION ":MAGISK (" str(MAGISK_VER_CODE) ")\n"); return 0; - } else if (strcmp(argv[1], "-v") == 0) { + } else if (argv[1] == "-v"sv) { int fd = connect_daemon(); write_int(fd, CHECK_VERSION); char *v = read_string(fd); printf("%s\n", v); free(v); return 0; - } else if (strcmp(argv[1], "-V") == 0) { + } else if (argv[1] == "-V"sv) { int fd = connect_daemon(); write_int(fd, CHECK_VERSION_CODE); printf("%d\n", read_int(fd)); return 0; - } else if (strcmp(argv[1], "--list") == 0) { + } else if (argv[1] == "--list"sv) { for (int i = 0; applet_names[i]; ++i) printf("%s\n", applet_names[i]); return 0; - } else if (strcmp(argv[1], "--unlock-blocks") == 0) { + } else if (argv[1] == "--unlock-blocks"sv) { unlock_blocks(); return 0; - } else if (strcmp(argv[1], "--restorecon") == 0) { + } else if (argv[1] == "--restorecon"sv) { restore_rootcon(); restorecon(); return 0; - } else if (strcmp(argv[1], "--clone-attr") == 0) { + } else if (argv[1] == "--clone-attr"sv) { if (argc < 4) usage(); clone_attr(argv[2], argv[3]); return 0; - } else if (strcmp(argv[1], "--clone") == 0) { + } else if (argv[1] == "--clone"sv) { if (argc < 4) usage(); cp_afc(argv[2], argv[3]); return 0; - } else if (strcmp(argv[1], "--daemon") == 0) { + } else if (argv[1] == "--daemon"sv) { int fd = connect_daemon(true); write_int(fd, DO_NOTHING); return 0; - } else if (strcmp(argv[1], "--post-fs-data") == 0) { + } else if (argv[1] == "--post-fs-data"sv) { int fd = connect_daemon(true); write_int(fd, POST_FS_DATA); return read_int(fd); - } else if (strcmp(argv[1], "--service") == 0) { + } else if (argv[1] == "--service"sv) { int fd = connect_daemon(true); write_int(fd, LATE_START); return read_int(fd); - } else if (strcmp(argv[1], "--boot-complete") == 0) { + } else if (argv[1] == "--boot-complete"sv) { int fd = connect_daemon(true); write_int(fd, BOOT_COMPLETE); return read_int(fd); - } else if (strcmp(argv[1], "--sqlite") == 0) { + } else if (argv[1] == "--sqlite"sv) { int fd = connect_daemon(); write_int(fd, SQLITE_CMD); write_string(fd, argv[2]); send_fd(fd, STDOUT_FILENO); return read_int(fd); + } else if (argv[1] == "--use-broadcast"sv) { + int fd = connect_daemon(); + write_int(fd, BROADCAST_ACK); + return 0; } #if 0 /* Entry point for testing stuffs */ - else if (strcmp(argv[1], "--test") == 0) { + else if (argv[1] == "--test"sv) { return 0; } #endif diff --git a/native/jni/include/daemon.h b/native/jni/include/daemon.h index 41baeb9c8..bfc45041c 100644 --- a/native/jni/include/daemon.h +++ b/native/jni/include/daemon.h @@ -17,7 +17,7 @@ enum { BOOT_COMPLETE, MAGISKHIDE, SQLITE_CMD, - ZYGOTE_NOTIFY, + BROADCAST_ACK, }; // Return codes for daemon @@ -82,6 +82,8 @@ void magiskhide_handler(int client); *************/ void su_daemon_handler(int client, struct ucred *credential); +void broadcast_test(); extern int SDK_INT; extern bool RECOVERY_MODE; +extern bool CONNECT_BROADCAST; diff --git a/native/jni/include/db.h b/native/jni/include/db.h index 50f8605ca..7b5726e0a 100644 --- a/native/jni/include/db.h +++ b/native/jni/include/db.h @@ -154,7 +154,7 @@ typedef std::function db_row_cb; int get_db_settings(db_settings &cfg, int key = -1); int get_db_strings(db_strings &str, int key = -1); -int get_uid_policy(int uid, su_access &su); +int get_uid_policy(su_access &su, int uid); int validate_manager(std::string &alt_pkg, int userid, struct stat *st); void exec_sql(int client); char *db_exec(const char *sql); diff --git a/native/jni/su/connect.cpp b/native/jni/su/connect.cpp index f68997f18..4cf8720f1 100644 --- a/native/jni/su/connect.cpp +++ b/native/jni/su/connect.cpp @@ -11,12 +11,21 @@ #include "su.h" +bool CONNECT_BROADCAST; + #define START_ACTIVITY \ "/system/bin/app_process", "/system/bin", "com.android.commands.am.Am", \ "start", "-n", nullptr, "--user", nullptr, "-f", "0x18000020", "-a" // 0x18000020 = FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_MULTIPLE_TASK|FLAG_INCLUDE_STOPPED_PACKAGES +#define START_BROADCAST \ +"/system/bin/app_process", "/system/bin", "com.android.commands.am.Am", \ +"broadcast", "-n", nullptr, "--user", nullptr, "-f", "0x00000020", \ +"-a", "android.intent.action.REBOOT", "--es", "action" + +// 0x00000020 = FLAG_INCLUDE_STOPPED_PACKAGES + static inline const char *get_command(const su_request *to) { if (to->command[0]) return to->command; @@ -39,9 +48,9 @@ static inline void get_uid(char *uid, su_info *info) { : info->uid); } -static void silent_run(const char **args, su_info *info) { +static void exec_am_cmd(const char **args, su_info *info) { char component[128]; - sprintf(component, "%s/a.m", info->str[SU_MANAGER].data()); + sprintf(component, "%s/%s", info->str[SU_MANAGER].data(), args[3][0] == 'b' ? "a.h" : "a.m"); char user[8]; get_user(user, info); @@ -62,6 +71,16 @@ static void silent_run(const char **args, su_info *info) { exec_command(exec); } +#define LOG_BODY \ +"log", \ +"--ei", "from.uid", fromUid, \ +"--ei", "to.uid", toUid, \ +"--ei", "pid", pid, \ +"--ei", "policy", policy, \ +"--es", "command", get_command(&ctx->req), \ +"--ez", "notify", ctx->info->access.notify ? "true" : "false", \ +nullptr + void app_log(su_context *ctx) { char fromUid[8]; get_uid(fromUid, ctx->info); @@ -75,19 +94,21 @@ void app_log(su_context *ctx) { char policy[2]; sprintf(policy, "%d", ctx->info->access.policy); - const char *cmd[] = { - START_ACTIVITY, "log", - "--ei", "from.uid", fromUid, - "--ei", "to.uid", toUid, - "--ei", "pid", pid, - "--ei", "policy", policy, - "--es", "command", get_command(&ctx->req), - "--ez", "notify", ctx->info->access.notify ? "true" : "false", - nullptr - }; - silent_run(cmd, ctx->info); + if (CONNECT_BROADCAST) { + const char *cmd[] = { START_BROADCAST, LOG_BODY }; + exec_am_cmd(cmd, ctx->info); + } else { + const char *cmd[] = { START_ACTIVITY, LOG_BODY }; + exec_am_cmd(cmd, ctx->info); + } } +#define NOTIFY_BODY \ +"notify", \ +"--ei", "from.uid", fromUid, \ +"--ei", "policy", policy, \ +nullptr + void app_notify(su_context *ctx) { char fromUid[8]; get_uid(fromUid, ctx->info); @@ -95,13 +116,14 @@ void app_notify(su_context *ctx) { char policy[2]; sprintf(policy, "%d", ctx->info->access.policy); - const char *cmd[] = { - START_ACTIVITY, "notify", - "--ei", "from.uid", fromUid, - "--ei", "policy", policy, - nullptr - }; - silent_run(cmd, ctx->info); + if (CONNECT_BROADCAST) { + const char *cmd[] = { START_BROADCAST, NOTIFY_BODY }; + exec_am_cmd(cmd, ctx->info); + } else { + const char *cmd[] = { START_ACTIVITY, NOTIFY_BODY }; + exec_am_cmd(cmd, ctx->info); + } + } void app_connect(const char *socket, su_info *info) { @@ -110,7 +132,17 @@ void app_connect(const char *socket, su_info *info) { "--es", "socket", socket, nullptr }; - silent_run(cmd, info); + exec_am_cmd(cmd, info); +} + +void broadcast_test() { + su_info info; + get_db_settings(info.cfg); + get_db_strings(info.str); + validate_manager(info.str[SU_MANAGER], 0, &info.mgr_st); + + const char *cmd[] = { START_BROADCAST, "test", nullptr }; + exec_am_cmd(cmd, &info); } void socket_send_request(int fd, su_info *info) { diff --git a/native/jni/su/su.h b/native/jni/su/su.h index 4d7822c02..33672da7e 100644 --- a/native/jni/su/su.h +++ b/native/jni/su/su.h @@ -32,7 +32,7 @@ public: int ref; time_t timestamp; - su_info(unsigned uid); + su_info(unsigned uid = 0); ~su_info(); void lock(); void unlock(); diff --git a/native/jni/su/su_daemon.cpp b/native/jni/su/su_daemon.cpp index 3d69bddda..d9f022e4d 100644 --- a/native/jni/su/su_daemon.cpp +++ b/native/jni/su/su_daemon.cpp @@ -83,7 +83,7 @@ static void database_check(su_info *info) { } if (uid > 0) - get_uid_policy(uid, info->access); + get_uid_policy(info->access, uid); // We need to check our manager if (info->access.log || info->access.notify) diff --git a/net/src/main/java/com/topjohnwu/net/Networking.java b/net/src/main/java/com/topjohnwu/net/Networking.java index a79274e53..f2033c1b1 100644 --- a/net/src/main/java/com/topjohnwu/net/Networking.java +++ b/net/src/main/java/com/topjohnwu/net/Networking.java @@ -44,7 +44,7 @@ public class Networking { gms.getClassLoader() .loadClass("com.google.android.gms.common.security.ProviderInstallerImpl") .getMethod("insertProvider", Context.class) - .invoke(null, context); + .invoke(null, gms); } catch (Exception e) { // Failed to update SSL provider, use NoSSLv3SocketFactory on SDK < 21 if (Build.VERSION.SDK_INT < 21) diff --git a/signing/build.gradle b/signing/build.gradle index 339e21088..f8ebecd19 100644 --- a/signing/build.gradle +++ b/signing/build.gradle @@ -33,6 +33,8 @@ repositories { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'org.bouncycastle:bcprov-jdk15on:1.60' - implementation 'org.bouncycastle:bcpkix-jdk15on:1.60' + + def bcVer = '1.61' + api "org.bouncycastle:bcprov-jdk15on:${bcVer}" + api "org.bouncycastle:bcpkix-jdk15on:${bcVer}" } diff --git a/signing/src/main/java/com/topjohnwu/signing/JarMap.java b/signing/src/main/java/com/topjohnwu/signing/JarMap.java index 44e61e11b..e9677e7e0 100644 --- a/signing/src/main/java/com/topjohnwu/signing/JarMap.java +++ b/signing/src/main/java/com/topjohnwu/signing/JarMap.java @@ -23,7 +23,7 @@ import java.util.zip.ZipFile; * On the other hand, when a JarFile is provided, it simply works as a wrapper. * */ -public class JarMap implements Closeable, AutoCloseable { +public class JarMap implements Closeable { private JarFile jarFile; private JarInputStream jis; @@ -119,7 +119,10 @@ public class JarMap implements Closeable, AutoCloseable { @Override public void close() throws IOException { - (jarFile == null ? jis : jarFile).close(); + if (jarFile != null) + jarFile.close(); + else + jis.close(); } private static class JarMapEntry extends JarEntry { diff --git a/signing/src/main/java/com/topjohnwu/signing/SignAPK.java b/signing/src/main/java/com/topjohnwu/signing/SignAPK.java index 711256cc5..f218f0a48 100644 --- a/signing/src/main/java/com/topjohnwu/signing/SignAPK.java +++ b/signing/src/main/java/com/topjohnwu/signing/SignAPK.java @@ -11,7 +11,6 @@ import org.bouncycastle.cms.CMSSignedData; import org.bouncycastle.cms.CMSSignedDataGenerator; import org.bouncycastle.cms.CMSTypedData; import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; -import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; @@ -60,16 +59,11 @@ public class SignAPK { private static final String CERT_SF_NAME = "META-INF/CERT.SF"; private static final String CERT_SIG_NAME = "META-INF/CERT.%s"; - private static Provider sBouncyCastleProvider; + private static Provider sBouncyCastleProvider = Security.getProvider("BC"); // bitmasks for which hash algorithms we need the manifest to include. private static final int USE_SHA1 = 1; private static final int USE_SHA256 = 2; - static { - sBouncyCastleProvider = new BouncyCastleProvider(); - Security.insertProviderAt(sBouncyCastleProvider, 1); - } - public static void sign(JarMap input, OutputStream output) throws Exception { sign(SignAPK.class.getResourceAsStream("/keys/testkey.x509.pem"), SignAPK.class.getResourceAsStream("/keys/testkey.pk8"), input, output); diff --git a/signing/src/main/java/com/topjohnwu/signing/SignBoot.java b/signing/src/main/java/com/topjohnwu/signing/SignBoot.java index 2a877e14d..11ed30bc1 100644 --- a/signing/src/main/java/com/topjohnwu/signing/SignBoot.java +++ b/signing/src/main/java/com/topjohnwu/signing/SignBoot.java @@ -12,7 +12,6 @@ import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERPrintableString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.io.ByteArrayInputStream; import java.io.FilterInputStream; @@ -23,7 +22,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.security.PrivateKey; import java.security.PublicKey; -import java.security.Security; import java.security.Signature; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateFactory; @@ -32,10 +30,6 @@ import java.util.Arrays; public class SignBoot { - static { - Security.addProvider(new BouncyCastleProvider()); - } - private static class PushBackRWStream extends FilterInputStream { private OutputStream out; private int pos = 0; diff --git a/signing/src/main/java/com/topjohnwu/signing/ZipSigner.java b/signing/src/main/java/com/topjohnwu/signing/ZipSigner.java index cb437f9bf..8e68de715 100644 --- a/signing/src/main/java/com/topjohnwu/signing/ZipSigner.java +++ b/signing/src/main/java/com/topjohnwu/signing/ZipSigner.java @@ -1,9 +1,12 @@ package com.topjohnwu.signing; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; +import java.security.Security; public class ZipSigner { @@ -22,6 +25,8 @@ public class ZipSigner { if (args.length != 2 && args.length != 4 && args.length != 6) usage(); + Security.insertProviderAt(new BouncyCastleProvider(), 1); + try (JarMap in = new JarMap(args[args.length - 2], false); OutputStream out = new FileOutputStream(args[args.length - 1])) { if (args.length == 2) {