import decrypt.ArchiveDecrypt
import decrypt.Encrypt
import decrypt.FileArchiveDecrypt
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import progress.Progress
import progress.ProgressFileHandler
import java.io.File
import java.util.logging.Logger
import javax.swing.JOptionPane
import kotlin.time.measureTime

object BruteForce {
    private val archiveDecrypt: ArchiveDecrypt = FileArchiveDecrypt
    private val progress: ProgressFileHandler = Progress
    private val passwordFoundFlow = MutableSharedFlow<String>()
    private var passwordFound: String? = null

    /**
     * Tenta descriptografar o arquivo fornecido utilizando a técnica de força bruta.
     *
     * @param file o arquivo a ser descriptografado
     * @return a senha utilizada para descriptografar o arquivo
     * @throws IllegalArgumentException se o arquivo não for criptografado
     */
    suspend fun force(file: File): String {
        if (!Encrypt().isEncrypted(file)) {
            throw IllegalArgumentException("Arquivo não criptografado!")
        }
        progress.loadProgress(file.name)

        val duration = measureTime {
            val consumers = List(Runtime.getRuntime().availableProcessors()) {
                CoroutineScope(Dispatchers.IO).launch { tryPasswords(file) }
            }
            passwordFound = passwordFoundFlow.first()
            consumers.forEach { it.cancel() }
        }
        val passwordsGenerated = progress.passwordIterator.totalPasswordsGenerated.toInt()

        JOptionPane.showMessageDialog(
            null,
            "\n--Senha encontrada--\n$passwordFound\nTempo de execução: $duration\nSenhas testadas: " +
                    "$passwordsGenerated\nSenhas por segundo: ${
                        if (duration.inWholeSeconds > 0) {
                            passwordsGenerated / duration.inWholeSeconds
                        } else {
                            passwordsGenerated / duration.inWholeMilliseconds
                        }
                    }",
            "Senha encontrada!",
            JOptionPane.INFORMATION_MESSAGE
        )
        Logger.getLogger(this.javaClass.name).info(
            "\n--Senha encontrada--\n$passwordFound\nTempo de execução: $duration\nSenhas testadas: " +
                    "$passwordsGenerated\nSenhas por segundo: ${
                        if (duration.inWholeSeconds > 0) {
                            passwordsGenerated / duration.inWholeSeconds
                        } else {
                            passwordsGenerated / duration.inWholeMilliseconds
                        }
                    }"
        )

        return passwordFound!!.also {
            passwordFound = null
            progress.passwordIterator.reset()
        }
    }

    private suspend fun tryPasswords(archiveFile: File) {
        while (passwordFound == null) {
            if (progress.passwordIterator.totalPasswordsGenerated.toInt() % 5000 == 0) {
                progress.saveProgress(archiveFile.name)
            }
            val result = archiveDecrypt.tryPassword(archiveFile, progress.passwordIterator.getNextPassword())
            if (result != null) {
                passwordFound = result
                passwordFoundFlow.emit(result)
                break
            }
        }
    }
}
package decrypt

import com.github.junrar.Archive
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import net.lingala.zip4j.ZipFile
import org.apache.commons.compress.archivers.sevenz.SevenZFile
import java.io.File
import java.io.IOException

/**
 * Implementation of [ArchiveDecrypt] that uses the 7-zip library to decrypt 7z files, and the Apache Commons Compress
 * library to decrypt zip files.
 */
object FileArchiveDecrypt : ArchiveDecrypt {
    override suspend fun tryPassword(archiveFile: File, password: String): String? {
        return withContext(Dispatchers.IO) {
            try {
                when (archiveFile.extension) {
                    "7z" -> SevenZFile.builder().setFile(archiveFile).setPassword(password.toCharArray()).get()
                        .use { sevenZFile ->
                            sevenZFile.entries.forEach { sevenEntry ->
                                sevenZFile.getInputStream(sevenEntry).readBytes()
                            }
                        }

                    "zip" -> ZipFile(archiveFile, password.toCharArray()).use { zipFile ->
                        zipFile.fileHeaders.forEach { fileHeader ->
                            zipFile.getInputStream(fileHeader).readBytes()
                        }
                    }

                    "rar" -> Archive(archiveFile, password).use { archive ->
                        archive.fileHeaders.forEach { fileHeader ->
                            archive.getInputStream(fileHeader).readBytes()
                        }
                    }

                    else -> throw IllegalArgumentException(
                        "Extensão de arquivo não suportado!\n${archiveFile.extension}"
                    )
                }
                password
            } catch (_: IOException) {
                null
            }
        }
    }
}

como eu posso melhorar o desempenho desse código?