Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ dependencies {
implementation(libs.bundles.lifecycle)
implementation(libs.bundles.navigation)
implementation(libs.kotlinx.collections.immutable)
implementation(libs.kotlinx.io.core)
implementation(libs.kotlinx.serialization.json) // JSON Parser

// Design & UI
Expand Down Expand Up @@ -275,6 +276,7 @@ dependencies {
implementation(libs.conscrypt.android) // To Fix SSL Fu*kery on Android 9
implementation(libs.jackson.module.kotlin) // JSON Parser
implementation(libs.zipline)
implementation(libs.bundles.cryptography) // Cryptography

// Temp/deprecated; will be removed once extensions have time to migrate from using it
implementation("com.google.code.gson:gson:2.11.0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ import com.lagradost.cloudstream3.plugins.PluginManager.getPluginSanitizedFileNa
import com.lagradost.cloudstream3.plugins.PluginManager.unloadPlugin
import com.lagradost.cloudstream3.ui.settings.extensions.REPOSITORIES_KEY
import com.lagradost.cloudstream3.ui.settings.extensions.RepositoryData
import dev.whyoleg.cryptography.CryptographyProvider
import dev.whyoleg.cryptography.algorithms.SHA256
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.io.asSource
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.io.File
import java.nio.file.AtomicMoveNotSupportedException
import java.nio.file.Files
import java.nio.file.StandardCopyOption
import java.security.MessageDigest
import java.util.concurrent.TimeUnit

/**
Expand Down Expand Up @@ -103,22 +105,16 @@ object RepositoryManager {
private val GH_REGEX =
Regex("^https://raw.githubusercontent.com/([A-Za-z0-9-]+)/([A-Za-z0-9_.-]+)/(.*)$")


/** Returns a SHA-256 string of the file content.
* Example: "sha256-b70462c264cb7f90fc2860a8e58d7544ce747ff347d1d11fa093623901853573" **/
@WorkerThread
fun sha256(file: File): String {
val digest = MessageDigest.getInstance("SHA-256")

file.inputStream().use { fis ->
val buffer = ByteArray(8192)
var read = fis.read(buffer)
while (read != -1) {
digest.update(buffer, 0, read)
read = fis.read(buffer)
}
val hashFunction = CryptographyProvider.Default.get(SHA256)
.hasher().createHashFunction()
return hashFunction.use {
it.update(file.inputStream().asSource())
"sha256-" + it.hashToByteArray().joinToString("") { b -> "%02x".format(b) }
}
return "sha256-" + digest.digest().joinToString("") { "%02x".format(it) }
}

/* Convert raw.githubusercontent.com urls to cdn.jsdelivr.net if enabled in settings */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import com.lagradost.cloudstream3.CloudStreamApp.Companion.context
import com.lagradost.cloudstream3.CloudStreamApp.Companion.getKey
import com.lagradost.cloudstream3.CloudStreamApp.Companion.setKey
import com.lagradost.cloudstream3.R
import java.security.MessageDigest
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.utils.Coroutines.main
import dev.whyoleg.cryptography.CryptographyProvider
import dev.whyoleg.cryptography.algorithms.SHA256
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.serialization.SerialName
Expand All @@ -19,14 +20,13 @@ object VotingApi {
private const val LOGKEY = "VotingApi"
private const val API_DOMAIN = "https://api.countify.xyz"

private fun transformUrl(url: String): String =
MessageDigest
.getInstance("SHA-256")
.digest("${url}#funny-salt".toByteArray())
private suspend fun transformUrl(url: String): String =
CryptographyProvider.Default.get(SHA256)
.hasher().hash("$url#funny-salt".encodeToByteArray())
.fold("") { str, it -> str + "%02x".format(it) }

suspend fun SitePlugin.getVotes(): Int = getVotes(url)
fun SitePlugin.hasVoted(): Boolean = hasVoted(url)
suspend fun SitePlugin.hasVoted(): Boolean = hasVoted(url)
suspend fun SitePlugin.vote(): Int = vote(url)
fun SitePlugin.canVote(): Boolean = canVote(this.url)

Expand All @@ -52,7 +52,7 @@ object VotingApi {
votesCache[pluginUrl] = it
}

fun hasVoted(pluginUrl: String): Boolean =
suspend fun hasVoted(pluginUrl: String): Boolean =
getKey<Boolean>("cs3-votes/${transformUrl(pluginUrl)}") ?: false

fun canVote(pluginUrl: String): Boolean =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import com.lagradost.cloudstream3.APIHolder.unixTimeMS
import com.lagradost.cloudstream3.base64Encode
import com.lagradost.cloudstream3.splitUrlParameters
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.APP_STRING
import dev.whyoleg.cryptography.random.CryptographyRandom
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonNames
import java.security.SecureRandom

data class AuthLoginPage(
/** The website to open to authenticate */
Expand Down Expand Up @@ -179,9 +179,7 @@ abstract class AuthAPI {
fun generateCodeVerifier(): String {
// It is recommended to use a URL-safe string as code_verifier.
// See section 4 of RFC 7636 for more details.
val secureRandom = SecureRandom()
val codeVerifierBytes = ByteArray(96) // base64 has 6bit per char; (8/6)*96 = 128
secureRandom.nextBytes(codeVerifierBytes)
val codeVerifierBytes = CryptographyRandom.nextBytes(96) // base64 has 6bit per char; (8/6)*96 = 128
return base64Encode(codeVerifierBytes).trimEnd('=')
.replace("+", "-").replace("/", "_").replace("\n", "")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.DataStoreHelper.toYear
import com.lagradost.cloudstream3.utils.serializers.NonEmptySerializer
import com.lagradost.cloudstream3.utils.txt
import dev.whyoleg.cryptography.random.CryptographyRandom
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KeepGeneratedSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.math.BigInteger
import java.security.SecureRandom
import java.text.SimpleDateFormat
import java.time.Instant
import java.util.Date
Expand Down Expand Up @@ -987,7 +987,7 @@ class SimklApi : SyncAPI() {
}

override fun loginRequest(): AuthLoginPage? {
val lastLoginState = BigInteger(130, SecureRandom()).toString(32)
val lastLoginState = BigInteger(130, CryptographyRandom.nextBytes(17)).toString(32)
val url = "https://simkl.com/oauth/authorize?response_type=code&client_id=$CLIENT_ID&redirect_uri=$APP_STRING://$redirectUrlIdentifier&state=$lastLoginState"
return AuthLoginPage(
url = url,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ import kotlinx.coroutines.delay
import okhttp3.Interceptor
import org.chromium.net.CronetEngine
import java.io.File
import java.security.SecureRandom
import java.util.UUID
import java.util.concurrent.Executors
import javax.net.ssl.HttpsURLConnection
Expand Down Expand Up @@ -1893,7 +1892,7 @@ class CS3IPlayer : IPlayer {
if (ignoreSSL) {
// Disables ssl check
val sslContext: SSLContext = SSLContext.getInstance("TLS")
sslContext.init(null, arrayOf(SSLTrustManager()), SecureRandom())
sslContext.init(null, arrayOf(SSLTrustManager()), null)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this was just removed because it has the same behavior as far as I could tell, null just uses a default SecureRandom and we don't need to pass it so I thought we should just let it handle it there to remove all usage of SecureRandom. But it can be changed if really wanted.

sslContext.createSSLEngine()
HttpsURLConnection.setDefaultHostnameVerifier { _: String, _: SSLSession ->
true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ class PluginDetailsFragment(val data: PluginViewData) : BaseBottomSheetDialogFra
}
}

private fun updateVoting(value: Int) {
private suspend fun updateVoting(value: Int) {
val metadata = data.pluginWrapper.plugin
binding?.apply {
pluginVotes.text = value.toString()
Expand All @@ -149,4 +149,4 @@ class PluginDetailsFragment(val data: PluginViewData) : BaseBottomSheetDialogFra
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ import com.lagradost.cloudstream3.syncproviders.PlainAuthRepo
import com.lagradost.cloudstream3.ui.result.ResultEpisode
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.AppUtils.toJson
import dev.whyoleg.cryptography.CryptographyProvider
import dev.whyoleg.cryptography.DelicateCryptographyApi
import dev.whyoleg.cryptography.algorithms.MD5
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.math.BigInteger
import java.util.concurrent.ConcurrentHashMap
import java.security.MessageDigest

class AnimeSkipAuth : AuthAPI() {
override val name = "AnimeSkip"
Expand All @@ -31,9 +33,12 @@ class AnimeSkipAuth : AuthAPI() {
override val hasInApp = true
override val createAccountUrl = "https://anime-skip.com/account"
val baseClientId = "as1JgiMbW4wKfmTLWXS79iTDQFll76pk"
fun md5(input: String): String {
val md = MessageDigest.getInstance("MD5")
return BigInteger(1, md.digest(input.toByteArray())).toString(16).padStart(32, '0')

suspend fun md5(input: String): String {
@OptIn(DelicateCryptographyApi::class)
val digest = CryptographyProvider.Default.get(MD5)
.hasher().hash(input.encodeToByteArray())
return BigInteger(1, digest).toString(16).padStart(32, '0')
}

@Serializable
Expand Down