Skip to content

Commit 48f519b

Browse files
authored
Merge pull request #285 from simple-robot/dev/improve-ed25519
为 ed25519 更换实现
2 parents 4b74f10 + 5dbb217 commit 48f519b

File tree

29 files changed

+1285
-324
lines changed

29 files changed

+1285
-324
lines changed

.github/workflows/kdoc.yml.bk

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
- name: Gradle generate documentation
2929
uses: gradle/gradle-build-action@v2
3030
with:
31-
gradle-version: 8.5
31+
gradle-version: 8.8
3232
arguments: |
3333
-Porg.gradle.jvmargs="-Xmx4g -Xms4g -XX:MaxMetaspaceSize=2g -Dfile.encoding=UTF-8"
3434
-Porg.gradle.daemon=false

.github/workflows/publish-v4-release.yml.bk

+4-4
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ jobs:
4040
- name: Gradle Run Test
4141
uses: gradle/gradle-build-action@v2
4242
with:
43-
gradle-version: 8.5
43+
gradle-version: 8.8
4444
arguments: assemble test -Porg.gradle.daemon=false
4545

4646
# setup Gradle
4747
- name: Publish Release
4848
uses: gradle/gradle-build-action@v2
4949
with:
50-
gradle-version: 8.5
50+
gradle-version: 8.8
5151
arguments: |
5252
publishToSonatype
5353
closeAndReleaseStagingRepositories
@@ -105,7 +105,7 @@ jobs:
105105
- name: Gradle publish snapshot
106106
uses: gradle/gradle-build-action@v2
107107
with:
108-
gradle-version: 8.5
108+
gradle-version: 8.8
109109
arguments: |
110110
publishToSonatype
111111
closeAndReleaseStagingRepositories
@@ -141,7 +141,7 @@ jobs:
141141
- name: Gradle generate documentation
142142
uses: gradle/gradle-build-action@v2
143143
with:
144-
gradle-version: 8.5
144+
gradle-version: 8.8
145145
arguments: |
146146
dokkaHtmlMultiModule
147147
--info

.github/workflows/publish-v4-snapshot.yml.bk

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ jobs:
5757
- name: Gradle test and publish snapshot
5858
uses: gradle/gradle-build-action@v2
5959
with:
60-
gradle-version: 8.5
60+
gradle-version: 8.8
6161
arguments: |
6262
test
6363
publishToSonatype
@@ -89,7 +89,7 @@ jobs:
8989
- name: Gradle generate documentation
9090
uses: gradle/gradle-build-action@v2
9191
with:
92-
gradle-version: 8.5
92+
gradle-version: 8.8
9393
arguments: |
9494
-Porg.gradle.jvmargs="-Xmx4g -Xms4g -XX:MaxMetaspaceSize=2g -Dfile.encoding=UTF-8"
9595
-Porg.gradle.daemon=false

.github/workflows/test-branch.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ jobs:
3333
with:
3434
distribution: 'zulu'
3535
java-version: 21
36-
# cache: 'gradle'
36+
cache: 'gradle'
3737

3838
- name: Run All Tests
3939
uses: gradle/actions/setup-gradle@v3
4040
with:
41-
gradle-version: 8.5
41+
gradle-version: 8.8
4242
arguments: |
4343
assemble
4444
build

build.gradle.kts

+2-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ apiValidation {
108108
"love.forte.simbot.annotations.InternalSimbotAPI",
109109
"love.forte.simbot.qguild.QGInternalApi",
110110
"love.forte.simbot.component.qguild.ExperimentalQGApi",
111-
"love.forte.simbot.qguild.ExperimentalQGMediaApi"
111+
"love.forte.simbot.qguild.ExperimentalQGMediaApi",
112+
"love.forte.simbot.qguild.ed25519.annotations.InternalEd25519Api"
112113
),
113114
)
114115

buildSrc/src/main/kotlin/JvmConfig.kt

+13-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024. ForteScarlet.
2+
* Copyright (c) 2024-2025. ForteScarlet.
33
*
44
* This file is part of simbot-component-qq-guild.
55
*
@@ -21,13 +21,11 @@ import org.gradle.api.tasks.compile.JavaCompile
2121
import org.gradle.kotlin.dsl.assign
2222
import org.gradle.kotlin.dsl.get
2323
import org.gradle.kotlin.dsl.getByName
24-
import org.gradle.kotlin.dsl.withType
2524
import org.gradle.process.CommandLineArgumentProvider
2625
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
2726
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
2827
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
2928
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
30-
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
3129
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
3230

3331

@@ -52,25 +50,23 @@ inline fun KotlinJvmTarget.configJava(crossinline block: KotlinJvmTarget.() -> U
5250
}
5351

5452

55-
fun KotlinTopLevelExtension.configJavaToolchain(jdkVersion: Int) {
56-
jvmToolchain(jdkVersion)
57-
}
58-
5953
inline fun KotlinMultiplatformExtension.configKotlinJvm(
6054
jdkVersion: Int = JVMConstants.KT_JVM_TARGET_VALUE,
6155
crossinline block: KotlinJvmTarget.() -> Unit = {}
6256
) {
63-
configJavaToolchain(jdkVersion)
57+
jvmToolchain(jdkVersion)
6458
jvm {
6559
configJava(block)
60+
compilerOptions {
61+
}
6662
}
6763
}
6864

6965
inline fun KotlinJvmProjectExtension.configKotlinJvm(
7066
jdkVersion: Int = JVMConstants.KT_JVM_TARGET_VALUE,
7167
crossinline block: KotlinJvmProjectExtension.() -> Unit = {}
7268
) {
73-
configJavaToolchain(jdkVersion)
69+
jvmToolchain(jdkVersion)
7470
compilerOptions {
7571
javaParameters = true
7672
jvmTarget.set(JvmTarget.fromTarget(jdkVersion.toString()))
@@ -80,16 +76,23 @@ inline fun KotlinJvmProjectExtension.configKotlinJvm(
8076
block()
8177
}
8278

79+
/**
80+
* 要放在 `kotlin {}` 下面
81+
*/
8382
inline fun Project.configJavaCompileWithModule(
8483
moduleName: String? = null,
8584
jvmVersion: String = JVMConstants.KT_JVM_TARGET,
8685
crossinline block: JavaCompile.() -> Unit = {}
8786
) {
88-
tasks.withType<JavaCompile> {
87+
tasks.named("compileJava", JavaCompile::class.java) {
8988
options.encoding = "UTF-8"
9089
sourceCompatibility = jvmVersion
9190
targetCompatibility = jvmVersion
9291

92+
println("$this sourceSets[\"main\"]: ${sourceSets["main"]}")
93+
println("$this sourceSets[\"main\"].output: ${sourceSets["main"].output}")
94+
println("$this sourceSets[\"main\"].output.asPath: ${sourceSets["main"].output.asPath}")
95+
9396
if (moduleName != null) {
9497
options.compilerArgumentProviders.add(CommandLineArgumentProvider {
9598
// Provide compiled Kotlin classes to javac – needed for Java/Kotlin mixed sources to work

gradle/libs.versions.toml

+11-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ kotlinPoet = "2.0.0"
2020
# TODO apply detekt
2121
detekt = "1.23.7"
2222

23-
23+
#
24+
bouncycastle = "1.80"
25+
#
26+
eddsa = "0.3.0"
27+
# https://github.com/ionspin/kotlin-multiplatform-libsodium
28+
libsodium-bindings = "0.9.2"
2429
[libraries]
2530
# simbot
2631
simbot-api = { group = "love.forte.simbot", name = "simbot-api", version.ref = "simbot" }
@@ -109,6 +114,11 @@ gradle-common-core = { group = "love.forte.gradle.common", name = "gradle-common
109114
gradle-common-multiplatform = { group = "love.forte.gradle.common", name = "gradle-common-kotlin-multiplatform", version.ref = "gradleCommon" }
110115
gradle-common-publication = { group = "love.forte.gradle.common", name = "gradle-common-publication", version.ref = "gradleCommon" }
111116

117+
# ed25519
118+
bouncycastle-bcprov-jdk18on = { module = "org.bouncycastle:bcprov-jdk18on", version.ref = "bouncycastle" }
119+
i2p-crypto-eddsa = { module = "net.i2p.crypto:eddsa", version.ref = "eddsa" }
120+
libsodium-bindings = { module = "com.ionspin.kotlin:multiplatform-crypto-libsodium-bindings", version.ref= "libsodium-bindings" }
121+
112122
[plugins]
113123
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
114124
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }

settings.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ include(":internal-processors:intents-processor")
3333
include(":simbot-component-qq-guild-api")
3434
include(":simbot-component-qq-guild-stdlib")
3535
include(":simbot-component-qq-guild-core")
36+
include(":simbot-component-qq-guild-internal-ed25519")
3637

3738
// samples
3839
include(":samples:webhook-server-ktor")

simbot-component-qq-guild-api/build.gradle.kts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023-2024. ForteScarlet.
2+
* Copyright (c) 2023-2025. ForteScarlet.
33
*
44
* This file is part of simbot-component-qq-guild.
55
*
@@ -34,8 +34,6 @@ plugins {
3434

3535
setup(P.ComponentQQGuild)
3636

37-
configJavaCompileWithModule("simbot.component.qqguild.api")
38-
//apply(plugin = "qq-guild-dokka-partial-configure")
3937
apply(plugin = "qq-guild-multiplatform-maven-publish")
4038

4139
//configJsTestTasks()
@@ -133,3 +131,5 @@ tasks.withType<DokkaTaskPartial>().configureEach {
133131
suppressGeneratedFiles.set(false)
134132
}
135133
}
134+
135+
configJavaCompileWithModule("simbot.component.qqguild.api")

simbot-component-qq-guild-core/build.gradle.kts

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ plugins {
3030

3131
setup(P.ComponentQQGuild)
3232

33-
configJavaCompileWithModule("simbot.component.qqguild.core")
3433
apply(plugin = "qq-guild-multiplatform-maven-publish")
3534

3635
configJsTestTasks()
@@ -98,3 +97,5 @@ kotlin {
9897
}
9998
}
10099
}
100+
101+
configJavaCompileWithModule("simbot.component.qqguild.core")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# internal ed25519 module
2+
3+
一个内部使用的用于提供对 ed25519 签名的支持的模块。
4+
通过 `ed25519KeyPairGenerator()` 获取一个当前平台支持的 `Ed25519KeyPairGenerator` 实例。
5+
6+
```Kotlin
7+
val generator = ed25519KeyPairGenerator()
8+
val (privateKey, publicKey) = generator.generate(seed)
9+
```
10+
11+
非 JVM 平台中,均使用 [libsodium bindings](https://github.com/ionspin/kotlin-multiplatform-libsodium)
12+
作为实现。
13+
14+
JVM 中优先尝试检测是否存在以下类:
15+
16+
- `org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters`
17+
- `org.bouncycastle.crypto.params.Ed25519PublicKeyParameters`
18+
- `org.bouncycastle.crypto.signers.Ed25519Signer`
19+
20+
如果存在,则使用这些类进行签名操作,也就是使用 [BouncyCastle](https://www.bouncycastle.org/)
21+
(编译时使用的是 `org.bouncycastle:bcprov-jdk18on:1.80`)
22+
进行密钥的生成或签名/验签。
23+
24+
当 BouncyCastle 的相关类存在时,使用 `ed25519KeyPairGenerator().generate(seed)` 相当于:
25+
26+
```Kotlin
27+
val (privateKey, publicKey) = BouncyCastleEd25519KeyPair(seed)
28+
```
29+
30+
如果 BouncyCastle 的相关类不存在,则使用 [ed25519-java](https://github.com/str4d/ed25519-java)
31+
作为实现库。此库默认作为 `implementation` 加载于 classpath 中。
32+
相比于 BouncyCastle (≈8,480 KB ≈8.48 MB),它轻量得多 (≈62 KB)。
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public abstract interface annotation class love/forte/simbot/qguild/ed25519/annotations/InternalEd25519Api : java/lang/annotation/Annotation {
2+
}
3+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (c) 2022-2025. ForteScarlet.
3+
*
4+
* This file is part of simbot-component-qq-guild.
5+
*
6+
* simbot-component-qq-guild is free software: you can redistribute it and/or modify it under the terms
7+
* of the GNU Lesser General Public License as published by the Free Software Foundation,
8+
* either version 3 of the License, or (at your option) any later version.
9+
*
10+
* simbot-component-qq-guild is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
* See the GNU Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public License along with simbot-component-qq-guild.
15+
* If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
18+
import love.forte.gradle.common.core.project.setup
19+
import love.forte.gradle.common.kotlin.multiplatform.applyTier1
20+
import love.forte.gradle.common.kotlin.multiplatform.applyTier2
21+
import love.forte.gradle.common.kotlin.multiplatform.applyTier3
22+
23+
plugins {
24+
kotlin("multiplatform")
25+
`qq-guild-dokka-partial-configure`
26+
`qq-guild-module-config`
27+
}
28+
29+
setup(P.ComponentQQGuild)
30+
31+
apply(plugin = "qq-guild-multiplatform-maven-publish")
32+
33+
configJsTestTasks()
34+
35+
kotlin {
36+
explicitApi()
37+
applyDefaultHierarchyTemplate()
38+
39+
sourceSets.configureEach {
40+
languageSettings {
41+
}
42+
}
43+
44+
configKotlinJvm()
45+
46+
js(IR) {
47+
configJs()
48+
}
49+
50+
applyTier1()
51+
applyTier2(
52+
// multiplatform-crypto-libsodium 不支持 watchosX64 target.
53+
watchosX64 = false,
54+
55+
)
56+
applyTier3(
57+
androidNativeArm32 = false,
58+
androidNativeArm64 = false,
59+
androidNativeX64 = false,
60+
androidNativeX86 = false,
61+
watchosDeviceArm64 = false,
62+
)
63+
64+
sourceSets {
65+
commonMain.dependencies {
66+
implementation(libs.simbot.logger)
67+
}
68+
69+
commonTest.dependencies {
70+
implementation(kotlin("test"))
71+
implementation(libs.kotlinx.coroutines.test)
72+
}
73+
74+
jvmMain.dependencies {
75+
implementation(libs.i2p.crypto.eddsa)
76+
compileOnly(libs.bouncycastle.bcprov.jdk18on)
77+
}
78+
79+
jvmTest.dependencies {
80+
implementation(libs.i2p.crypto.eddsa)
81+
implementation(libs.bouncycastle.bcprov.jdk18on)
82+
}
83+
84+
jsMain.dependencies {
85+
implementation(libs.libsodium.bindings)
86+
}
87+
88+
nativeMain.dependencies {
89+
implementation(libs.libsodium.bindings)
90+
implementation(libs.kotlinx.coroutines.core)
91+
}
92+
}
93+
}
94+
95+
configJavaCompileWithModule("simbot.component.qqguild.internal.ed25519s")
96+

0 commit comments

Comments
 (0)