From d08206212ddcce58f676189a2b4aec1286b1d2b7 Mon Sep 17 00:00:00 2001 From: student-d-sherstnev Date: Wed, 25 Feb 2026 13:55:03 +0300 Subject: [PATCH] AES encryption --- .../ru/myitschool/work/data/AESEncryption.kt | 58 +++++++++++++++++++ .../work/data/repo/AuthRepository.kt | 17 ++++-- .../work/data/source/NetworkDataSource.kt | 16 ++++- 3 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/ru/myitschool/work/data/AESEncryption.kt diff --git a/app/src/main/java/ru/myitschool/work/data/AESEncryption.kt b/app/src/main/java/ru/myitschool/work/data/AESEncryption.kt new file mode 100644 index 0000000..00e2a8b --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/data/AESEncryption.kt @@ -0,0 +1,58 @@ +package ru.myitschool.work.data + +import android.util.Base64 +import javax.crypto.Cipher +import javax.crypto.SecretKeyFactory +import javax.crypto.spec.IvParameterSpec +import javax.crypto.spec.PBEKeySpec +import javax.crypto.spec.SecretKeySpec + + +object AESEncyption { + + const val secretKey = "tK5Ugskdkipokuodvknfdk3434weofnf=" + const val salt = "QLlGNHNhYTJTQWZ2bGhpV3U=" + const val iv = "bVQqNFNhRkQ1Njc4UUFaPA==" + + fun encrypt(strToEncrypt: String): String? { + try { + val ivParameterSpec = IvParameterSpec(Base64.decode(iv, Base64.DEFAULT)) + + val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") + val spec = + PBEKeySpec(secretKey.toCharArray(), Base64.decode(salt, Base64.DEFAULT), 10000, 256) + val tmp = factory.generateSecret(spec) + val secretKey = SecretKeySpec(tmp.encoded, "AES") + + val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding") + cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec) + return Base64.encodeToString( + cipher.doFinal(strToEncrypt.toByteArray(Charsets.UTF_8)), + Base64.DEFAULT + ) + } catch (e: Exception) { + println("Error while encrypting: $e") + } + return null + } + + fun decrypt(strToDecrypt: String?): String? { + try { + + val ivParameterSpec = IvParameterSpec(Base64.decode(iv, Base64.DEFAULT)) + + val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1") + val spec = + PBEKeySpec(secretKey.toCharArray(), Base64.decode(salt, Base64.DEFAULT), 10000, 256) + val tmp = factory.generateSecret(spec) + val secretKey = SecretKeySpec(tmp.encoded, "AES") + + val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding") + cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec) + return String(cipher.doFinal(Base64.decode(strToDecrypt, Base64.DEFAULT))) + } catch (e: Exception) { + println("Error while decrypting: $e") + } + return null + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/data/repo/AuthRepository.kt b/app/src/main/java/ru/myitschool/work/data/repo/AuthRepository.kt index f6240b2..8dffc44 100644 --- a/app/src/main/java/ru/myitschool/work/data/repo/AuthRepository.kt +++ b/app/src/main/java/ru/myitschool/work/data/repo/AuthRepository.kt @@ -8,6 +8,7 @@ import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore import kotlinx.coroutines.flow.firstOrNull import ru.myitschool.work.App +import ru.myitschool.work.data.AESEncyption import ru.myitschool.work.data.dto.AuthRequestDto import ru.myitschool.work.data.dto.AuthResponseDto import ru.myitschool.work.data.source.NetworkDataSource @@ -21,10 +22,13 @@ object AuthRepository { suspend fun checkAndSave(login: String, password: String): Result { val data = AuthRequestDto(login=login, password=password) return NetworkDataSource.checkAuth(data).onSuccess { success -> - tokenCache = success.token - App.context.userDataStore.edit { preferences -> - val prefKey = stringPreferencesKey(TOKEN_KEY) - preferences[prefKey] = success.token + val encryptedTokenCache = AESEncyption.encrypt(success.token) + tokenCache = encryptedTokenCache + if (encryptedTokenCache != null) { + App.context.userDataStore.edit { preferences -> + val prefKey = stringPreferencesKey(TOKEN_KEY) + preferences[prefKey] = encryptedTokenCache + } } } } @@ -37,7 +41,10 @@ object AuthRepository { preferences[stringPreferencesKey(TOKEN_KEY)] } } - return tokenCache + if (tokenCache != null) { + return AESEncyption.decrypt(tokenCache) + } + return null } suspend fun logout() { diff --git a/app/src/main/java/ru/myitschool/work/data/source/NetworkDataSource.kt b/app/src/main/java/ru/myitschool/work/data/source/NetworkDataSource.kt index 1405880..dee42cb 100644 --- a/app/src/main/java/ru/myitschool/work/data/source/NetworkDataSource.kt +++ b/app/src/main/java/ru/myitschool/work/data/source/NetworkDataSource.kt @@ -22,6 +22,7 @@ import ru.myitschool.work.data.dto.AuthResponseDto import ru.myitschool.work.data.dto.PlaceDto import ru.myitschool.work.data.dto.BookRequestDto import ru.myitschool.work.data.dto.UserDto +import ru.myitschool.work.data.repo.AuthRepository object NetworkDataSource { private val client by lazy { @@ -41,7 +42,7 @@ object NetworkDataSource { suspend fun checkAuth(data: AuthRequestDto): Result = withContext(Dispatchers.IO) { return@withContext runCatching { - val response = client.post(getUrl(Constants.BOOK_URL)) { + val response = client.post(getUrl(Constants.AUTH_URL)) { contentType(ContentType.Application.Json) setBody(data) } @@ -64,6 +65,9 @@ object NetworkDataSource { println("!!!!!!!!!!!!!! getInfo OK ${response.bodyAsText()}") response.body() } else { + if (response.status == HttpStatusCode.Unauthorized) { + AuthRepository.logout() + } println("!!!!!!!!!!!!!! getInfo ERROR ${response.bodyAsText()}") error(response.bodyAsText()) } @@ -80,6 +84,9 @@ object NetworkDataSource { if (response.status == HttpStatusCode.OK) { response.body>>() } else { + if (response.status == HttpStatusCode.Unauthorized) { + AuthRepository.logout() + } error(response.bodyAsText()) } } @@ -97,7 +104,12 @@ object NetworkDataSource { when (response.status) { HttpStatusCode.Created -> true HttpStatusCode.Conflict -> false - else -> error(response.bodyAsText()) + else -> { + if (response.status == HttpStatusCode.Unauthorized) { + AuthRepository.logout() + } + error(response.bodyAsText()) + } } } }