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) {