/* * Copyright (c) 2022 Proton AG * * This file is part of Proton Mail. * * Proton Mail is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Proton Mail is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Proton Mail. If not, see https://www.gnu.org/licenses/. */ package ch.protonmail.android.crypto import android.text.TextUtils import androidx.test.filters.LargeTest import ch.protonmail.android.api.models.Keys import ch.protonmail.android.core.UserManager import ch.protonmail.android.data.local.model.Attachment import ch.protonmail.android.mapper.bridge.AddressKeyBridgeMapper import ch.protonmail.android.mapper.bridge.UserKeyBridgeMapper import ch.protonmail.android.utils.crypto.OpenPGP import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic import me.proton.core.domain.arch.map import me.proton.core.domain.entity.UserId import me.proton.core.user.domain.entity.AddressId import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import javax.mail.internet.InternetHeaders import kotlin.test.Test @LargeTest internal class CryptoTest { private val oneAddressKeyUserManagerMock: UserManager = mockk() private val manyAddressKeysUserManagerMock: UserManager = mockk() private val openPgp = OpenPGP() private val openPgpMock: OpenPGP = mockk() //region One Address Key Setup private val oneAddressKeyUserId = UserId("one_address_key_user") private val oneAddressKeyMailboxPassword = "7NgO4d0h72zt4XuFLOUbg352vhrn.tu" private val oneAddressKeyAddressId = "MMxTCP7DMErrWkOREQljdviitcZ1mDzjWcnzdg8wqObisClP25ILZ18vUsNgUVi-JD3O2EgmOuiEmx8C5qmofw==" private val oneAddressKeyUserKeyFingerprint = "20cf363b58ec99e722e53ec411c31e8e5e07f4d0" private val armoredPrivateKey = """ -----BEGIN PGP PRIVATE KEY BLOCK----- Version: ProtonMail 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 dlEt7f8XNvX3HxQw9w== =FW0u -----END PGP PRIVATE KEY BLOCK----- """.trimIndent() private val oneAddressKeyAddressKeys = listOf( Keys( "DvRZxrFRFUnjsL6MCOdGjyMZ9AoECd7kNXX9uKxmV-75K4iArEHijRPvd7Dhw43yBlCDxIsbNSW7cg2Uu5FUFg==", armoredPrivateKey, 3, 1, null, null, null, 1 ) ) private val oneAddressKeyUserKeys = listOf( Keys( "ScOOyl7_x7HXDuIUGUzWaIz83IFQJKWHi85smpaV-QH-4gVnDBwnWBtDixsVMfehF-ZGOjxrbUfUsmm7cO4R5Q==", armoredPrivateKey, 0, 1, null, null, null, 1 ) ) //endregion //region Many Address Keys Setup private val manyAddressKeysUserId = UserId("many_address_keys_user") private val manyAddressKeysMailboxPassword = "ikaAA3dimv9p7D.bqZ6mq.R45LRS6oi" private val manyAddressKeysAddressId = "odHOhMzF3YKgGR9firZjLxRWn9lfF2CPuS4XX2t0VWaKggxd3qqQ6QWv-hSbavF6VjZRmuFdDVXsMgh_lhUX-Q==" private val manyAddressKeysAddressKeys = listOf( Keys( "i9DnLBbuJ8VfUf3ZG78KSz9vr8A6Tx--ylLAWOSvlvXskdW8deVC_UVA_Yvx6UZf5xv9vCRjfwNkq7JrJuiaYw==", """ -----BEGIN PGP PRIVATE KEY BLOCK----- Version: ProtonMail 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 a2j5Ak+MfeXknuaYqP6hs5BzulMTTJjM =4S1O -----END PGP PRIVATE KEY BLOCK----- """.trimIndent(), 3, 1, """ -----BEGIN PGP MESSAGE----- Version: ProtonMail wcBMA/AwZ+kGahlZAQf/fkz6NVnIhvSFSMA5GpaakdUC57vCPZa3Zf0VLJZO j3Nh3Xn1kIvFDGe75H4HZsAGJFFGyFkjKIEoyR4bMOzK1M7vKilm6O47ydnS hGutVmAo7nHEdbgDjUEnwJnePwYK8IaTpPK7QjRxBAI553NQNLM9OJ+byluU /bR670tG4UJpMkA8eEvjpHS6+xLngq+HT3PM81QsKUwBmkRFVHyLqqd3y1yg GSTFedNqOZae7CXHlxJe88wU9n9egZPiIsbRErf4ZJWhVbPQQxYx4cavVa00 QncdJ00QDWStjZFZucK8RZU3UPfhuV1W7FfIhtp/x/+hf7iIX1Y4eVZ9kjR0 /tJ4ARMLQc/NBQdHCwmMHYGJZc9r85dX6YplrdaROlvc2f2oEKxUlH0MVQoO qpYay7uM+X1ywV1NJNlrZsSDwoeR+lGRidhq/Y4r6K2g/MJCJv2xSK+Lrp7m M8EKUXj+dFaq00ViLsBEYeqnRQRsg4GRjEI+luZOT4u0 =Xd62 -----END PGP MESSAGE----- """.trimIndent(), """ -----BEGIN PGP SIGNATURE----- Version: ProtonMail wsBcBAEBCAAGBQJddheAAAoJEPiq8c68NCm8FN8IAKV+VmWYfkuiisCsWkrF VCU3sRxz//Gno6sZl01bOoJJ1rDbJH584nfVoLP2mmu12gcO6nKWVj7eAN0j FuKp9ZEB6XW4LdxVd1KAklTPYN+OePvbZBgXoH/OX4+VSadkBgZfPUeZ9oNU WcBjzYWEZNWNCxRlDOiaZX7q4mNMlnvhZF0zk3/6g88CKToXlhW7f4iJ36EX wYnWjwQGhsBEJ3BoYeYFW2M6mXlh6Fiembe9FZmORbhlCpJ0exPOC4rKg8EE 7XKWrrAVncwhXb3IbBPwbsWVS5yBziaiw1Ozo6HyAzsBEskLRajBjZoByO8x TkchT8r9OTDm26fYGVdGiQg= =68Qs -----END PGP SIGNATURE----- """.trimIndent(), null, 1 ), Keys( "QtsLAEJcOo_jhThoFLMfCQrWme3lRiQ16TWHwE9O0Vr-4Qn-3xSWvHGzYesK72--nTwebC9ZK01RhMd16ymDFg==", """ -----BEGIN PGP PRIVATE KEY BLOCK----- Version: ProtonMail xYYEXXYRuxYJKwYBBAHaRw8BAQdAtZY+Jb6pR3lMwGroH7k6/eG8UrOql+FV 3pH1Bd/6xCf+CQMIE8QkUA7nY/xgLDtKTJ0J4wS3fgT5+0/ztay5u3PRJt5m TUVOZzhd8ReeDOu4xsP4exFGMy/CVu6A90cQthyaDxJGCMR5c7ySt/OwfU7k iM0vYXJvbjIyQHByb3Rvbm1haWwuYmx1ZSA8YXJvbjIyQHByb3Rvbm1haWwu Ymx1ZT7CdwQQFgoAHwUCXXYRuwYLCQcIAwIEFQgKAgMWAgECGQECGwMCHgEA CgkQgovwMGfg5xzb9AD/TQaYoyas7x0lbb/sX/AwWmPos4FOoj2Bu+IYcblr b/QA/2Fdbxgep0qSTfDWW2cJ465NLekrj/BSWuBkUmFc+AQLx4sEXXYRuxIK KwYBBAGXVQEFAQEHQMjPZ/LK0Vteukg6Ah0EyV4ClzjQBS7Bf/Ay0gbh8ONj AwEIB/4JAwhX9ycQRkdaqWC6Vtauscd8gYHgTdTosb6ANkVrrQd6w7s6u7BH Abe3NjrWcbQo+FkXbca9r/+YHqme7oSwF0Cp4QATmXEwAf8aIDvWkOTnwmEE GBYIAAkFAl12EbsCGwwACgkQgovwMGfg5xwhvQD+NvvdyEEY+4g1tkp2qC2y q0SamQiEOg6/yz5gzwPEatoBAOk+AJwP+1qdJncILj0KJ30KnfBHbEa86veO z7XCwucC =GzAB -----END PGP PRIVATE KEY BLOCK----- """.trimIndent(), 1, 0, """ -----BEGIN PGP MESSAGE----- Version: ProtonMail wcBMA7M4YhTWmh7GAQgAi8nn7wQcb+bh0EZknNdPHMJ3D1QLijgTSv/WfD3p 2k14RoJReYW7/gvPBUJQKC+unZGuUDrceSJsAZskBGTnJ2ZLNVkAjSljUl9l za+XYHKfJnhrVsF9E1edeh6KY32nd7F11UPcJ5/7ca1kZCNdUIaAoDTdPI7B wpC+g8A6vylVJ5P1gTKRPi+YR4inRPIxXz3f4nrdrZWO5ta4Yt8wSwgF8VRx KItqunhuphaR2E66aUftennIrj8SQRl+ExqDRRMOQGpwF53UnZBX+JvMjq64 tFDoIheOolCCt6yUa85iLTuCiMLNms+Mz/T8FvrqUs4ousKawEi6cVYK5tca CdJ4AUa86f/szoTH+oWuFApaLzK5j8KYQF0Z7YB8P/TGkkGrtpbl6ldSCoc3 UuFCTHEbf+n/AbErz2om6UojgPaP7ezzpOZdCCWI1GG5o8iQodrUstbe1SMR ++kf6m7JU1dU/1tC1PjOxUoo7b4DNB1PGBLmH1uoSJlM =pcs5 -----END PGP MESSAGE----- """.trimIndent(), """ -----BEGIN PGP SIGNATURE----- Version: ProtonMail wsBcBAEBCAAGBQJddhY6AAoJEFW4yVpiddmBBDYH+wW9RXwIqtwFo1mE5T+z Wq7rxWJKu7qqeSTWmgMjhBEjrLlvD2CzIH4LZw5O+y9iVye6/4bsBMWjHgGX Rb59zR5nncqIDyKQu9sbIJYzLyl9nTnes/MgUfLwhHgJ3BDRKlg8qnxepBnr i6cin+Z81kmaQccHFSxabpA7g6KCdFOUKoq9eyvaKZIWQ3lgaMqSpJO0/3WA qP4/vPwgbVsPR5X8cxnP5fkW81l2Stz+fQKdznTM1CG1ImfuWKXxq8huXsYY wKUdbdKzG14vsCrZY/UUNq/o9515aRojjV2KgZByq4KICra6jPxkAnvz8jRx ulskRhRJqufYuGUUBmK8fx8= =4SVY -----END PGP SIGNATURE----- """.trimIndent(), null, 1 ), Keys( "Kufr0UxSSqOB6975FEPC17yNhhq6FyE_Jc18-O_Q3w7bB3yWgC-hgJrxRF2iJxfqTDAwMjtvv8_roYJhDpv8Pg==", """ -----BEGIN PGP PRIVATE KEY BLOCK----- Version: ProtonMail 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 PG6pu/4dcMT67x9K7G/QEgP/AD+jTSMS =N8jj -----END PGP PRIVATE KEY BLOCK----- """.trimIndent(), 1, 0, """ -----BEGIN PGP MESSAGE----- Version: ProtonMail wcBMA7M4YhTWmh7GAQf+NpXNbsOlshLPYAbyuRYKaOfCz8m6kMirO29XPXcj 1c9a1ruZTC8N3y3IVbhmCRQp5ykSDmv+yUGCbSt45G5IgIeOTFJLdfD19QHr dpnhmlziohqmCciLkbwRQwXbfLP4rr5n1RDIOf8ZiIKGNWrRJ2CIExhW9dM0 Rc2Ijiw3i76DyPpfELTjYxOB5IR9MhDGt9UHyJr60N47RoQQiibfwu6qWq9V 1xN7Kl+Kl5DRQFrYWnPsXYRKNHGgWZFiDRaMvzLjQLDsWeDn2+bUIwxVzoM3 N53MYkkDMKOsHr/RUCuCuGVGP4kRcYMH0MEvwCixhyr6GZvCyIiEtOFMj0TS Z9J4AZ8FMkHaF5wzmlURQn4+NP/XmFjqDDcPgjrTTcIU0VloWd/Rcrxtay54 2lHK/zrzMYkrRG7jgZvCzBoqzCjMEVbNPv3qfmz45DN5m+OfpNkN7WbYFaqH sPBRgjr9+HxsyqPu3/wdawgLlI0c5lBrhivNojZBtACj =77u7 -----END PGP MESSAGE----- """.trimIndent(), """ -----BEGIN PGP SIGNATURE----- Version: ProtonMail wsBcBAEBCAAGBQJddhY5AAoJEFW4yVpiddmBjI4H+gImMlzpBRCRnDaAYWtm Io59SeLCUYC9ML2oqIuwcM1yIfvBhpdmxNuDGAmGqazJAzLUpeiV7iz2ymdM Mk9NxHngP2dkT31q8ZdV7rvGItAVV2lgpLFHcgWPMkdCo7a3jgbbo4qbgc4p Z2+2KwHOo5NIrrjgZHRoRWrx7p96OjqWZ38buvUQXl+bjhDLh0GBYRGRY0fM dV4FK/W1cu//cwBgjKAOmLhxKNMigSxDJMY33DTPOhaiviqpKVx/3qw6EUgt nqLuiSwSM4oUQzQnbDluDVVI68E0JlxJC8KerJWP8aeq3LvyrJgbNLSSWBju LgA1n0GjKKT+n1fJR2/DfUg= =yh1P -----END PGP SIGNATURE----- """.trimIndent(), null, 1 ), Keys( "v3foSmcRMfxukR9VdZH-ql-sm4lFfAkHYbgsCzUbSrHQD-49BkEQVlmgkWk1u8oxMkceVW5Loaxwma3RSFTK8w==", """ -----BEGIN PGP PRIVATE KEY BLOCK----- Version: ProtonMail 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 b5BlAx31rUZ+NdCZyPnU+83opOdYrRjy =4Q+q -----END PGP PRIVATE KEY BLOCK----- """.trimIndent(), 1, 0, """ -----BEGIN PGP MESSAGE----- Version: ProtonMail wcBMA7M4YhTWmh7GAQgAwb04y2B+brcyyIrknDy23xQPN8sOyXhUjSOkD4b+ oS9MrA5jJoh4roeicDGAmfs8YFWBhr/raLG6t2iesxqSZ8zpf52u05DTeJy8 8nRd+1ACh6hEMYPrMzQeHC+joDjYxRtuOh/kDetQlO/RVVrOmLAlCCxXE+eR unr5G7029u7VhaCV7tg1t/b+wYfu8wiQCmZBvDXZVjlHvcCSGWCDdtHYk6sV q/rQvnSJgqC+6ilJkk1ujHkaP4Xt4CSHSDOmzHPuYs2rLVLum8U8EEpZVRVe plt6P6smMIm6dgfBUhVrJUKYCCn/HVH1aN19saBUVpOJ4MZFJhfxynEgcstT ddJ4AYZxxOU2VgdwDePMqYXtDTlL7xi46LW8fJvUitAv6BWpLJhhUR6HsjG7 oJj0VjFCreBFHXniBPyFCaivX28U+PFgSduHfq+8W5dIn94E3/Bx6Xck/wcp y/iDQpC6sVUOvsGeuErACZPuqF6sOzIL+Bva91qhoMDO =5QCS -----END PGP MESSAGE----- """.trimIndent(), """ -----BEGIN PGP SIGNATURE----- Version: ProtonMail wsBcBAEBCAAGBQJddhY4AAoJEFW4yVpiddmBB1AH/j7O0LnFxKSpPLj2s0Cl btmfj1MljLpAu303VxL6pFNxdlTQ0ehrt8Ff76aE8YRXU33zukm8mcHOM31e tjrfJhib011TcxACgkKtgs0WPpERhtyxhGpAGcIXzuEdyHIDnBfvbU4sls6j 4KYNDFBcN3vCk2DiWRRVJlXnF88cffWNq31fpkkfWAaGl5ePFqnEz54mzxm0 /MlZ+i9LP6bBBpnF6QBAO8DWYnGl3IVT9qjR0Crzp7T1obRbO32gorhU/ifA YGyKRSN6axG+6+01a523I+0qnCmhI4bFiGvE7f3BJucB/QZI4wuWLMhAqxGW IKS2Qorq1xywg/8FbDNG7GQ= =Jrx1 -----END PGP SIGNATURE----- """.trimIndent(), null, 1 ) ) private val manyAddressKeysUserKeys = listOf( Keys( "IB2lsghg5bLlCJkSu7eNPq-PD7Ae9ZXn_yy52sObxxF1NzlM8iuVY-oFvfFFxE4egvWMqse402s_ERB9SbM7HQ==", """ -----BEGIN PGP PRIVATE KEY BLOCK----- Version: ProtonMail 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 a2j5Ak+MfeXknuaYqP6hs5BzulMTTJjM =sm1p -----END PGP PRIVATE KEY BLOCK----- """.trimIndent(), 0, 1, null, null, null, 1 ), Keys( "XFEG7ogZjpsk23o8AIPlzKZiqLnLlATQmbIJzt-RubRpwhNd6F2I29OSJWqwKiq73IQfctWOn9mgJ8J3Av4Xew==", """ -----BEGIN PGP PRIVATE KEY BLOCK----- Version: ProtonMail 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 b5BlAx31rUZ+NdCZyPnU+83opOdYrRjy =kArG -----END PGP PRIVATE KEY BLOCK----- """.trimIndent(), 0, 0, null, null, null, 1 ) ) //endregion //region Token and Signature generation private val tokenAndSignatureUserId = UserId("token_and_sign") private val passphrase = "7NgO4d0h72zt4XuFLOUbg352vhrn.tu".toByteArray() private val randomTokenString = "9efb6173a8da137e7ead1a9d2b6ada0f707a19156dee0c84899761fee73e556a" private val randomToken = randomTokenString.chunked(2).map { it.toInt(16).toByte() }.toByteArray() //endregion private val addressKeyMapper = AddressKeyBridgeMapper() private val userKeyMapper = UserKeyBridgeMapper() private val oneKeyUserMock: ch.protonmail.android.domain.entity.user.User = mockk { every { addresses } returns mockk { every { findBy(AddressId(oneAddressKeyAddressId)) } answers { addresses[1] } every { addresses } returns mapOf( 1 to mockk { every { keys } returns mockk { every { keys } returns oneAddressKeyAddressKeys.map(addressKeyMapper) { it.toNewModel() } every { primaryKey } returns keys.first() } } ) } every { keys } returns mockk { every { keys } returns oneAddressKeyUserKeys.map(userKeyMapper) { it.toNewModel() } every { primaryKey } returns keys.first() } } private val manyAddressKeysUserMock: ch.protonmail.android.domain.entity.user.User = mockk { every { addresses } returns mockk { every { findBy(AddressId(manyAddressKeysAddressId)) } answers { addresses[1] } every { addresses } returns mapOf( 1 to mockk { every { keys } returns mockk { every { keys } returns manyAddressKeysAddressKeys.map(addressKeyMapper) { it.toNewModel() } every { primaryKey } returns keys.first() } } ) } every { keys } returns mockk { every { keys } returns manyAddressKeysUserKeys.map(userKeyMapper) { it.toNewModel() } every { primaryKey } returns keys.first() } } init { mockkStatic(TextUtils::class) every { oneAddressKeyUserManagerMock.openPgp } returns openPgp every { manyAddressKeysUserManagerMock.openPgp } returns openPgp // one address key /* every { oneKeyUserMock.keys } returns oneAddressKeyUserKeys every { oneKeyUserMock.getAddressById(oneAddressKeyAddressId) } returns mockk { every { keys } returns oneAddressKeyAddressKeys }*/ every { oneAddressKeyUserManagerMock.getUserBlocking(oneAddressKeyUserId) } returns oneKeyUserMock every { oneAddressKeyUserManagerMock.getUserPassphraseBlocking( oneAddressKeyUserId ) } returns oneAddressKeyMailboxPassword.toByteArray() // many address keys /* every { manyAddressKeysUserMock.keys } returns manyAddressKeysUserKeys every { manyAddressKeysUserMock.getAddressById(manyAddressKeysAddressId) } returns mockk { every { keys } returns manyAddressKeysAddressKeys }*/ every { manyAddressKeysUserManagerMock.getUserBlocking(manyAddressKeysUserId) } returns manyAddressKeysUserMock every { manyAddressKeysUserManagerMock.getUserPassphraseBlocking( manyAddressKeysUserId ) } returns manyAddressKeysMailboxPassword.toByteArray() // token and signature generation every { oneAddressKeyUserManagerMock.currentUserId } returns tokenAndSignatureUserId every { oneAddressKeyUserManagerMock.requireCurrentUserId() } returns tokenAndSignatureUserId every { oneAddressKeyUserManagerMock.getUserPassphraseBlocking(tokenAndSignatureUserId) } returns passphrase every { openPgpMock.randomToken() } returns randomToken // token and signature generation every { manyAddressKeysUserManagerMock.currentUser } returns manyAddressKeysUserMock every { manyAddressKeysUserManagerMock.currentUserId } returns tokenAndSignatureUserId every { manyAddressKeysUserManagerMock.requireCurrentUserId() } returns tokenAndSignatureUserId every { manyAddressKeysUserManagerMock.getUserPassphraseBlocking(tokenAndSignatureUserId) } returns passphrase } @Test fun get_key_fingerprint() { assertEquals( oneAddressKeyUserKeyFingerprint, openPgp.getFingerprint(oneAddressKeyAddressKeys.first().privateKey) ) } @Test fun encrypt_and_decrypt_message() { val message = "Text to encrypt and decrypt." val userCrypto = Crypto.forUser(oneAddressKeyUserManagerMock, oneAddressKeyUserId) val encrypted = userCrypto.encrypt(message, false) val decrypted = userCrypto.decrypt(encrypted) // TODO this assert fails because we probably incorrectly handle SignatureVerificationError // in TextDecryptionResult(hasSignature), or Helper.decryptExplicitVerify returns incorrect // value, 2 instead of 1 when there is no signature // assertFalse(decrypted.hasSignature()) assertFalse(decrypted.isSignatureValid) assertEquals(message, decrypted.decryptedData) } @Test fun encrypt_and_decrypt_signed_message() { val message = "Text to encrypt and decrypt, signed." val userCrypto = Crypto.forUser(oneAddressKeyUserManagerMock, oneAddressKeyUserId) val encryptedAndSigned = userCrypto.encrypt(message, true) val decrypted = userCrypto.decrypt(encryptedAndSigned) assert(decrypted.hasSignature()) assert(decrypted.isSignatureValid) assertEquals(message, decrypted.decryptedData) } @Test fun decrypt_pgp_mime_message_body_only() { val encryptedMessage = """ -----BEGIN PGP MESSAGE----- Version: ProtonMail wcBMA5kajsUECZmgAQf/ZPNo2ycCcSfoHJpRvHBpaxDOhj+pJmynsIwptekE ygoiPTUhLRtVCGSoAZOBzWYGU2wxWUAUZupJx3enkY9GGUTNFYxNgoWIjSqZ G0BmASdgQBLGfINjNACdafiFtm1to2z4s41Vwv9ENBornkABzR7VqbrSe5EY fef+ZwtXDzg5lyO6G4HqOMHmrX+H8gbDKslS3OgHk66+e58HsWPRDK9DvUfz YqGAybRZpMwAs0UXhr9MXrnUBzzd010NGo58iWugt4zggyO/xfiMaC4cXLrm 2LmGlTQrJ8+gNUSTPcOqpDtovS/Ve0LbFAcXjLMZsxyTx5UwQSFTgDZiaQwz gcHBTANv03LIBj82fgEQAIC2NiDaRLanLPwlDZx12YbrgDKcjywDWTdJDg3X ABmKK2RlnMpK8xV3ffRN+MHQv6o1a1kz8U+l5PZx1NxFwEUPEFzCgU43hg/t qgWkZDs20BfPEv84uwnxB0UKvN0BqUorCRfIqrGmcAgj/9ZcbQqp9xUGk3Wo rM3CbgCDjkL6uu9USpPdiT+sVx/I4BatZQFBBGUn6IBkTGA4jivBmlCOyoed q0IKXLL/HhcdaiicY3EgVkSVOmzv4Qvl5rS2NhqUuuzhm7J/Q0pBTjD09MuB ypFpxZ3SChTdCvYrSzXSdTHV0A3WzmjcWAPxFBQeu6EyAKDFY8xlbIGmJcuw x1xd36IZ3Lz9wvHjVkK6AGUwLX4Gbr4LqI+cv0737Kylsn8nZqNYzYyu1pIJ SRtOigIERnQQ7tJUdB9MPCQYV1HNoqtERyIsWsYxHxxIBjyh08574IbRFov0 SYvBGyeiWuUbxIWIYKNRloezrr1VdO3Ir2NXpOQcg9X5bLmFcyWLb+HkmP0L IoqPip2oj8p9bK3W5eugGpuB0Wg4rtLMC/y4uGagZWQEuIfDwbaU1DJY53Gd gLOrrwugxokWpff46nsJm7fDuKtS9JRRSrIf0kEK9U9r2PiZJ5EZGk6Xlfls rf+/B//B6CraAxchCuBKZWfiSkwzlp5JLNCHoJ9ClfiQ0sDMAUuVdfoLxykG pEgYd7WZWhL/HWqL6wnJwIgLWc0KNlNfLTe3xDzsrH40TrggeLkhxt5SMt+/ Z1qHe1I2ySAG71T+h9nXQvf59/TCJCrYeovONMytFWWM86IAlWdaGUf3UgQJ 2nbRBA1mjdlDXLASnR026jQZCGLvwI/AtEtwf/rFZCr+9BHRp3xqL/7N5eAM rQkeVtR4GHQ/5b2k/nAgikHSwPZVq3rWW7zq6LZov5o+bWrpkTC/jADoPJhS 17culs74jO0+uJIDvrXjs15/2wy8gCorjP1+uVo9jSwEl7R0YXe3N1Dk3GLJ qfXCH7M6YagGA+QrKPGVbf+u9mzW8Xa0a0LkiztOQAjVeIATQchc2CULuDaQ 3GQI5plpG+UXk56hKaHaWqOW4DFUwqytfpUouqC8HYtkNK/U/qof7W7XyK0a IQDm/u9BGpUTGi0RRIKw3MceOaqhx4CsVY+4KI8TZxTBUgz0FEolsSGc3n4z b84EjTEttONJFdRubt7KSWkoibrlQ7BBLfkd =47eC -----END PGP MESSAGE----- """.trimIndent() val expected = "Test PGP/MIME Message\r\n\r\n\r\n" val addressCrypto = Crypto.forAddress( oneAddressKeyUserManagerMock, oneAddressKeyUserId, AddressId(oneAddressKeyAddressId) ) var errorCallbackCalled = false lateinit var resultBody: String addressCrypto.decryptMime( message = CipherText(encryptedMessage), onBody = { eventBody: String, _ -> resultBody = eventBody }, onError = { errorCallbackCalled = true }, onVerified = { _, _ -> }, onAttachment = { _, _ -> }, keys = listOf(), time = 0 ) assertEquals(expected, resultBody) assertFalse(errorCallbackCalled) } @Test fun call_error_callback_when_none_of_the_address_keys_works() { val encryptedMessage = """ -----BEGIN PGP MESSAGE----- Version: ProtonMail wcBMA5kajsUECZmgAQf/ZPNo2ycCcSfoHJpRvHBpaxDOhj+pJmynsIwptekE ygoiPTUhLRtVCGSoAZOBzWYGU2wxWUAUZupJx3enkY9GGUTNFYxNgoWIjSqZ G0BmASdgQBLGfINjNACdafiFtm1to2z4s41Vwv9ENBornkABzR7VqbrSe5EY fef+ZwtXDzg5lyO6G4HqOMHmrX+H8gbDKslS3OgHk66+e58HsWPRDK9DvUfz YqGAybRZpMwAs0UXhr9MXrnUBzzd010NGo58iWugt4zggyO/xfiMaC4cXLrm 2LmGlTQrJ8+gNUSTPcOqpDtovS/Ve0LbFAcXjLMZsxyTx5UwQSFTgDZiaQwz gcHBTANv03LIBj82fgEQAIC2NiDaRLanLPwlDZx12YbrgDKcjywDWTdJDg3X ABmKK2RlnMpK8xV3ffRN+MHQv6o1a1kz8U+l5PZx1NxFwEUPEFzCgU43hg/t qgWkZDs20BfPEv84uwnxB0UKvN0BqUorCRfIqrGmcAgj/9ZcbQqp9xUGk3Wo rM3CbgCDjkL6uu9USpPdiT+sVx/I4BatZQFBBGUn6IBkTGA4jivBmlCOyoed q0IKXLL/HhcdaiicY3EgVkSVOmzv4Qvl5rS2NhqUuuzhm7J/Q0pBTjD09MuB ypFpxZ3SChTdCvYrSzXSdTHV0A3WzmjcWAPxFBQeu6EyAKDFY8xlbIGmJcuw x1xd36IZ3Lz9wvHjVkK6AGUwLX4Gbr4LqI+cv0737Kylsn8nZqNYzYyu1pIJ SRtOigIERnQQ7tJUdB9MPCQYV1HNoqtERyIsWsYxHxxIBjyh08574IbRFov0 SYvBGyeiWuUbxIWIYKNRloezrr1VdO3Ir2NXpOQcg9X5bLmFcyWLb+HkmP0L IoqPip2oj8p9bK3W5eugGpuB0Wg4rtLMC/y4uGagZWQEuIfDwbaU1DJY53Gd gLOrrwugxokWpff46nsJm7fDuKtS9JRRSrIf0kEK9U9r2PiZJ5EZGk6Xlfls rf+/B//B6CraAxchCuBKZWfiSkwzlp5JLNCHoJ9ClfiQ0sDMAUuVdfoLxykG pEgYd7WZWhL/HWqL6wnJwIgLWc0KNlNfLTe3xDzsrH40TrggeLkhxt5SMt+/ Z1qHe1I2ySAG71T+h9nXQvf59/TCJCrYeovONMytFWWM86IAlWdaGUf3UgQJ 2nbRBA1mjdlDXLASnR026jQZCGLvwI/AtEtwf/rFZCr+9BHRp3xqL/7N5eAM rQkeVtR4GHQ/5b2k/nAgikHSwPZVq3rWW7zq6LZov5o+bWrpkTC/jADoPJhS 17culs74jO0+uJIDvrXjs15/2wy8gCorjP1+uVo9jSwEl7R0YXe3N1Dk3GLJ qfXCH7M6YagGA+QrKPGVbf+u9mzW8Xa0a0LkiztOQAjVeIATQchc2CULuDaQ 3GQI5plpG+UXk56hKaHaWqOW4DFUwqytfpUouqC8HYtkNK/U/qof7W7XyK0a IQDm/u9BGpUTGi0RRIKw3MceOaqhx4CsVY+4KI8TZxTBUgz0FEolsSGc3n4z b84EjTEttONJFdRubt7KSWkoibrlQ7BBLfkd =47eC -----END PGP MESSAGE----- """.trimIndent() val addressCrypto = Crypto.forAddress( manyAddressKeysUserManagerMock, manyAddressKeysUserId, AddressId(manyAddressKeysAddressId) ) var errorCallbackCalled = false var onBodyCallbackCalled = false addressCrypto.decryptMime( message = CipherText(encryptedMessage), onBody = { _, _ -> onBodyCallbackCalled = true }, onError = { errorCallbackCalled = true }, onVerified = { _, _ -> }, onAttachment = { _, _ -> }, keys = listOf(), time = 0 ) assertTrue(errorCallbackCalled) assertFalse(onBodyCallbackCalled) } @Test fun decrypt_pgp_mime_message_with_attachments() { //region Encrypted Message val encryptedMessage = """ -----BEGIN PGP MESSAGE----- Version: ProtonMail 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 2uWTaHJe6uuxCBAblYwUPHgdDU1qw86tE7t2+0eJcyplpffFMnNkTI1diyl7 dV+tX2YY9up0zUtDhs54Kb9IiojIiQEeOYma4YN5TSMD0r2MyKdgi7YAxsGp SobKHfov8F2VzRxrB7Ys1D8SefcqZGiXF+aqw/r1r4Vl0t4xcZb2xdIsvGU4 9vbOdrP4HTz28FA7cuuVMIJlm47faq1z/NEQq6gp8kyy/62cM1SClnqy+RGf Y//tTL3DpAIFKHZIo4hyNNwtoXCCRn4iOfDtKcQCQGEvhz4nADr5gXgNNd9P HfPT/eovNSX+aoae5w35K7bWE8HuI0nWj9xBOPvLmJM7ZNDsma+qCvYBlZM4 iF66EXRkOonqX129HV/YmMO2j87CznnbeG9kGdosW0UdKNVgOq8fdajlvg4r RrvHKyHU1xqfCocrp/8u+6BR48ghee/0oBI0nSpi0hA2BHKfN2NdpTIwq7l5 G36zwii+NeLEupGbt9zfhFLWdxgEzU81Srp3WUl0SLNZfeHmYGTLPjxKE5bi Aj669zwKIdRXvc/wnAE0ja0mTJkwdrvFgr5lqohBd9I9uO81Gl1TvSYzWGV+ tKDsBrlhi7Iv8pMGIOBy7jKEa3fbY+tU8TlX4nNeCRaVWq36RRuc8xaRTMHg ey3zflKFPbXGj+r8P/GJD8MLJyPLkXYmy0tendPgr+LB+8MbkEHDcNn2D5CC ExqCJzUPDAkfjbc30+bQaggiTdqVKIrnt4nJF0ORIeev7W8RQ5VfExy/nhIM a6yMEt/7pvagPW1UAU2z7qKA2cgH8juUyxjDEuN0bGdVYGxlH0df3TpuxvVG DCoEI4i3R9gVQE5P7+bDnE1UjY4rpZGH7mG8LjKi3L1hhifvhYx0S81RqwyU K2VC35idOtE15wERB3DRbH9c+HbGu++bMe3t/rgHbemZ7FSSeXOSE8s8L8WV M1CskpavejzvYRCTMXdWLxoO9VbNq8WWgoJ7H7rupYLnQeO7Sy3fPu8qt4HO 01A6yjw1wsRFfyym8aND0Gt/61op35AA+c+IHM6A6k6loKKPZHSBxG5HUIuK bfvJNQsw76Dahv2mUPGvzFoYmBEpldaONbI/6PR1bYapeDdueU19uVJjcVLw 30NL09BkJmUEwM0ij7mOlZCnGBhP72gV+2vO8QjH0OD8aG4xMzsfbe1NnWUZ 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 OAUBTdhDjCoqYxx48+D3+Q== =X3FI -----END PGP MESSAGE----- """.trimIndent() //endregion val expectedBody = "Test PGP/MIME Message with attachment\r\n\r\n\r\n" val mockedMessageId = "0-KKFldtlrtWQRGmOQR1V4QVsnqq7nuHw_nkmdDAd2xtIvibEqnV0IYVS3FfX-RT8BruIrL35HQ35rQkP6VbBg==" val mockedAttachments = listOf( mockk { every { attachmentId } returns "PGPAttachment/0-KKFldtlrtWQRGmOQR1V4QVsnqq7nuHw_nkmdDAd2xtIvibEqnV0IYVS3FfX-RT8BruIrL35HQ35rQkP6VbBg==/dbfcdb13e07ef2fcf26249fec3a4bae2/0" every { fileName } returns "default" every { mimeType } returns "text/rfc822-headers; protected-headers=\"v1\"" every { fileSize } returns 48 every { messageId } returns mockedMessageId // every { headers } returns }, mockk { every { attachmentId } returns "PGPAttachment/0-KKFldtlrtWQRGmOQR1V4QVsnqq7nuHw_nkmdDAd2xtIvibEqnV0IYVS3FfX-RT8BruIrL35HQ35rQkP6VbBg==/778b4f3c8e74a652aefbee588e67421a/1" every { fileName } returns "elon.jpg" every { mimeType } returns "image/jpeg; name=\"elon.jpg\"" every { fileSize } returns 27723 every { messageId } returns mockedMessageId // every { headers } returns } ) lateinit var resultBody: String var errorCallbackCalled = false val attachments = mutableListOf() val addressCrypto = Crypto.forAddress(oneAddressKeyUserManagerMock, oneAddressKeyUserId, AddressId(oneAddressKeyAddressId)) addressCrypto.decryptMime( message = CipherText(encryptedMessage), onBody = { eventBody: String, _ -> resultBody = eventBody }, onAttachment = { headers: InternetHeaders, content: ByteArray -> attachments.add(Attachment.fromMimeAttachment(content, headers, mockedMessageId, attachments.size)) }, onError = { errorCallbackCalled = true }, onVerified = { _, _ -> }, keys = emptyList(), time = 0 ) attachments.forEachIndexed { i, attachment -> val expected = mockedAttachments[i] assertEquals(expected.attachmentId, attachment.attachmentId) assertEquals(expected.fileName, attachment.fileName) assertEquals(expected.mimeType, attachment.mimeType) assertEquals(expected.fileSize, attachment.fileSize) assertEquals(expected.messageId, attachment.messageId) assert(attachment.isPGPAttachment) } assertEquals(expectedBody, resultBody) assertEquals(attachments.size, mockedAttachments.size) assertFalse(errorCallbackCalled) } @Test fun check_key_passphrase() { assertTrue( openPgp.checkPassphrase(oneAddressKeyAddressKeys[0].privateKey, oneAddressKeyMailboxPassword.toByteArray()) ) assertFalse( openPgp.checkPassphrase(oneAddressKeyAddressKeys[0].privateKey, "incorrect key password".toByteArray()) ) } }