From 06c1652d532aaa010ffe13a28867a8a6f4dfdc81 Mon Sep 17 00:00:00 2001 From: RainChan Date: Wed, 25 Aug 2021 15:07:56 +0800 Subject: [PATCH] Bypass BC deprecation check on Android (#1481) Co-authored-by: Karlatemp Co-authored-by: Karlatemp --- buildSrc/src/main/kotlin/Versions.kt | 4 ++- mirai-core/build.gradle.kts | 5 ++-- .../kotlin/utils/crypto/ECDHJvmDesktop.kt | 28 ++++++++++++++++++- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 84626da14..8e51745bf 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -45,6 +45,7 @@ object Versions { const val asm = "9.1" const val difflib = "1.3.0" const val netty = "4.1.63.Final" + const val bouncycastle = "1.64" const val junit = "5.7.2" @@ -121,4 +122,5 @@ const val `jetbrains-annotations` = "org.jetbrains:annotations:19.0.0" const val `caller-finder` = "io.github.karlatemp:caller:1.1.1" const val `android-runtime` = "com.google.android:android:${Versions.android}" -const val `netty-all` = "io.netty:netty-all:${Versions.netty}" \ No newline at end of file +const val `netty-all` = "io.netty:netty-all:${Versions.netty}" +const val `bouncycastle` = "org.bouncycastle:bcprov-jdk15on:${Versions.bouncycastle}" \ No newline at end of file diff --git a/mirai-core/build.gradle.kts b/mirai-core/build.gradle.kts index e6fbb2cc7..e3503407b 100644 --- a/mirai-core/build.gradle.kts +++ b/mirai-core/build.gradle.kts @@ -73,6 +73,7 @@ kotlin { implementation1(`kotlinx-coroutines-io`) implementation(`netty-all`) implementation(`log4j-api`) + implementation(bouncycastle) } } @@ -95,14 +96,14 @@ kotlin { implementation(kotlin("test-junit5", Versions.kotlinCompiler)) implementation(kotlin("test-annotations-common")) implementation(kotlin("test-common")) - implementation("org.bouncycastle:bcprov-jdk15on:1.64") + //implementation("org.bouncycastle:bcprov-jdk15on:1.64") } } } val jvmMain by getting { dependencies { - implementation("org.bouncycastle:bcprov-jdk15on:1.64") + //implementation("org.bouncycastle:bcprov-jdk15on:1.64") // api(kotlinx("coroutines-debug", Versions.coroutines)) } } diff --git a/mirai-core/src/androidMain/kotlin/utils/crypto/ECDHJvmDesktop.kt b/mirai-core/src/androidMain/kotlin/utils/crypto/ECDHJvmDesktop.kt index fff6d1196..610e005b9 100644 --- a/mirai-core/src/androidMain/kotlin/utils/crypto/ECDHJvmDesktop.kt +++ b/mirai-core/src/androidMain/kotlin/utils/crypto/ECDHJvmDesktop.kt @@ -11,6 +11,7 @@ package net.mamoe.mirai.internal.utils.crypto import net.mamoe.mirai.utils.decodeBase64 import net.mamoe.mirai.utils.md5 +import net.mamoe.mirai.utils.recoverCatchingSuppressed import java.security.* import java.security.spec.ECGenParameterSpec import java.security.spec.X509EncodedKeySpec @@ -32,6 +33,31 @@ internal actual class ECDHKeyPairImpl( override val maskedShareKey: ByteArray by lazy { ECDH.calculateShareKey(privateKey, initialPublicKey) } } +/** + * 绕过在Android P之后的版本无法使用EC的限制 + * https://cs.android.com/android/platform/superproject/+/master:libcore/ojluni/src/main/java/sun/security/jca/Providers.java;l=371;bpv=1;bpt=1 + * https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html + * */ +private class AndroidProvider : Provider("sbAndroid", 1.0, "") { + override fun getService(type: String?, algorithm: String?): Service? { + if (type == "KeyFactory" && algorithm == "EC") { + return object : Service(this, type, algorithm, "", emptyList(), emptyMap()) { + override fun newInstance(constructorParameter: Any?): Any { + return org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi.EC() + } + } + } + return super.getService(type, algorithm) + } +} + +private val ANDROID_PROVIDER by lazy { AndroidProvider() } +private val ecKf by lazy { + runCatching { KeyFactory.getInstance("EC", "BC") } + .recoverCatchingSuppressed { KeyFactory.getInstance("EC", ANDROID_PROVIDER) } + .getOrThrow() +} + internal actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) { actual companion object { private const val curveName = "prime256v1" // p-256 @@ -88,7 +114,7 @@ internal actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) { } actual fun constructPublicKey(key: ByteArray): ECDHPublicKey { - return KeyFactory.getInstance("EC", "BC").generatePublic(X509EncodedKeySpec(key)) + return ecKf.generatePublic(X509EncodedKeySpec(key)) } }