From 1f8de2109854865c1d66254d0499541e7b37a8a1 Mon Sep 17 00:00:00 2001 From: Secozzi <49240133+Secozzi@users.noreply.github.com> Date: Tue, 11 Jul 2023 12:28:16 +0200 Subject: [PATCH] fix(lib/chillx-extractor): update key & small refactor (#1888) --- lib/chillx-extractor/build.gradle.kts | 1 + .../lib/chillxextractor/ChillxExtractor.kt | 57 +++++++------------ 2 files changed, 20 insertions(+), 38 deletions(-) diff --git a/lib/chillx-extractor/build.gradle.kts b/lib/chillx-extractor/build.gradle.kts index c2d02170b..7b9e04b82 100644 --- a/lib/chillx-extractor/build.gradle.kts +++ b/lib/chillx-extractor/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("com.android.library") kotlin("android") + id("kotlinx-serialization") } android { diff --git a/lib/chillx-extractor/src/main/java/eu/kanade/tachiyomi/lib/chillxextractor/ChillxExtractor.kt b/lib/chillx-extractor/src/main/java/eu/kanade/tachiyomi/lib/chillxextractor/ChillxExtractor.kt index 7a35aa6ae..2ab7adc24 100644 --- a/lib/chillx-extractor/src/main/java/eu/kanade/tachiyomi/lib/chillxextractor/ChillxExtractor.kt +++ b/lib/chillx-extractor/src/main/java/eu/kanade/tachiyomi/lib/chillxextractor/ChillxExtractor.kt @@ -683,7 +683,7 @@ import android.util.Base64 import eu.kanade.tachiyomi.animesource.model.Video import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.util.asJsoup -import kotlinx.serialization.decodeFromString +import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.jsonPrimitive @@ -707,37 +707,16 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea ).execute().asJsoup().html() val master = Regex("""MasterJS\s*=\s*'([^']+)""").find(document)?.groupValues?.get(1) - val aesJson = Json.decodeFromString(base64Decode(master ?: return null).toString(Charsets.UTF_8)) + val aesJson = Json.decodeFromString(base64Decode(master ?: return null).toString(Charsets.UTF_8)) - val encData = - try { - AESData( - aesJson["ciphertext"]!!.jsonPrimitive.content, - aesJson["iv"]!!.jsonPrimitive.content, - aesJson["salt"]!!.jsonPrimitive.content, - aesJson["iterations"]!!.jsonPrimitive.content, - ) - } catch(_: Exception) { - null - } + val decrypt = cryptoAESHandler(aesJson ?: return null, KEY) - val decrypt = cryptoAESHandler(encData ?: return null, KEY) val playlistUrl = Regex("""sources:\s*\[\{"file":"([^"]+)""").find(decrypt)?.groupValues?.get(1) ?: return null val tracks = Regex("""tracks:\s*\[(.+)]""").find(decrypt)?.groupValues?.get(1) - val trackJson = Json.decodeFromString(tracks ?: return null) - // TODO: Add subtitle support when a site is found that uses it - val trackData = - try { - SubtitleTrack( - trackJson["file"]!!.jsonPrimitive.content, - trackJson["label"]!!.jsonPrimitive.content, - trackJson["kind"]!!.jsonPrimitive.content, - ) - } catch(_: Exception) { - null - } + // TODO: Add subtitle support when a site is found that uses it + val trackJson = Json.decodeFromString(tracks ?: return null) val masterHeaders = Headers.headersOf( "Accept", "*/*", @@ -752,8 +731,8 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea val response = client.newCall(GET(playlistUrl, headers = masterHeaders)).execute() val masterPlaylist = response.body.string() - masterPlaylist?.substringAfter("#EXT-X-STREAM-INF:") - ?.split("#EXT-X-STREAM-INF:")?.map { + masterPlaylist.substringAfter("#EXT-X-STREAM-INF:") + .split("#EXT-X-STREAM-INF:").map { val quality = it.substringAfter("RESOLUTION=").split(",")[0].split("\n")[0].substringAfter("x") + "p" var videoUrl = it.substringAfter("\n").substringBefore("\n") @@ -771,14 +750,14 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea } private fun cryptoAESHandler( - data: AESData, + data: CryptoInfo, pass: String, ): String { val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512") val spec = PBEKeySpec( pass.toCharArray(), data.salt?.hexToByteArray(), - data.iterations?.toIntOrNull() ?: 1, + data.iterations ?: 1, 256 ) val key = factory.generateSecret(spec) @@ -795,6 +774,14 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea return Base64.decode(string, Base64.DEFAULT) } + @Serializable + data class CryptoInfo( + val ciphertext: String? = null, + val iv: String? = null, + val salt: String? = null, + val iterations: Int? = null, + ) + private fun String.hexToByteArray(): ByteArray { check(length % 2 == 0) { "Must have an even length" } return chunked(2) @@ -803,13 +790,7 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea .toByteArray() } - data class AESData( - val ciphertext: String? = null, - val iv: String? = null, - val salt: String? = null, - val iterations: String? = null, - ) - + @Serializable data class SubtitleTrack( val file: String? = null, val label: String? = null, @@ -817,6 +798,6 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea ) companion object { - private const val KEY = "4VqE3#N7zt&HEP^a" + private const val KEY = "11x&W5UBrcqn\$9Yl" } }