Bypass BC deprecation check on Android (#1481)

Co-authored-by: Karlatemp <karlatemp@vip.qq.com>

Co-authored-by: Karlatemp <karlatemp@vip.qq.com>
This commit is contained in:
RainChan 2021-08-25 15:07:56 +08:00 committed by GitHub
parent cda50e73a4
commit 06c1652d53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 4 deletions

View File

@ -45,6 +45,7 @@ object Versions {
const val asm = "9.1" const val asm = "9.1"
const val difflib = "1.3.0" const val difflib = "1.3.0"
const val netty = "4.1.63.Final" const val netty = "4.1.63.Final"
const val bouncycastle = "1.64"
const val junit = "5.7.2" 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 `caller-finder` = "io.github.karlatemp:caller:1.1.1"
const val `android-runtime` = "com.google.android:android:${Versions.android}" const val `android-runtime` = "com.google.android:android:${Versions.android}"
const val `netty-all` = "io.netty:netty-all:${Versions.netty}" const val `netty-all` = "io.netty:netty-all:${Versions.netty}"
const val `bouncycastle` = "org.bouncycastle:bcprov-jdk15on:${Versions.bouncycastle}"

View File

@ -73,6 +73,7 @@ kotlin {
implementation1(`kotlinx-coroutines-io`) implementation1(`kotlinx-coroutines-io`)
implementation(`netty-all`) implementation(`netty-all`)
implementation(`log4j-api`) implementation(`log4j-api`)
implementation(bouncycastle)
} }
} }
@ -95,14 +96,14 @@ kotlin {
implementation(kotlin("test-junit5", Versions.kotlinCompiler)) implementation(kotlin("test-junit5", Versions.kotlinCompiler))
implementation(kotlin("test-annotations-common")) implementation(kotlin("test-annotations-common"))
implementation(kotlin("test-common")) implementation(kotlin("test-common"))
implementation("org.bouncycastle:bcprov-jdk15on:1.64") //implementation("org.bouncycastle:bcprov-jdk15on:1.64")
} }
} }
} }
val jvmMain by getting { val jvmMain by getting {
dependencies { dependencies {
implementation("org.bouncycastle:bcprov-jdk15on:1.64") //implementation("org.bouncycastle:bcprov-jdk15on:1.64")
// api(kotlinx("coroutines-debug", Versions.coroutines)) // api(kotlinx("coroutines-debug", Versions.coroutines))
} }
} }

View File

@ -11,6 +11,7 @@ package net.mamoe.mirai.internal.utils.crypto
import net.mamoe.mirai.utils.decodeBase64 import net.mamoe.mirai.utils.decodeBase64
import net.mamoe.mirai.utils.md5 import net.mamoe.mirai.utils.md5
import net.mamoe.mirai.utils.recoverCatchingSuppressed
import java.security.* import java.security.*
import java.security.spec.ECGenParameterSpec import java.security.spec.ECGenParameterSpec
import java.security.spec.X509EncodedKeySpec import java.security.spec.X509EncodedKeySpec
@ -32,6 +33,31 @@ internal actual class ECDHKeyPairImpl(
override val maskedShareKey: ByteArray by lazy { ECDH.calculateShareKey(privateKey, initialPublicKey) } 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) { internal actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) {
actual companion object { actual companion object {
private const val curveName = "prime256v1" // p-256 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 { actual fun constructPublicKey(key: ByteArray): ECDHPublicKey {
return KeyFactory.getInstance("EC", "BC").generatePublic(X509EncodedKeySpec(key)) return ecKf.generatePublic(X509EncodedKeySpec(key))
} }
} }