diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/VidStack.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/VidStack.kt index 5861499412d..7b52cfdf895 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/VidStack.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/VidStack.kt @@ -3,6 +3,8 @@ package com.lagradost.cloudstream3.extractors import com.lagradost.api.Log import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.extractors.helper.AesHelper.hexToByteArray +import com.lagradost.cloudstream3.extractors.helper.AesHelper.rawAesCbc import com.lagradost.cloudstream3.newSubtitleFile import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink @@ -10,9 +12,6 @@ import com.lagradost.cloudstream3.utils.ExtractorLinkType import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.fixUrl import com.lagradost.cloudstream3.utils.newExtractorLink -import dev.whyoleg.cryptography.CryptographyProvider -import dev.whyoleg.cryptography.DelicateCryptographyApi -import dev.whyoleg.cryptography.algorithms.AES import io.ktor.http.Url class Server1uns : VidStack() { @@ -21,7 +20,6 @@ class Server1uns : VidStack() { override var requiresReferer = true } - open class VidStack : ExtractorApi() { override var name = "Vidstack" override var mainUrl = "https://vidstack.io" @@ -31,7 +29,7 @@ open class VidStack : ExtractorApi() { url: String, referer: String?, subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit + callback: (ExtractorLink) -> Unit, ) { val headers = mapOf("User-Agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0") val hash = url.substringAfterLast("#").substringAfter("/") @@ -44,8 +42,14 @@ open class VidStack : ExtractorApi() { val decryptedText = ivList.firstNotNullOfOrNull { iv -> try { - AesHelper.decryptAES(encoded, key, iv) - } catch (e: Exception) { + rawAesCbc( + input = encoded.hexToByteArray(), + key = key.encodeToByteArray(), + iv = iv.encodeToByteArray(), + encrypt = false, + padding = true, + ).decodeToString() + } catch (_: Exception) { null } } ?: throw Exception("Failed to decrypt with all IVs") @@ -73,7 +77,7 @@ open class VidStack : ExtractorApi() { source = this.name, name = this.name, url = m3u8, - type = ExtractorLinkType.M3U8 + type = ExtractorLinkType.M3U8, ) { this.referer = url this.quality = Qualities.Unknown.value @@ -90,22 +94,3 @@ open class VidStack : ExtractorApi() { } } } - -object AesHelper { - private val aesCbc = CryptographyProvider.Default.get(AES.CBC) - - @OptIn(DelicateCryptographyApi::class) - fun decryptAES(inputHex: String, key: String, iv: String): String { - val keyBytes = key.encodeToByteArray() - val ivBytes = iv.encodeToByteArray() - val aesKey = aesCbc.keyDecoder().decodeFromByteArrayBlocking(AES.Key.Format.RAW, keyBytes) - val cipher = aesKey.cipher(padding = true) - val decrypted = cipher.decryptWithIvBlocking(ivBytes, inputHex.hexToByteArray()) - return decrypted.decodeToString() - } - - private fun String.hexToByteArray(): ByteArray { - check(length % 2 == 0) { "Hex string must have an even length" } - return chunked(2).map { it.toInt(16).toByte() }.toByteArray() - } -} diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/helper/AesHelper.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/helper/AesHelper.kt index 1d2b6bdf39d..c9d8b4f6eca 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/helper/AesHelper.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/helper/AesHelper.kt @@ -21,6 +21,21 @@ object AesHelper { private val md5Hasher = provider.get(MD5).hasher() @OptIn(DelicateCryptographyApi::class) + @Prerelease + suspend fun rawAesCbc( + input: ByteArray, + key: ByteArray, + iv: ByteArray, + encrypt: Boolean = true, + padding: Boolean = true, + ): ByteArray { + val aesKey = aesCbc.keyDecoder().decodeFromByteArray(AES.Key.Format.RAW, key) + val cipher = aesKey.cipher(padding = padding) + return if (!encrypt) { + cipher.decryptWithIv(iv, input) + } else cipher.encryptWithIv(iv, input) + } + suspend fun cryptoAESHandler( data: String, pass: ByteArray, @@ -35,14 +50,11 @@ object AesHelper { saltLength = parse.s.length / 2, ) ?: return null - val aesKey = aesCbc.keyDecoder().decodeFromByteArray(AES.Key.Format.RAW, key) - val cipher = aesKey.cipher(padding = padding) - return if (!encrypt) { - val plainBytes = cipher.decryptWithIv(iv, base64DecodeArray(parse.ct)) + val plainBytes = rawAesCbc(base64DecodeArray(parse.ct), key, iv, encrypt = false, padding = padding) plainBytes.decodeToString() } else { - base64Encode(cipher.encryptWithIv(iv, parse.ct.encodeToByteArray())) + base64Encode(rawAesCbc(parse.ct.encodeToByteArray(), key, iv, encrypt = true, padding = padding)) } }