Skip to content

Commit

Permalink
fix(en/aniwave): Fix VRF encrypt/decrypt (#2504)
Browse files Browse the repository at this point in the history
  • Loading branch information
samfundev authored Nov 12, 2023
1 parent c5a1747 commit e2df506
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/en/aniwave/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ext {
extName = 'Aniwave'
pkgNameSuffix = 'en.nineanime'
extClass = '.Aniwave'
extVersionCode = 57
extVersionCode = 58
libVersion = '13'
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.animeextension.en.nineanime

import android.util.Base64
import eu.kanade.tachiyomi.AppInfo
import eu.kanade.tachiyomi.animeextension.BuildConfig
import eu.kanade.tachiyomi.network.GET
Expand All @@ -10,6 +11,9 @@ import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.Response
import uy.kohesive.injekt.injectLazy
import java.net.URLDecoder
import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec

class AniwaveUtils(private val client: OkHttpClient, private val headers: Headers) {

Expand Down Expand Up @@ -37,27 +41,62 @@ class AniwaveUtils(private val client: OkHttpClient, private val headers: Header
headers = userAgent,
),
).execute().parseAs<RawResponse>().rawURL
} else if (action == "decrypt") {
vrfDecrypt(query)
} else {
client.newCall(
GET("https://9anime.eltik.net/$action?query=$query&apikey=aniyomi", userAgent),
).execute().use {
val body = it.body.string()
when (action) {
"decrypt" -> {
json.decodeFromString<VrfResponse>(body).url
}
else -> {
json.decodeFromString<VrfResponse>(body).let { vrf ->
"${vrf.vrfQuery}=${java.net.URLEncoder.encode(vrf.url, "utf-8")}"
}
}
}
}
"vrf=${java.net.URLEncoder.encode(vrfEncrypt(query), "utf-8")}"
}
}

private inline fun <reified T> Response.parseAs(): T {
val responseBody = use { it.body.string() }
return json.decodeFromString(responseBody)
}

private fun vrfEncrypt(input: String): String {
val rc4Key = SecretKeySpec("ysJhV6U27FVIjjuk".toByteArray(), "RC4")
val cipher = Cipher.getInstance("RC4")
cipher.init(Cipher.DECRYPT_MODE, rc4Key, cipher.parameters)

var vrf = cipher.doFinal(input.toByteArray())
vrf = Base64.encode(vrf, Base64.URL_SAFE or Base64.NO_WRAP)
vrf = Base64.encode(vrf, Base64.DEFAULT or Base64.NO_WRAP)
vrf = vrfShift(vrf)
vrf = Base64.encode(vrf, Base64.DEFAULT)
vrf = rot13(vrf)

return vrf.toString(Charsets.UTF_8)
}

private fun vrfDecrypt(input: String): String {
var vrf = input.toByteArray()
vrf = Base64.decode(vrf, Base64.URL_SAFE)

val rc4Key = SecretKeySpec("hlPeNwkncH0fq9so".toByteArray(), "RC4")
val cipher = Cipher.getInstance("RC4")
cipher.init(Cipher.DECRYPT_MODE, rc4Key, cipher.parameters)
vrf = cipher.doFinal(vrf)

return URLDecoder.decode(vrf.toString(Charsets.UTF_8), "utf-8")
}

private fun rot13(vrf: ByteArray): ByteArray {
for (i in vrf.indices) {
val byte = vrf[i]
if (byte in 'A'.code..'Z'.code) {
vrf[i] = ((byte - 'A'.code + 13) % 26 + 'A'.code).toByte()
} else if (byte in 'a'.code..'z'.code) {
vrf[i] = ((byte - 'a'.code + 13) % 26 + 'a'.code).toByte()
}
}
return vrf
}

private fun vrfShift(vrf: ByteArray): ByteArray {
for (i in vrf.indices) {
val shift = arrayOf(-3, 3, -4, 2, -2, 5, 4, 5)[i % 8]
vrf[i] = vrf[i].plus(shift).toByte()
}
return vrf
}
}

0 comments on commit e2df506

Please sign in to comment.