@@ -6,7 +6,9 @@ import io.nekohasekai.sagernet.ktx.toLink
66import io.nekohasekai.sagernet.ktx.urlSafe
77import moe.matsuri.nb4a.SingBoxOptions
88import moe.matsuri.nb4a.SingBoxOptions.Outbound_JuicityOptions
9+ import moe.matsuri.nb4a.utils.listByLineOrComma
910import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
11+ import java.util.Base64
1012
1113fun parseJuicity (url : String ): JuicityBean {
1214 val link = url.replace(" juicity://" , " https://" ).toHttpUrlOrNull() ? : error(
@@ -23,7 +25,9 @@ fun parseJuicity(url: String): JuicityBean {
2325 sni = it
2426 }
2527 link.queryParameter(" pinned_certchain_sha256" )?.let {
26- pinnedCertchainSha256 = it
28+ normalizePinnedCertChainHash(it)?.let { hash ->
29+ pinnedCertchainSha256 = hash
30+ }
2731 }
2832 link.queryParameter(" allow_insecure" )?.let {
2933 if (it == " 1" || it == " true" ) allowInsecure = true
@@ -38,7 +42,9 @@ fun JuicityBean.toUri(): String {
3842 builder.addQueryParameter(" sni" , sni)
3943 }
4044 if (pinnedCertchainSha256.isNotBlank()) {
41- builder.addQueryParameter(" pinned_certchain_sha256" , pinnedCertchainSha256)
45+ normalizePinnedCertChainHash(pinnedCertchainSha256.listByLineOrComma().firstOrNull())?.let {
46+ builder.addQueryParameter(" pinned_certchain_sha256" , it)
47+ }
4248 }
4349 if (allowInsecure) {
4450 builder.addQueryParameter(" allow_insecure" , " 1" )
@@ -68,7 +74,18 @@ fun buildSingBoxOutboundJuicityBean(bean: JuicityBean): Outbound_JuicityOptions
6874 }
6975
7076 if (bean.pinnedCertchainSha256.isNotBlank()) {
71- pin_cert_sha256 = bean.pinnedCertchainSha256
77+ normalizePinnedCertChainHash(bean.pinnedCertchainSha256.listByLineOrComma().firstOrNull())?.let {
78+ pin_cert_sha256 = it
79+ }
7280 }
7381 }
7482}
83+
84+ private fun normalizePinnedCertChainHash (rawHash : String? ): String? {
85+ val certChainHash = rawHash?.replace(" :" , " " )?.takeIf { it.isNotEmpty() } ? : return null
86+ return when {
87+ certChainHash.length == 64 -> Base64 .getUrlEncoder()
88+ .encodeToString(certChainHash.chunked(2 ).map { chunk -> chunk.toInt(16 ).toByte() }.toByteArray())
89+ else -> certChainHash.replace(' /' , ' _' ).replace(' +' , ' -' )
90+ }
91+ }
0 commit comments