diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000..1c36519f5e --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1 @@ +/dictionaries/ivan.xml diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/activity/ImportPrivateKeyActivityFromSettingsTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/activity/ImportPrivateKeyActivityFromSettingsTest.kt index 4d201d5b7b..9322120038 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/activity/ImportPrivateKeyActivityFromSettingsTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/activity/ImportPrivateKeyActivityFromSettingsTest.kt @@ -80,7 +80,6 @@ class ImportPrivateKeyActivityFromSettingsTest : BaseTest() { .around(ScreenshotTestRule()) @Test - @ReadyForCIAnnotation fun testImportKeyFromBackup() { useIntentionFromRunCheckKeysActivity() diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/gmail/GmailApiHelper.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/gmail/GmailApiHelper.kt index 7cfbd37274..27de60c861 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/gmail/GmailApiHelper.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/gmail/GmailApiHelper.kt @@ -1,6 +1,8 @@ /* * © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com - * Contributors: DenBond7 + * Contributors: + * DenBond7 + * Ivan Pizhenko */ package com.flowcrypt.email.api.email.gmail @@ -16,7 +18,6 @@ import com.flowcrypt.email.api.email.gmail.api.GMailRawAttachmentFilterInputStre import com.flowcrypt.email.api.email.gmail.api.GMailRawMIMEMessageFilterInputStream import com.flowcrypt.email.api.email.model.AttachmentInfo import com.flowcrypt.email.api.email.model.LocalFolder -import com.flowcrypt.email.api.retrofit.node.NodeCallsExecutor import com.flowcrypt.email.api.retrofit.response.base.Result import com.flowcrypt.email.api.retrofit.response.model.node.NodeKeyDetails import com.flowcrypt.email.database.FlowCryptRoomDatabase @@ -27,6 +28,7 @@ import com.flowcrypt.email.extensions.contentId import com.flowcrypt.email.extensions.disposition import com.flowcrypt.email.extensions.isMimeType import com.flowcrypt.email.extensions.uid +import com.flowcrypt.email.security.pgp.PgpKey import com.flowcrypt.email.ui.notifications.ErrorNotificationManager import com.flowcrypt.email.util.exception.CommonConnectionException import com.flowcrypt.email.util.exception.ExceptionUtil @@ -668,7 +670,7 @@ class GmailApiHelper { } try { - list.addAll(NodeCallsExecutor.parseKeys(backup)) + list.addAll(PgpKey.parseKeysC(backup.toByteArray())) } catch (e: NodeException) { e.printStackTrace() ExceptionUtil.handleError(e) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/model/node/NodeKeyDetails.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/model/node/NodeKeyDetails.kt index 3a731143b0..1733f4593b 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/model/node/NodeKeyDetails.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/retrofit/response/model/node/NodeKeyDetails.kt @@ -1,6 +1,8 @@ /* * © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com - * Contributors: DenBond7 + * Contributors: + * DenBond7 + * Ivan Pizhenko */ package com.flowcrypt.email.api.retrofit.response.model.node diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/pgp/PGPKeyRingExt.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/pgp/PGPKeyRingExt.kt index 505b007957..d4e702e0d2 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/pgp/PGPKeyRingExt.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/extensions/pgp/PGPKeyRingExt.kt @@ -11,11 +11,6 @@ import com.flowcrypt.email.api.retrofit.response.model.node.Algo import com.flowcrypt.email.api.retrofit.response.model.node.KeyId import com.flowcrypt.email.api.retrofit.response.model.node.NodeKeyDetails import com.flowcrypt.email.security.pgp.PgpArmor -import java.io.ByteArrayOutputStream -import java.io.IOException -import java.nio.charset.StandardCharsets -import java.time.Instant -import java.util.concurrent.TimeUnit import org.bouncycastle.bcpg.ArmoredOutputStream import org.bouncycastle.openpgp.PGPKeyRing import org.bouncycastle.openpgp.PGPSecretKeyRing @@ -24,6 +19,11 @@ import org.pgpainless.key.OpenPgpV4Fingerprint import org.pgpainless.key.generation.type.eddsa.EdDSACurve import org.pgpainless.key.info.KeyInfo import org.pgpainless.key.info.KeyRingInfo +import java.io.ByteArrayOutputStream +import java.io.IOException +import java.nio.charset.StandardCharsets +import java.time.Instant +import java.util.concurrent.TimeUnit /** * @author Denis Bondarenko @@ -56,11 +56,11 @@ fun PGPKeyRing.toNodeKeyDetails(): NodeKeyDetails { ) } - val privateKey = if (keyRingInfo.isSecretKey) this.armor(PgpArmor.FLOWCRYPT_HEADERS) else null + val privateKey = if (keyRingInfo.isSecretKey) armor() else null val publicKey = if (keyRingInfo.isSecretKey) { - (this as PGPSecretKeyRing).toPublicKeyRing().armor(PgpArmor.FLOWCRYPT_HEADERS) + (this as PGPSecretKeyRing).toPublicKeyRing().armor() } else { - this.armor(PgpArmor.FLOWCRYPT_HEADERS) + armor() } return NodeKeyDetails( @@ -80,7 +80,7 @@ fun PGPKeyRing.toNodeKeyDetails(): NodeKeyDetails { } @Throws(IOException::class) -fun PGPKeyRing.armor(headers: List>? = null): String { +fun PGPKeyRing.armor(headers: List>? = PgpArmor.FLOWCRYPT_HEADERS): String { ByteArrayOutputStream().use { out -> ArmoredOutputStream(out).use { armoredOut -> if (headers != null) { diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/LoadPrivateKeysViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/LoadPrivateKeysViewModel.kt index 5733b57646..3172283443 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/LoadPrivateKeysViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/LoadPrivateKeysViewModel.kt @@ -1,6 +1,8 @@ /* * © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com - * Contributors: DenBond7 + * Contributors: + * DenBond7 + * Ivan Pizhenko */ package com.flowcrypt.email.jetpack.viewmodel @@ -15,10 +17,10 @@ import com.flowcrypt.email.api.email.EmailUtil import com.flowcrypt.email.api.email.SearchBackupsUtil import com.flowcrypt.email.api.email.gmail.GmailApiHelper import com.flowcrypt.email.api.email.protocol.OpenStoreHelper -import com.flowcrypt.email.api.retrofit.node.NodeCallsExecutor import com.flowcrypt.email.api.retrofit.response.base.Result import com.flowcrypt.email.api.retrofit.response.model.node.NodeKeyDetails import com.flowcrypt.email.database.entity.AccountEntity +import com.flowcrypt.email.security.pgp.PgpKey import com.flowcrypt.email.util.exception.ExceptionUtil import com.flowcrypt.email.util.exception.NodeException import com.google.android.gms.auth.GoogleAuthException @@ -111,7 +113,7 @@ class LoadPrivateKeysViewModel(application: Application) : BaseAndroidViewModel( } try { - details.addAll(NodeCallsExecutor.parseKeys(backup)) + details.addAll(PgpKey.parseKeysC(backup.toByteArray())) } catch (e: NodeException) { e.printStackTrace() ExceptionUtil.handleError(e) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt index fc1bbf0c6e..8b0329d8ad 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/PrivateKeysViewModel.kt @@ -1,6 +1,8 @@ /* * © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com - * Contributors: DenBond7 + * Contributors: + * DenBond7 + * Ivan Pizhenko */ package com.flowcrypt.email.jetpack.viewmodel @@ -22,7 +24,6 @@ import com.flowcrypt.email.api.email.protocol.OpenStoreHelper import com.flowcrypt.email.api.email.protocol.SmtpProtocolUtil import com.flowcrypt.email.api.retrofit.ApiRepository import com.flowcrypt.email.api.retrofit.FlowcryptApiRepository -import com.flowcrypt.email.api.retrofit.node.NodeCallsExecutor import com.flowcrypt.email.api.retrofit.node.NodeRepository import com.flowcrypt.email.api.retrofit.node.PgpApiRepository import com.flowcrypt.email.api.retrofit.request.model.InitialLegacySubmitModel @@ -40,6 +41,7 @@ import com.flowcrypt.email.model.PgpContact import com.flowcrypt.email.security.KeyStoreCryptoManager import com.flowcrypt.email.security.KeysStorageImpl import com.flowcrypt.email.security.SecurityUtils +import com.flowcrypt.email.security.pgp.PgpKey import com.flowcrypt.email.service.actionqueue.actions.BackupPrivateKeyToInboxAction import com.flowcrypt.email.service.actionqueue.actions.RegisterUserPublicKeyAction import com.flowcrypt.email.service.actionqueue.actions.SendWelcomeTestEmailAction @@ -375,7 +377,7 @@ class PrivateKeysViewModel(application: Application) : BaseNodeApiViewModel(appl newPassphrase: String, originalPrivateKey: String?): NodeKeyDetails = withContext(Dispatchers.IO) { - val keyDetailsList = NodeCallsExecutor.parseKeys(originalPrivateKey!!) + val keyDetailsList = PgpKey.parseKeysC(originalPrivateKey!!.toByteArray()) if (CollectionUtils.isEmpty(keyDetailsList) || keyDetailsList.size != 1) { throw IllegalStateException("Parse keys error") } @@ -387,19 +389,19 @@ class PrivateKeysViewModel(application: Application) : BaseNodeApiViewModel(appl throw IllegalStateException("Passphrase for key with longid $longId not found") } - val (decryptedKey) = NodeCallsExecutor.decryptKey(nodeKeyDetails.privateKey!!, oldPassphrase!!) + val decryptedKey = PgpKey.decryptKey(nodeKeyDetails.privateKey!!, oldPassphrase!!) if (TextUtils.isEmpty(decryptedKey)) { throw IllegalStateException("Can't decrypt key with longid " + longId!!) } - val (encryptedKey) = NodeCallsExecutor.encryptKey(decryptedKey!!, newPassphrase) + val encryptedKey = PgpKey.encryptKey(decryptedKey, newPassphrase) if (TextUtils.isEmpty(encryptedKey)) { throw IllegalStateException("Can't encrypt key with longid " + longId!!) } - val modifiedKeyDetailsList = NodeCallsExecutor.parseKeys(encryptedKey!!) + val modifiedKeyDetailsList = PgpKey.parseKeysC(encryptedKey.toByteArray()) if (CollectionUtils.isEmpty(modifiedKeyDetailsList) || modifiedKeyDetailsList.size != 1) { throw IllegalStateException("Parse keys error") } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/security/SecurityUtils.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/security/SecurityUtils.kt index 04e8e100c4..5d47e0604d 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/security/SecurityUtils.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/security/SecurityUtils.kt @@ -1,6 +1,8 @@ /* * © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com - * Contributors: DenBond7 + * Contributors: + * DenBond7 + * Ivan Pizhenko */ package com.flowcrypt.email.security @@ -12,6 +14,7 @@ import com.flowcrypt.email.R import com.flowcrypt.email.api.retrofit.node.NodeCallsExecutor import com.flowcrypt.email.database.FlowCryptRoomDatabase import com.flowcrypt.email.database.entity.AccountEntity +import com.flowcrypt.email.security.pgp.PgpKey import com.flowcrypt.email.util.exception.DifferentPassPhrasesException import com.flowcrypt.email.util.exception.NoKeyAvailableException import com.flowcrypt.email.util.exception.NoPrivateKeysAvailableException @@ -93,12 +96,11 @@ class SecurityUtils { else -> throw IllegalArgumentException(context.getString(R.string.missing_pass_phrase_strength_evaluation)) } - val nodeKeyDetailsList = NodeCallsExecutor.parseKeys(private) + val nodeKeyDetailsList = PgpKey.parseKeysC(private.toByteArray()) val keyDetails = nodeKeyDetailsList.first() val encryptedKey = if (keyDetails.isFullyDecrypted == true) { - val encryptKeResult = NodeCallsExecutor.encryptKey(private, passPhrase) - encryptKeResult.encryptedKey + PgpKey.encryptKey(private, passPhrase) } else { keyDetails.privateKey } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/security/pgp/PgpKey.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/security/pgp/PgpKey.kt index 2b2356933a..8160a77cff 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/security/pgp/PgpKey.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/security/pgp/PgpKey.kt @@ -8,8 +8,8 @@ package com.flowcrypt.email.security.pgp import com.flowcrypt.email.api.retrofit.response.model.node.MsgBlock import com.flowcrypt.email.api.retrofit.response.model.node.NodeKeyDetails import com.flowcrypt.email.core.msg.MsgBlockParser +import com.flowcrypt.email.extensions.pgp.armor import com.flowcrypt.email.extensions.pgp.toNodeKeyDetails -import java.nio.charset.StandardCharsets import org.bouncycastle.bcpg.ArmoredInputStream import org.bouncycastle.openpgp.PGPKeyRing import org.bouncycastle.openpgp.PGPObjectFactory @@ -21,8 +21,38 @@ import org.bouncycastle.openpgp.PGPSignature import org.bouncycastle.openpgp.jcajce.JcaPGPPublicKeyRingCollection import org.bouncycastle.openpgp.jcajce.JcaPGPSecretKeyRingCollection import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator +import org.pgpainless.PGPainless +import org.pgpainless.util.Passphrase +import java.nio.charset.StandardCharsets object PgpKey { + fun encryptKey(armored: String, passphrase: String): String { + return try { + val keys = parseAndNormalizeKeyRings(armored) + PGPainless.modifyKeyRing(keys[0] as PGPSecretKeyRing) + .changePassphraseFromOldPassphrase(null) + .withSecureDefaultSettings() + .toNewPassphrase(Passphrase.fromPassword(passphrase)) + .done() + .armor() + } catch (e: Exception) { + "" + } + } + + fun decryptKey(armored: String, passphrase: String): String { + return try { + val keys = parseAndNormalizeKeyRings(armored) + PGPainless.modifyKeyRing(keys[0] as PGPSecretKeyRing) + .changePassphraseFromOldPassphrase(Passphrase.fromPassword(passphrase)) + .withSecureDefaultSettings() + .toNoPassphrase() + .done() + .armor() + } catch (ex: Exception) { + "" + } + } /** * Parses multiple keys, binary or armored. @@ -30,20 +60,20 @@ object PgpKey { * @return Pair.first indicates armored (true) or binary (false) format * Pair.second list of keys */ - fun parseKeys(source: ByteArray): Pair> { + fun parseKeys(source: ByteArray): Pair> { val blockType = PgpMsg.detectBlockType(source) if (blockType.second == MsgBlock.Type.UNKNOWN) { throw IllegalArgumentException("Unknown message type") } - val allKeys = mutableListOf() + val allKeys = mutableListOf() if (blockType.first) { // armored text format val blocks = MsgBlockParser.detectBlocks(String(source, StandardCharsets.UTF_8)) for (block in blocks) { val content = block.content if (content != null) { - val keys = parse(content) + val keys = parseAndNormalizeKeyRings(content) allKeys.addAll(keys) } } @@ -53,7 +83,7 @@ object PgpKey { while (true) { val obj = objectFactory.nextObject() ?: break if (obj is PGPKeyRing) { - allKeys.add(obj.toNodeKeyDetails()) + allKeys.add(obj) } } } @@ -61,8 +91,17 @@ object PgpKey { return Pair(blockType.first, allKeys) } - fun parse(armored: String): List - = parseAndNormalizeKeyRings(armored).map { it.toNodeKeyDetails() }.toList() + /** + * Parse a list of [NodeKeyDetails] from the given string. It can take one key or many keys, it can be + * private or public keys, it can be armored or binary... doesn't matter. + * + * This method should be dropped in the future. Currently it should be used just for compatibility. + * + * @return list of keys + */ + fun parseKeysC(source: ByteArray): List { + return parseKeys(source).second.map { it.toNodeKeyDetails() } + } private fun parseAndNormalizeKeyRings(armored: String): List { val normalizedArmored = PgpArmor.normalize(armored, MsgBlock.Type.UNKNOWN) @@ -70,7 +109,7 @@ object PgpKey { if (PgpArmor.ARMOR_HEADER_DICT_REGEX[MsgBlock.Type.PUBLIC_KEY]!! .beginRegexp.containsMatchIn(normalizedArmored)) { val keyRingCollection = JcaPGPPublicKeyRingCollection( - ArmoredInputStream(normalizedArmored.toByteArray(StandardCharsets.UTF_8).inputStream()) + ArmoredInputStream(normalizedArmored.toByteArray(StandardCharsets.UTF_8).inputStream()) ) // We have to use reflection because BouncyCastle declares "order" list as a private field // https://stackoverflow.com/a/1196207/1540501 diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/service/CheckClipboardToFindKeyService.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/service/CheckClipboardToFindKeyService.kt index 79298922e0..d1bf0175ca 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/service/CheckClipboardToFindKeyService.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/service/CheckClipboardToFindKeyService.kt @@ -1,6 +1,8 @@ /* * © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com - * Contributors: DenBond7 + * Contributors: + * DenBond7 + * Ivan Pizhenko */ package com.flowcrypt.email.service @@ -18,9 +20,9 @@ import android.os.Message import android.os.Messenger import android.os.RemoteException import android.text.TextUtils -import com.flowcrypt.email.api.retrofit.node.NodeCallsExecutor import com.flowcrypt.email.model.KeyDetails import com.flowcrypt.email.model.KeyImportModel +import com.flowcrypt.email.security.pgp.PgpKey import com.flowcrypt.email.util.LogsUtil import com.flowcrypt.email.util.exception.ExceptionUtil import com.google.android.gms.common.util.CollectionUtils @@ -111,7 +113,7 @@ class CheckClipboardToFindKeyService : Service(), ClipboardManager.OnPrimaryClip * The incoming handler realization. This handler will be used to communicate with current * service and the worker thread. */ - private class ReplyHandler internal constructor(checkClipboardToFindKeyService: CheckClipboardToFindKeyService) + private class ReplyHandler(checkClipboardToFindKeyService: CheckClipboardToFindKeyService) : Handler() { private val weakRef: WeakReference = WeakReference(checkClipboardToFindKeyService) @@ -138,14 +140,14 @@ class CheckClipboardToFindKeyService : Service(), ClipboardManager.OnPrimaryClip * This handler will be used by the instance of [HandlerThread] to receive message from * the UI thread. */ - private class ServiceWorkerHandler internal constructor(looper: Looper) : Handler(looper) { + private class ServiceWorkerHandler(looper: Looper) : Handler(looper) { override fun handleMessage(msg: Message) { when (msg.what) { MESSAGE_WHAT -> { val clipboardText = msg.obj as String try { - val nodeKeyDetails = NodeCallsExecutor.parseKeys(clipboardText) + val nodeKeyDetails = PgpKey.parseKeysC(clipboardText.toByteArray()) if (!CollectionUtils.isEmpty(nodeKeyDetails)) { sendReply(msg) } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/service/actionqueue/actions/BackupPrivateKeyToInboxAction.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/service/actionqueue/actions/BackupPrivateKeyToInboxAction.kt index ca85c72181..0b8d566694 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/service/actionqueue/actions/BackupPrivateKeyToInboxAction.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/service/actionqueue/actions/BackupPrivateKeyToInboxAction.kt @@ -1,6 +1,8 @@ /* * © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com - * Contributors: DenBond7 + * Contributors: + * DenBond7 + * Ivan Pizhenko */ package com.flowcrypt.email.service.actionqueue.actions @@ -16,6 +18,7 @@ import com.flowcrypt.email.api.retrofit.node.NodeCallsExecutor import com.flowcrypt.email.database.FlowCryptRoomDatabase import com.flowcrypt.email.jetpack.viewmodel.AccountViewModel import com.flowcrypt.email.security.KeysStorageImpl +import com.flowcrypt.email.security.pgp.PgpKey import com.google.gson.annotations.SerializedName /** @@ -43,14 +46,12 @@ data class BackupPrivateKeyToInboxAction @JvmOverloads constructor(override var val session = OpenStoreHelper.getAccountSess(context, account) val transport = SmtpProtocolUtil.prepareSmtpTransport(context, session, account) - val (encryptedKey) = NodeCallsExecutor.encryptKey(keyEntity.privateKeyAsString, keyEntity - .passphrase!!) - + val encryptedKey = PgpKey.encryptKey(keyEntity.privateKeyAsString, keyEntity.passphrase!!) if (TextUtils.isEmpty(encryptedKey)) { throw IllegalStateException("An error occurred during encrypting some key") } - val mimeBodyPart = EmailUtil.genBodyPartWithPrivateKey(encryptedAccount, encryptedKey!!) + val mimeBodyPart = EmailUtil.genBodyPartWithPrivateKey(encryptedAccount, encryptedKey) val message = EmailUtil.genMsgWithPrivateKeys(context, encryptedAccount, session, mimeBodyPart) transport.sendMessage(message, message.allRecipients) } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/service/actionqueue/actions/EncryptPrivateKeysIfNeededAction.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/service/actionqueue/actions/EncryptPrivateKeysIfNeededAction.kt index e243c3ab3d..34cecc45a4 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/service/actionqueue/actions/EncryptPrivateKeysIfNeededAction.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/service/actionqueue/actions/EncryptPrivateKeysIfNeededAction.kt @@ -1,6 +1,8 @@ /* * © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com - * Contributors: DenBond7 + * Contributors: + * DenBond7 + * Ivan Pizhenko */ package com.flowcrypt.email.service.actionqueue.actions @@ -10,11 +12,11 @@ import android.os.Parcel import android.os.Parcelable import androidx.preference.PreferenceManager import com.flowcrypt.email.Constants -import com.flowcrypt.email.api.retrofit.node.NodeCallsExecutor import com.flowcrypt.email.database.FlowCryptRoomDatabase import com.flowcrypt.email.database.entity.KeyEntity import com.flowcrypt.email.security.KeyStoreCryptoManager import com.flowcrypt.email.security.KeysStorageImpl +import com.flowcrypt.email.security.pgp.PgpKey import com.flowcrypt.email.ui.notifications.SystemNotificationManager import com.flowcrypt.email.util.SharedPreferencesHelper import com.flowcrypt.email.util.exception.ExceptionUtil @@ -49,7 +51,7 @@ data class EncryptPrivateKeysIfNeededAction @JvmOverloads constructor(override v for (keyEntity in keyEntities) { val passphrase = keyEntity.passphrase ?: continue - val keyDetailsList = NodeCallsExecutor.parseKeys(keyEntity.privateKeyAsString) + val keyDetailsList = PgpKey.parseKeysC(keyEntity.privateKeyAsString.toByteArray()) if (keyDetailsList.isEmpty() || keyDetailsList.size != 1) { ExceptionUtil.handleError( IllegalArgumentException("An error occurred during the key parsing| 1: " @@ -64,14 +66,14 @@ data class EncryptPrivateKeysIfNeededAction @JvmOverloads constructor(override v } try { - val encryptedKeyResult = NodeCallsExecutor.encryptKey(keyDetails.privateKey!!, passphrase) + val encryptedKey = PgpKey.encryptKey(keyDetails.privateKey!!, passphrase) - if (encryptedKeyResult.encryptedKey.isNullOrEmpty()) { + if (encryptedKey.isEmpty()) { ExceptionUtil.handleError(IllegalArgumentException("An error occurred during the key encryption")) continue } - val encryptedKeyDetailsList = NodeCallsExecutor.parseKeys(encryptedKeyResult.encryptedKey) + val encryptedKeyDetailsList = PgpKey.parseKeysC(encryptedKey.toByteArray()) if (encryptedKeyDetailsList.isEmpty() || encryptedKeyDetailsList.size != 1) { ExceptionUtil.handleError(IllegalArgumentException("An error occurred during the key parsing| 2")) continue diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/PreviewImportPgpContactFragment.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/PreviewImportPgpContactFragment.kt index 5ae4c058a0..cc9eacf468 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/PreviewImportPgpContactFragment.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/PreviewImportPgpContactFragment.kt @@ -1,6 +1,8 @@ /* * © 2016-present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com - * Contributors: DenBond7 + * Contributors: + * DenBond7 + * Ivan Pizhenko */ package com.flowcrypt.email.ui.activity.fragment @@ -22,7 +24,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.flowcrypt.email.Constants import com.flowcrypt.email.R -import com.flowcrypt.email.api.retrofit.node.NodeCallsExecutor import com.flowcrypt.email.api.retrofit.response.model.node.NodeKeyDetails import com.flowcrypt.email.database.FlowCryptRoomDatabase import com.flowcrypt.email.database.entity.ContactEntity @@ -30,6 +31,7 @@ import com.flowcrypt.email.jetpack.viewmodel.ContactsViewModel import com.flowcrypt.email.model.PgpContact import com.flowcrypt.email.model.PublicKeyInfo import com.flowcrypt.email.model.results.LoaderResult +import com.flowcrypt.email.security.pgp.PgpKey import com.flowcrypt.email.ui.activity.fragment.base.BaseFragment import com.flowcrypt.email.ui.adapter.ImportPgpContactsRecyclerViewAdapter import com.flowcrypt.email.util.GeneralUtil @@ -219,7 +221,7 @@ class PreviewImportPgpContactFragment : BaseFragment(), View.OnClickListener, private fun parseKeys(armoredKeys: String?): LoaderResult { try { - val details = NodeCallsExecutor.parseKeys(armoredKeys!!) + val details = PgpKey.parseKeysC(armoredKeys!!.toByteArray()) return if (!CollectionUtils.isEmpty(details)) { LoaderResult(parsePublicKeysInfo(details), null) diff --git a/FlowCrypt/src/test/java/com/flowcrypt/email/security/pgp/PgpKeyTest.kt b/FlowCrypt/src/test/java/com/flowcrypt/email/security/pgp/PgpKeyTest.kt index f5db84583b..b251d9427e 100644 --- a/FlowCrypt/src/test/java/com/flowcrypt/email/security/pgp/PgpKeyTest.kt +++ b/FlowCrypt/src/test/java/com/flowcrypt/email/security/pgp/PgpKeyTest.kt @@ -8,6 +8,7 @@ package com.flowcrypt.email.security.pgp import com.flowcrypt.email.api.retrofit.response.model.node.Algo import com.flowcrypt.email.api.retrofit.response.model.node.KeyId import com.flowcrypt.email.api.retrofit.response.model.node.NodeKeyDetails +import com.flowcrypt.email.extensions.pgp.toNodeKeyDetails import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test @@ -78,7 +79,7 @@ class PgpKeyTest { errorMsg = null ) assertEquals(1, result.second.size) - assertEquals(expected, result.second[0]) + assertEquals(expected, result.second[0].toNodeKeyDetails()) } @Test @@ -147,6 +148,6 @@ class PgpKeyTest { errorMsg = null ) assertEquals(1, result.second.size) - assertEquals(expected, result.second[0]) + assertEquals(expected, result.second[0].toNodeKeyDetails()) } }