diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 75a9698c8c4..f00d14cfaf2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -275,6 +275,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 // Deprecated; will be removed once extensions have time to migrate from using it implementation("me.xdrop:fuzzywuzzy:1.4.0") diff --git a/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt b/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt index 7fec6763793..c1bb96e590f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/plugins/RepositoryManager.kt @@ -16,6 +16,8 @@ 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.serialization.SerialName @@ -24,7 +26,6 @@ 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 /** @@ -103,22 +104,31 @@ 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() + // Use kotlinx-io eventually + /* + return hashFunction.use { + it.update(file.asSource()) + "sha256-" + it.hashToByteArray().joinToString("") { b -> "%02x".format(b) } + } + */ + hashFunction.use { + file.inputStream().use { fis -> + val buffer = ByteArray(8192) + var read = fis.read(buffer) + while (read != -1) { + it.update(buffer, 0, read) + read = fis.read(buffer) + } } + + return "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 */ diff --git a/app/src/main/java/com/lagradost/cloudstream3/plugins/VotingApi.kt b/app/src/main/java/com/lagradost/cloudstream3/plugins/VotingApi.kt index 57f6f475087..ba301f7b5db 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/plugins/VotingApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/plugins/VotingApi.kt @@ -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 @@ -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) @@ -52,7 +52,7 @@ object VotingApi { votesCache[pluginUrl] = it } - fun hasVoted(pluginUrl: String): Boolean = + suspend fun hasVoted(pluginUrl: String): Boolean = getKey("cs3-votes/${transformUrl(pluginUrl)}") ?: false fun canVote(pluginUrl: String): Boolean = diff --git a/app/src/main/java/com/lagradost/cloudstream3/syncproviders/AuthAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/syncproviders/AuthAPI.kt index 60e41e8b3d5..9646c398765 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/syncproviders/AuthAPI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/syncproviders/AuthAPI.kt @@ -8,12 +8,12 @@ import com.lagradost.cloudstream3.APIHolder.unixTimeMS import com.lagradost.cloudstream3.base64Encode import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.APP_STRING import com.lagradost.cloudstream3.utils.AppContextUtils.splitQuery +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.net.URI -import java.security.SecureRandom data class AuthLoginPage( /** The website to open to authenticate */ @@ -182,9 +182,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", "") } diff --git a/app/src/main/java/com/lagradost/cloudstream3/syncproviders/providers/SimklApi.kt b/app/src/main/java/com/lagradost/cloudstream3/syncproviders/providers/SimklApi.kt index a57ec67164e..edeb790d1f2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/syncproviders/providers/SimklApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/syncproviders/providers/SimklApi.kt @@ -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 @@ -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, diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt index d7e10c81441..ff652441cfa 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt @@ -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 @@ -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) sslContext.createSSLEngine() HttpsURLConnection.setDefaultHostnameVerifier { _: String, _: SSLSession -> true diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginDetailsFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginDetailsFragment.kt index 06a95d527d7..5ce6bae8be3 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginDetailsFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginDetailsFragment.kt @@ -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() @@ -149,4 +149,4 @@ class PluginDetailsFragment(val data: PluginViewData) : BaseBottomSheetDialogFra } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/videoskip/AnimeSkip.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/videoskip/AnimeSkip.kt index df9d56217fd..d55a430b218 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/videoskip/AnimeSkip.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/videoskip/AnimeSkip.kt @@ -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" @@ -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