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 difflib = "1.3.0"
const val netty = "4.1.63.Final"
const val bouncycastle = "1.64"
const val junit = "5.7.2"
@ -122,3 +123,4 @@ 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}"
const val `bouncycastle` = "org.bouncycastle:bcprov-jdk15on:${Versions.bouncycastle}"

View File

@ -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))
}
}

View File

@ -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))
}
}