Use CipherSource to decrypt responses by streaming (#10253)
This commit is contained in:
parent
e4cd4833e0
commit
f50bec002b
@ -1,7 +1,7 @@
|
||||
ext {
|
||||
extName = 'izneo (webtoons)'
|
||||
extClass = '.IzneoFactory'
|
||||
extVersionCode = 7
|
||||
extVersionCode = 8
|
||||
isNsfw = false
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,14 @@ import android.util.Base64
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.Response
|
||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||
import okhttp3.ResponseBody.Companion.asResponseBody
|
||||
import okio.buffer
|
||||
import okio.cipherSource
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
object ImageInterceptor : Interceptor {
|
||||
private val mediaType = "image/jpeg".toMediaType()
|
||||
|
||||
private inline val AES: Cipher
|
||||
get() = Cipher.getInstance("AES/CBC/PKCS7Padding")
|
||||
|
||||
@ -31,7 +31,7 @@ object ImageInterceptor : Interceptor {
|
||||
|
||||
private fun Response.decode(key: ByteArray, iv: ByteArray) = AES.let {
|
||||
it.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
|
||||
newBuilder().body(it.doFinal(body.bytes()).toResponseBody(mediaType)).build()
|
||||
newBuilder().body(body.source().cipherSource(it).buffer().asResponseBody("image/jpeg".toMediaType())).build()
|
||||
}
|
||||
|
||||
private fun String.atob() = Base64.decode(this, Base64.URL_SAFE)
|
||||
|
@ -1,7 +1,7 @@
|
||||
ext {
|
||||
extName = 'COMIC FUZ'
|
||||
extClass = '.ComicFuz'
|
||||
extVersionCode = 1
|
||||
extVersionCode = 2
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
|
@ -3,14 +3,14 @@ package eu.kanade.tachiyomi.extension.ja.comicfuz
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.Response
|
||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||
import okhttp3.ResponseBody.Companion.asResponseBody
|
||||
import okio.buffer
|
||||
import okio.cipherSource
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
object ImageInterceptor : Interceptor {
|
||||
private val mediaType = "image/jpeg".toMediaType()
|
||||
|
||||
private inline val AES: Cipher
|
||||
get() = Cipher.getInstance("AES/CBC/PKCS7Padding")
|
||||
|
||||
@ -29,7 +29,7 @@ object ImageInterceptor : Interceptor {
|
||||
).build(),
|
||||
)
|
||||
|
||||
val body = response.body.bytes()
|
||||
val body = response
|
||||
.decode(key.decodeHex(), iv.decodeHex())
|
||||
|
||||
return response.newBuilder()
|
||||
@ -37,9 +37,9 @@ object ImageInterceptor : Interceptor {
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun ByteArray.decode(key: ByteArray, iv: ByteArray) = AES.let {
|
||||
private fun Response.decode(key: ByteArray, iv: ByteArray) = AES.let {
|
||||
it.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
|
||||
it.doFinal(this).toResponseBody(mediaType)
|
||||
body.source().cipherSource(it).buffer().asResponseBody("image/jpeg".toMediaType())
|
||||
}
|
||||
|
||||
private fun String.decodeHex(): ByteArray {
|
||||
|
@ -3,7 +3,9 @@ package eu.kanade.tachiyomi.extension.pt.randomscan
|
||||
import eu.kanade.tachiyomi.lib.zipinterceptor.ZipInterceptor
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import java.io.ByteArrayInputStream
|
||||
import okio.BufferedSource
|
||||
import okio.buffer
|
||||
import okio.cipherSource
|
||||
import java.io.InputStream
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.security.MessageDigest
|
||||
@ -13,18 +15,18 @@ import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
class LuraZipInterceptor : ZipInterceptor() {
|
||||
fun decryptFile(encryptedData: ByteArray, keyBytes: ByteArray): ByteArray {
|
||||
private fun decryptFile(encryptedData: BufferedSource, keyBytes: ByteArray): BufferedSource {
|
||||
val keyHash = MessageDigest.getInstance("SHA-256").digest(keyBytes)
|
||||
|
||||
val key: SecretKey = SecretKeySpec(keyHash, "AES")
|
||||
|
||||
val counter = encryptedData.copyOfRange(0, 8)
|
||||
val counter = encryptedData.readByteArray(8)
|
||||
val iv = IvParameterSpec(counter)
|
||||
|
||||
val cipher = Cipher.getInstance("AES/CTR/NoPadding")
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, iv)
|
||||
|
||||
val decryptedData = cipher.doFinal(encryptedData.copyOfRange(8, encryptedData.size))
|
||||
val decryptedData = encryptedData.cipherSource(cipher).buffer()
|
||||
|
||||
return decryptedData
|
||||
}
|
||||
@ -35,11 +37,11 @@ class LuraZipInterceptor : ZipInterceptor() {
|
||||
|
||||
override fun zipGetByteStream(request: Request, response: Response): InputStream {
|
||||
val keyData = listOf("obra_id", "slug", "cap_id", "cap_slug").joinToString("") {
|
||||
request.url.queryParameterValues(it).first().toString()
|
||||
request.url.queryParameter(it)!!
|
||||
}.toByteArray(StandardCharsets.UTF_8)
|
||||
val encryptedData = response.body.bytes()
|
||||
val encryptedData = response.body.source()
|
||||
|
||||
val decryptedData = decryptFile(encryptedData, keyData)
|
||||
return ByteArrayInputStream(decryptedData)
|
||||
return decryptedData.inputStream()
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
ext {
|
||||
extName = 'Manwa'
|
||||
extClass = '.Manwa'
|
||||
extVersionCode = 12
|
||||
extVersionCode = 13
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,9 @@ import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||
import okhttp3.ResponseBody.Companion.asResponseBody
|
||||
import okio.buffer
|
||||
import okio.cipherSource
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
@ -57,13 +59,12 @@ class Manwa : ParsedHttpSource(), ConfigurableSource {
|
||||
val originalResponse: Response = chain.proceed(chain.request())
|
||||
if (originalResponse.request.url.toString().endsWith("?v=20220724")) {
|
||||
// Decrypt images in mangas
|
||||
val orgBody = originalResponse.body.bytes()
|
||||
val key = "my2ecret782ecret".toByteArray()
|
||||
val aesKey = SecretKeySpec(key, "AES")
|
||||
val cipher = Cipher.getInstance("AES/CBC/NOPADDING")
|
||||
cipher.init(Cipher.DECRYPT_MODE, aesKey, IvParameterSpec(key))
|
||||
val result = cipher.doFinal(orgBody)
|
||||
val newBody = result.toResponseBody("image/webp".toMediaTypeOrNull())
|
||||
val result = originalResponse.body.source().cipherSource(cipher).buffer()
|
||||
val newBody = result.asResponseBody("image/webp".toMediaTypeOrNull())
|
||||
originalResponse.newBuilder()
|
||||
.body(newBody)
|
||||
.build()
|
||||
|
@ -1,7 +1,7 @@
|
||||
ext {
|
||||
extName = 'COLAMANGA'
|
||||
extClass = '.Onemanhua'
|
||||
extVersionCode = 25
|
||||
extVersionCode = 26
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
|
@ -3,15 +3,14 @@ package eu.kanade.tachiyomi.extension.zh.onemanhua
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.Response
|
||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||
import okhttp3.ResponseBody.Companion.asResponseBody
|
||||
import okio.buffer
|
||||
import okio.cipherSource
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
class ColaMangaImageInterceptor : Interceptor {
|
||||
private val iv = "0000000000000000".toByteArray()
|
||||
private val mediaType = "image/jpeg".toMediaType()
|
||||
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val request = chain.request()
|
||||
val response = chain.proceed(request)
|
||||
@ -22,12 +21,13 @@ class ColaMangaImageInterceptor : Interceptor {
|
||||
|
||||
val key = request.url.fragment!!.substringAfter(KEY_PREFIX).toByteArray()
|
||||
val output = Cipher.getInstance("AES/CBC/PKCS7Padding").let {
|
||||
val iv = "0000000000000000".toByteArray()
|
||||
it.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
|
||||
it.doFinal(response.body.bytes())
|
||||
response.body.source().cipherSource(it).buffer()
|
||||
}
|
||||
|
||||
return response.newBuilder()
|
||||
.body(output.toResponseBody(mediaType))
|
||||
.body(output.asResponseBody("image/jpeg".toMediaType()))
|
||||
.build()
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user