EncryptionUtilsV2IT.kt 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. /*
  2. * Nextcloud - Android Client
  3. *
  4. * SPDX-FileCopyrightText: 2023 Tobias Kaminsky <tobias@kaminsky.me>
  5. * SPDX-FileCopyrightText: 2023 Nextcloud GmbH
  6. * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
  7. */
  8. package com.owncloud.android.utils
  9. import com.google.gson.reflect.TypeToken
  10. import com.nextcloud.client.account.MockUser
  11. import com.nextcloud.common.User
  12. import com.nextcloud.utils.extensions.findMetadataKeyByUserId
  13. import com.owncloud.android.EncryptionIT
  14. import com.owncloud.android.datamodel.OCFile
  15. import com.owncloud.android.datamodel.e2e.v1.decrypted.Data
  16. import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFolderMetadataFileV1
  17. import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedFile
  18. import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedFolderMetadataFile
  19. import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedMetadata
  20. import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedUser
  21. import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFiledrop
  22. import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFiledropUser
  23. import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFolderMetadataFile
  24. import com.owncloud.android.operations.RefreshFolderOperation
  25. import com.owncloud.android.util.EncryptionTestIT
  26. import junit.framework.TestCase.assertEquals
  27. import junit.framework.TestCase.assertTrue
  28. import org.junit.Assert.assertNotEquals
  29. import org.junit.Test
  30. @Suppress("TooManyFunctions", "LargeClass")
  31. class EncryptionUtilsV2IT : EncryptionIT() {
  32. private val encryptionTestUtils = EncryptionTestUtils()
  33. private val encryptionUtilsV2 = EncryptionUtilsV2()
  34. private val enc1UserId = "enc1"
  35. private val enc1PrivateKey = """
  36. MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAo
  37. IBAQDsn0JKS/THu328z1IgN0VzYU53HjSX03WJIgWkmyTaxbiKpoJaKbksXmfSpgzV
  38. GzKFvGfZ03fwFrN7Q8P8R2e8SNiell7mh1TDw9/0P7Bt/ER8PJrXORo+GviKHxaLr7
  39. Y0BJX9i/nW/L0L/VaE8CZTAqYBdcSJGgHJjY4UMf892ZPTa9T2Dl3ggdMZ7BQ2kiCi
  40. CC3qV99b0igRJGmmLQaGiAflhFzuDQPMifUMq75wI8RSRPdxUAtjTfkl68QHu7Umye
  41. yy33OQgdUKaTl5zcS3VSQbNjveVCNM4RDH1RlEc+7Wf1BY8APqT6jbiBcROJD2CeoL
  42. H2eiIJCi+61ZkSGfAgMBAAECggEBALFStCHrhBf+GL9a+qer4/8QZ/X6i91PmaBX/7
  43. SYk2jjjWVSXRNmex+V6+Y/jBRT2mvAgm8J+7LPwFdatE+lz0aZrMRD2gCWYF6Itpda
  44. 90OlLkmQPVWWtGTgX2ta2tF5r2iSGzk0IdoL8zw98Q2UzpOcw30KnWtFMxuxWk0mHq
  45. pgp00g80cDWg3+RPbWOhdLp5bflQ36fKDfmjq05cGlIk6unnVyC5HXpvh4d4k2EWlX
  46. rjGsndVBPCjGkZePlLRgDHxT06r+5XdJ+1CBDZgCsmjGz3M8uOHyCfVW0WhB7ynzDT
  47. agVgz0iqpuhAi9sPt6iWWwpAnRw8cQgqEKw9bvKKECgYEA/WPi2PJtL6u/xlysh/H7
  48. A717CId6fPHCMDace39ZNtzUzc0nT5BemlcF0wZ74NeJSur3Q395YzB+eBMLs5p8mA
  49. 95wgGvJhM65/J+HX+k9kt6Z556zLMvtG+j1yo4D0VEwm3xahB4SUUP+1kD7dNvo4+8
  50. xeSCyjzNllvYZZC0DrECgYEA7w8pEqhHHn0a+twkPCZJS+gQTB9Rm+FBNGJqB3XpWs
  51. TeLUxYRbVGk0iDve+eeeZ41drxcdyWP+WcL34hnrjgI1Fo4mK88saajpwUIYMy6+qM
  52. LY+jC2NRSBox56eH7nsVYvQQK9eKqv9wbB+PF9SwOIvuETN7fd8mAY02UnoaaU8CgY
  53. BoHRKocXPLkpZJuuppMVQiRUi4SHJbxDo19Tp2w+y0TihiJ1lvp7I3WGpcOt3LlMQk
  54. tEbExSvrRZGxZKH6Og/XqwQsYuTEkEIz679F/5yYVosE6GkskrOXQAfh8Mb3/04xVV
  55. tMaVgDQw0+CWVD4wyL+BNofGwBDNqsXTCdCsfxAQKBgQCDv2EtbRw0y1HRKv21QIxo
  56. ju5cZW4+cDfVPN+eWPdQFOs1H7wOPsc0aGRiiupV2BSEF3O1ApKziEE5U1QH+29bR4
  57. R8L1pemeGX8qCNj5bCubKjcWOz5PpouDcEqimZ3q98p3E6GEHN15UHoaTkx0yO/V8o
  58. j6zhQ9fYRxDHB5ACtQKBgQCOO7TJUO1IaLTjcrwS4oCfJyRnAdz49L1AbVJkIBK0fh
  59. JLecOFu3ZlQl/RStQb69QKb5MNOIMmQhg8WOxZxHcpmIDbkDAm/J/ovJXFSoBdOr5o
  60. uQsYsDZhsWW97zvLMzg5pH9/3/1BNz5q3Vu4HgfBSwWGt4E2NENj+XA+QAVmGA==
  61. """.trimIndent()
  62. private val enc1Cert = """
  63. -----BEGIN CERTIFICATE-----
  64. MIIDpzCCAo+gAwIBAgIBADANBgkqhkiG9w0BAQUFADBuMRowGAYDVQQDDBF3d3cu
  65. bmV4dGNsb3VkLmNvbTESMBAGA1UECgwJTmV4dGNsb3VkMRIwEAYDVQQHDAlTdHV0
  66. dGdhcnQxGzAZBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzELMAkGA1UEBhMCREUw
  67. HhcNMTcwOTI2MTAwNDMwWhcNMzcwOTIxMTAwNDMwWjBuMRowGAYDVQQDDBF3d3cu
  68. bmV4dGNsb3VkLmNvbTESMBAGA1UECgwJTmV4dGNsb3VkMRIwEAYDVQQHDAlTdHV0
  69. dGdhcnQxGzAZBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzELMAkGA1UEBhMCREUw
  70. ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDsn0JKS/THu328z1IgN0Vz
  71. YU53HjSX03WJIgWkmyTaxbiKpoJaKbksXmfSpgzVGzKFvGfZ03fwFrN7Q8P8R2e8
  72. SNiell7mh1TDw9/0P7Bt/ER8PJrXORo+GviKHxaLr7Y0BJX9i/nW/L0L/VaE8CZT
  73. AqYBdcSJGgHJjY4UMf892ZPTa9T2Dl3ggdMZ7BQ2kiCiCC3qV99b0igRJGmmLQaG
  74. iAflhFzuDQPMifUMq75wI8RSRPdxUAtjTfkl68QHu7Umyeyy33OQgdUKaTl5zcS3
  75. VSQbNjveVCNM4RDH1RlEc+7Wf1BY8APqT6jbiBcROJD2CeoLH2eiIJCi+61ZkSGf
  76. AgMBAAGjUDBOMB0GA1UdDgQWBBTFrXz2tk1HivD9rQ75qeoyHrAgIjAfBgNVHSME
  77. GDAWgBTFrXz2tk1HivD9rQ75qeoyHrAgIjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3
  78. DQEBBQUAA4IBAQARQTX21QKO77gAzBszFJ6xVnjfa23YZF26Z4X1KaM8uV8TGzuN
  79. JA95XmReeP2iO3r8EWXS9djVCD64m2xx6FOsrUI8HZaw1JErU8mmOaLAe8q9RsOm
  80. 9Eq37e4vFp2YUEInYUqs87ByUcA4/8g3lEYeIUnRsRsWsA45S3wD7wy07t+KAn7j
  81. yMmfxdma6hFfG9iN/egN6QXUAyIPXvUvlUuZ7/BhWBj/3sHMrF9quy9Q2DOI8F3t
  82. 1wdQrkq4BtStKhciY5AIXz9SqsctFHTv4Lwgtkapoel4izJnO0ZqYTXVe7THwri9
  83. H/gua6uJDWH9jk2/CiZDWfsyFuNUuXvDSp05
  84. -----END CERTIFICATE-----
  85. """.trimIndent()
  86. private val enc2Cert = """
  87. -----BEGIN CERTIFICATE-----
  88. MIIC7DCCAdSgAwIBAgIBADANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDDARlbmMz
  89. MB4XDTIwMDcwODA3MzE1OFoXDTQwMDcwMzA3MzE1OFowDzENMAsGA1UEAwwEZW5j
  90. MzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAI/83eC/EF3xOocwjO+Z
  91. ZkPc1TFxt3aUgjEvrpZu45LOqesG67kkkVDYgjeg3Biz9XRUQXqtXaAyxRZH8GiH
  92. PFyKUiP1bUlCptd8X+hk9vxeN25YS5OS2RrxU9tDQ/dVOHr20427UvVCighotQnR
  93. /6+md1FQMV92PFxji7OP5TWOE1y389X6eb7kSPLs8Tu+2PpqaNVQ9C/89Y8KNYWs
  94. x9Zo+kbQhjfFFUikEpkuzMgT9QLaeq6xuXIPP+y1tzNmF6NTL0a2GoYULuxYWnCe
  95. joFyXj77LuLmK+KXfPdhvlxa5Kl9XHSxKPHBVVQpwPqNMT+b2T1VLE2l7M9NfImy
  96. iLcCAwEAAaNTMFEwHQYDVR0OBBYEFBKubDeR2lXwuyTrdyv6O7euPS4PMB8GA1Ud
  97. IwQYMBaAFBKubDeR2lXwuyTrdyv6O7euPS4PMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
  98. KoZIhvcNAQEFBQADggEBAChCOIH8CkEpm1eqjsuuNPa93aduLjtnZXat5eIKsKCl
  99. rL9nFslpg/DO5SeU5ynPY9F2QjX5CN/3RxDXum9vFfpXhTJphOv8N0uHU4ucmQxE
  100. DN388Vt5VtN3V2pzNUL3JSiG6qeYG047/r/zhGFVpcgb2465G5mEwFT0qnkEseCC
  101. VVZ63GN8hZgUobyRXxMIhkfWlbO1dgABB4VNyudq0CW8urmewkkbUBwCslvtUvPM
  102. WuzpQjq2A80bvbrAqO5VUfvMcqRiUWkDgfa6cHXyV0o4N11mMIoxsMgh+PFYr6lR
  103. BHkuQHqKEwP8kkWugIFj3TMcy9dYtXfMXWvzFaDoE4s=
  104. -----END CERTIFICATE-----
  105. """.trimIndent()
  106. private val enc2PrivateKey = """
  107. MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCP/N3gvxBd8TqH
  108. MIzvmWZD3NUxcbd2lIIxL66WbuOSzqnrBuu5JJFQ2II3oNwYs/V0VEF6rV2gMsUW
  109. R/BohzxcilIj9W1JQqbXfF/oZPb8XjduWEuTktka8VPbQ0P3VTh69tONu1L1QooI
  110. aLUJ0f+vpndRUDFfdjxcY4uzj+U1jhNct/PV+nm+5Ejy7PE7vtj6amjVUPQv/PWP
  111. CjWFrMfWaPpG0IY3xRVIpBKZLszIE/UC2nqusblyDz/stbczZhejUy9GthqGFC7s
  112. WFpwno6Bcl4++y7i5ivil3z3Yb5cWuSpfVx0sSjxwVVUKcD6jTE/m9k9VSxNpezP
  113. TXyJsoi3AgMBAAECggEACWwKFtlZ2FPfORZ3unwGwZ0TRFOFJljMdiyBF6307Vfh
  114. rZP729clPS2Vw88eZ+1qu+yBhmYO0NtRo0Yc2LI0xHd2rYyzVI5sfYBRhFMLCHOf
  115. 2/QiKet7knRFQP1TVr14Xy+Eo2slIBB1GNzFL/nSaeuSNjtxp6YEiCUpcJwTayAi
  116. Squ5QWMxhlciLKvwUkraFRBqkugvMz3jXzuk/i+DcYlOgoj+tytweNn/azOMH9MH
  117. mWI+3owYspjzE1rVpbrcWImvlnbInd0z9KaQPpBf7Njj7wtyBMaYww4K4GCMhboD
  118. SQCYgpnznWkPIN3jyXtmNVSsZ1nvD+Laod+0p7giOQKBgQDA6KEKctYpbt051yTe
  119. 2UP8hpq+MUSS7FIXiHlUc8s0PSujouypUyzfrPeL6yquI0GtKHkMVCWwfT+otMZR
  120. VnklofrmPTPovvsUQFM4Di411NZwzfxEbBFyVXAUWcLd9NxJ1hZW7w+hLk/N5Bej
  121. DOa2CncZmifyMNIlvIn7T1vDyQKBgQC/FE8HaDBoN98m/3rEjx7/rVtX8dCei5By
  122. Fzg/yQ2u4ELbf/Qk/n4k75sy0690EwnFdJxVn2gdNgS1YDv8YP/N5Wfq8xnX9V9B
  123. irWY/W24cN2qDNXm5i8o5wklyt+fDVqMcEHFfONUpLC+RYmOdc1rrFxPaQOYYYpp
  124. dWsnuG0ofwKBgBm6rUf8ew35qG3/gP5sEgJLXbZCUfgapvRWkoAuFYs5IWno4BHR
  125. cym+IyI5Um75atgSjtqTGpfIjMYOnmjY1L2tNg6hWRwQ5OIVlkPiuE0bvyI6hwwF
  126. MeqC9LjyI+iAsSTz9fTQW9BOofw/ENwBa4AaMzpp8iv+UPkRhYHMWtvpAoGAX6As
  127. RMqxnxaHCR9GM2Rk4RPC6OpNu2qhKVfRgKp/vIrjKrKIXpM2UgnPo8oovnBgrX7E
  128. Vl1mX2gPRy4YFx/8JPCv5vcucdOMjmJ6q0v5QxrI9DdkPR/pbhDhlRZIf3LRZAMy
  129. B0GPC2c4RKDMTI1L9pzVvbASaoo2GLz4mXJEvsUCgYEAibwFNXz1H52sZtL6/1zQ
  130. 1rHCTS8qkryBhxl5eYa6MV5YkbLJZZstF0w2nLxkPba8NttS/nJqjX/iJobD5uLb
  131. UzeD8jMeAWPNt4DZCtA4ossNYcXIMKqBVFKOANMvAAvLMpVdlNYSucNnTSQcLwI6
  132. 2J9mW5WvAAaG+j28Q/GKSuE=
  133. """.trimIndent()
  134. @Test
  135. fun testEncryptDecryptMetadata() {
  136. val metadataKey = EncryptionUtils.generateKey()
  137. val metadata = DecryptedMetadata(
  138. mutableListOf("hash1", "hash of key 2"),
  139. false,
  140. 1,
  141. mutableMapOf(
  142. Pair(EncryptionUtils.generateUid(), "Folder 1"),
  143. Pair(EncryptionUtils.generateUid(), "Folder 2"),
  144. Pair(EncryptionUtils.generateUid(), "Folder 3")
  145. ),
  146. mutableMapOf(
  147. Pair(
  148. EncryptionUtils.generateUid(),
  149. DecryptedFile(
  150. "file 1.png",
  151. "image/png",
  152. "initializationVector",
  153. "authenticationTag",
  154. "key 1"
  155. )
  156. ),
  157. Pair(
  158. EncryptionUtils.generateUid(),
  159. DecryptedFile(
  160. "file 2.png",
  161. "image/png",
  162. "initializationVector 2",
  163. "authenticationTag 2",
  164. "key 2"
  165. )
  166. )
  167. ),
  168. metadataKey
  169. )
  170. val encrypted = encryptionUtilsV2.encryptMetadata(metadata, metadataKey)
  171. val decrypted = encryptionUtilsV2.decryptMetadata(encrypted, metadataKey)
  172. assertEquals(metadata, decrypted)
  173. }
  174. @Throws(Throwable::class)
  175. @Test
  176. fun encryptDecryptSymmetric() {
  177. val string = "123"
  178. val metadataKey = EncryptionUtils.generateKeyString()
  179. val e = EncryptionUtils.encryptStringSymmetricAsString(
  180. string,
  181. metadataKey.toByteArray()
  182. )
  183. val d = EncryptionUtils.decryptStringSymmetric(e, metadataKey.toByteArray())
  184. assertEquals(string, d)
  185. val encryptedMetadata = EncryptionUtils.encryptStringSymmetric(
  186. string,
  187. metadataKey.toByteArray(),
  188. EncryptionUtils.ivDelimiter
  189. )
  190. val d2 = EncryptionUtils.decryptStringSymmetric(
  191. encryptedMetadata.ciphertext,
  192. metadataKey.toByteArray()
  193. )
  194. assertEquals(string, d2)
  195. val decrypted = EncryptionUtils.decryptStringSymmetric(
  196. encryptedMetadata.ciphertext,
  197. metadataKey.toByteArray(),
  198. encryptedMetadata.authenticationTag,
  199. encryptedMetadata.nonce
  200. )
  201. assertEquals(string, EncryptionUtils.decodeBase64BytesToString(decrypted))
  202. }
  203. @Test
  204. fun testEncryptDecryptUser() {
  205. val metadataKeyBase64 = EncryptionUtils.generateKeyString()
  206. val metadataKey = EncryptionUtils.decodeStringToBase64Bytes(metadataKeyBase64)
  207. val user = DecryptedUser("t1", encryptionTestUtils.t1PublicKey, null)
  208. val encryptedUser = encryptionUtilsV2.encryptUser(user, metadataKey)
  209. assertNotEquals(encryptedUser.encryptedMetadataKey, metadataKeyBase64)
  210. val decryptedMetadataKey = encryptionUtilsV2.decryptMetadataKey(encryptedUser, encryptionTestUtils.t1PrivateKey)
  211. val decryptedMetadataKeyBase64 = EncryptionUtils.encodeBytesToBase64String(decryptedMetadataKey)
  212. assertEquals(metadataKeyBase64, decryptedMetadataKeyBase64)
  213. }
  214. @Throws(com.owncloud.android.operations.UploadException::class, Throwable::class)
  215. @Test
  216. fun testEncryptDecryptMetadataFile() {
  217. val enc1 = MockUser("enc1", "Nextcloud")
  218. val root = OCFile("/")
  219. storageManager.saveFile(root)
  220. val folder = OCFile("/enc/").apply {
  221. parentId = storageManager.getFileByDecryptedRemotePath("/")?.fileId ?: throw IllegalStateException()
  222. }
  223. val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
  224. val encrypted = encryptionUtilsV2.encryptFolderMetadataFile(
  225. metadataFile,
  226. enc1.accountName,
  227. folder,
  228. storageManager,
  229. client,
  230. enc1PrivateKey,
  231. user,
  232. targetContext,
  233. arbitraryDataProvider
  234. )
  235. val signature = encryptionUtilsV2.getMessageSignature(enc1Cert, enc1PrivateKey, encrypted)
  236. val decrypted = encryptionUtilsV2.decryptFolderMetadataFile(
  237. encrypted,
  238. enc1.accountName,
  239. enc1PrivateKey,
  240. folder,
  241. storageManager,
  242. client,
  243. 0,
  244. signature,
  245. user,
  246. targetContext,
  247. arbitraryDataProvider
  248. )
  249. // V1 doesn't have decryptedMetadataKey so that we can ignore it for comparison
  250. for (user in decrypted.users) {
  251. user.decryptedMetadataKey = null
  252. }
  253. assertEquals(metadataFile, decrypted)
  254. }
  255. @Test
  256. fun addFile() {
  257. val enc1 = MockUser("enc1", "Nextcloud")
  258. val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
  259. assertEquals(2, metadataFile.metadata.files.size)
  260. assertEquals(1, metadataFile.metadata.counter)
  261. val updatedMetadata = encryptionUtilsV2.addFileToMetadata(
  262. EncryptionUtils.generateUid(),
  263. OCFile("/test.jpg").apply {
  264. mimeType = MimeType.JPEG
  265. },
  266. EncryptionUtils.generateIV(),
  267. // random string, not real tag
  268. EncryptionUtils.generateUid(),
  269. EncryptionUtils.generateKey(),
  270. metadataFile,
  271. storageManager
  272. )
  273. assertEquals(3, updatedMetadata.metadata.files.size)
  274. assertEquals(2, updatedMetadata.metadata.counter)
  275. }
  276. @Test
  277. fun removeFile() {
  278. val enc1 = MockUser("enc1", "Nextcloud")
  279. val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
  280. assertEquals(2, metadataFile.metadata.files.size)
  281. val filename = metadataFile.metadata.files.keys.first()
  282. encryptionUtilsV2.removeFileFromMetadata(filename, metadataFile)
  283. assertEquals(1, metadataFile.metadata.files.size)
  284. }
  285. @Test
  286. fun renameFile() {
  287. val enc1 = MockUser("enc1", "Nextcloud")
  288. val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
  289. assertEquals(2, metadataFile.metadata.files.size)
  290. val key = metadataFile.metadata.files.keys.first()
  291. val decryptedFile = metadataFile.metadata.files[key]
  292. val filename = decryptedFile?.filename
  293. val newFilename = "New File 1"
  294. encryptionUtilsV2.renameFile(key, newFilename, metadataFile)
  295. assertEquals(newFilename, metadataFile.metadata.files[key]?.filename)
  296. assertNotEquals(filename, newFilename)
  297. assertNotEquals(filename, metadataFile.metadata.files[key]?.filename)
  298. }
  299. @Test
  300. fun addFolder() {
  301. val folder = OCFile("/e/")
  302. val enc1 = MockUser("enc1", "Nextcloud")
  303. val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
  304. assertEquals(2, metadataFile.metadata.files.size)
  305. assertEquals(3, metadataFile.metadata.folders.size)
  306. val updatedMetadata = encryptionUtilsV2.addFolderToMetadata(
  307. EncryptionUtils.generateUid(),
  308. "new subfolder",
  309. metadataFile,
  310. folder,
  311. storageManager
  312. )
  313. assertEquals(2, updatedMetadata.metadata.files.size)
  314. assertEquals(4, updatedMetadata.metadata.folders.size)
  315. }
  316. @Test
  317. fun removeFolder() {
  318. val folder = OCFile("/e/")
  319. val enc1 = MockUser("enc1", "Nextcloud")
  320. val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
  321. assertEquals(2, metadataFile.metadata.files.size)
  322. assertEquals(3, metadataFile.metadata.folders.size)
  323. val encryptedFileName = EncryptionUtils.generateUid()
  324. var updatedMetadata = encryptionUtilsV2.addFolderToMetadata(
  325. encryptedFileName,
  326. "new subfolder",
  327. metadataFile,
  328. folder,
  329. storageManager
  330. )
  331. assertEquals(2, updatedMetadata.metadata.files.size)
  332. assertEquals(4, updatedMetadata.metadata.folders.size)
  333. updatedMetadata = encryptionUtilsV2.removeFolderFromMetadata(
  334. encryptedFileName,
  335. updatedMetadata
  336. )
  337. assertEquals(2, updatedMetadata.metadata.files.size)
  338. assertEquals(3, updatedMetadata.metadata.folders.size)
  339. }
  340. @Test
  341. fun verifyMetadata() {
  342. val folder = OCFile("/e/")
  343. val enc1 = MockUser("enc1", "Nextcloud")
  344. val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
  345. val encrypted = encryptionUtilsV2.encryptFolderMetadataFile(
  346. metadataFile,
  347. enc1UserId,
  348. folder,
  349. storageManager,
  350. client,
  351. enc1PrivateKey,
  352. user,
  353. targetContext,
  354. arbitraryDataProvider
  355. )
  356. val signature = encryptionUtilsV2.getMessageSignature(enc1Cert, enc1PrivateKey, encrypted)
  357. encryptionUtilsV2.verifyMetadata(encrypted, metadataFile, 0, signature)
  358. assertTrue(true) // if we reach this, test is successful
  359. }
  360. private fun generateDecryptedFileV1(): com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile {
  361. return com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile().apply {
  362. encrypted = Data().apply {
  363. key = EncryptionUtils.generateKeyString()
  364. filename = "Random filename.jpg"
  365. mimetype = MimeType.JPEG
  366. version = 1.0
  367. }
  368. initializationVector = EncryptionUtils.generateKeyString()
  369. authenticationTag = EncryptionUtils.generateKeyString()
  370. }
  371. }
  372. @Test
  373. fun testMigrateDecryptedV1ToV2() {
  374. val v1 = generateDecryptedFileV1()
  375. val v2 = encryptionUtilsV2.migrateDecryptedFileV1ToV2(v1)
  376. assertEquals(v1.encrypted.filename, v2.filename)
  377. assertEquals(v1.encrypted.mimetype, v2.mimetype)
  378. assertEquals(v1.authenticationTag, v2.authenticationTag)
  379. assertEquals(v1.initializationVector, v2.nonce)
  380. assertEquals(v1.encrypted.key, v2.key)
  381. }
  382. @Test
  383. fun testMigrateMetadataV1ToV2() {
  384. OCFile("/").apply {
  385. storageManager.saveFile(this)
  386. }
  387. val folder = OCFile("/enc/").apply {
  388. parentId = storageManager.getFileByDecryptedRemotePath("/")?.fileId ?: throw IllegalStateException()
  389. }
  390. val v1 = DecryptedFolderMetadataFileV1().apply {
  391. metadata = com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedMetadata().apply {
  392. metadataKeys = mapOf(Pair(0, EncryptionUtils.generateKeyString()))
  393. }
  394. files = mapOf(
  395. Pair(EncryptionUtils.generateUid(), generateDecryptedFileV1()),
  396. Pair(EncryptionUtils.generateUid(), generateDecryptedFileV1()),
  397. Pair(
  398. EncryptionUtils.generateUid(),
  399. com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile().apply {
  400. encrypted = Data().apply {
  401. key = EncryptionUtils.generateKeyString()
  402. filename = "subFolder"
  403. mimetype = MimeType.WEBDAV_FOLDER
  404. }
  405. initializationVector = EncryptionUtils.generateKeyString()
  406. authenticationTag = null
  407. }
  408. )
  409. )
  410. }
  411. val v2 = encryptionUtilsV2.migrateV1ToV2(
  412. v1,
  413. enc1UserId,
  414. enc1Cert,
  415. folder,
  416. storageManager
  417. )
  418. assertEquals(2, v2.metadata.files.size)
  419. assertEquals(1, v2.metadata.folders.size)
  420. assertEquals(1, v2.users.size) // only one user upon migration
  421. }
  422. @Throws(com.owncloud.android.operations.UploadException::class, Throwable::class)
  423. @Test
  424. fun addSharee() {
  425. val enc1 = MockUser("enc1", "Nextcloud")
  426. val enc2 = MockUser("enc2", "Nextcloud")
  427. val root = OCFile("/")
  428. storageManager.saveFile(root)
  429. val folder = OCFile("/enc/").apply {
  430. parentId = storageManager.getFileByDecryptedRemotePath("/")?.fileId ?: throw IllegalStateException()
  431. }
  432. var metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
  433. metadataFile = encryptionUtilsV2.addShareeToMetadata(metadataFile, enc2.accountName, enc2Cert, null)
  434. val encryptedMetadataFile = encryptionUtilsV2.encryptFolderMetadataFile(
  435. metadataFile,
  436. client.userId,
  437. folder,
  438. storageManager,
  439. client,
  440. enc1PrivateKey,
  441. user,
  442. targetContext,
  443. arbitraryDataProvider
  444. )
  445. val signature = encryptionUtilsV2.getMessageSignature(enc1Cert, enc1PrivateKey, encryptedMetadataFile)
  446. val decryptedByEnc1 = encryptionUtilsV2.decryptFolderMetadataFile(
  447. encryptedMetadataFile,
  448. enc1.accountName,
  449. enc1PrivateKey,
  450. folder,
  451. storageManager,
  452. client,
  453. metadataFile.metadata.counter,
  454. signature,
  455. user,
  456. targetContext,
  457. arbitraryDataProvider
  458. )
  459. assertEquals(metadataFile.metadata, decryptedByEnc1.metadata)
  460. val decryptedByEnc2 = encryptionUtilsV2.decryptFolderMetadataFile(
  461. encryptedMetadataFile,
  462. enc2.accountName,
  463. enc2PrivateKey,
  464. folder,
  465. storageManager,
  466. client,
  467. metadataFile.metadata.counter,
  468. signature,
  469. user,
  470. targetContext,
  471. arbitraryDataProvider
  472. )
  473. assertEquals(metadataFile.metadata, decryptedByEnc2.metadata)
  474. }
  475. @Test
  476. fun removeSharee() {
  477. val enc1 = MockUser("enc1", "Nextcloud")
  478. val enc2 = MockUser("enc2", "Nextcloud")
  479. var metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
  480. metadataFile = encryptionUtilsV2.addShareeToMetadata(
  481. metadataFile,
  482. enc2.accountName,
  483. enc2Cert,
  484. metadataFile.users.findMetadataKeyByUserId(enc2.accountName)
  485. )
  486. assertEquals(2, metadataFile.users.size)
  487. metadataFile = encryptionUtilsV2.removeShareeFromMetadata(metadataFile, enc2.accountName)
  488. assertEquals(1, metadataFile.users.size)
  489. }
  490. private fun generateDecryptedFolderMetadataFile(user: User, cert: String): DecryptedFolderMetadataFile {
  491. val metadata = DecryptedMetadata(
  492. mutableListOf("hash1", "hash of key 2"),
  493. false,
  494. 1,
  495. mutableMapOf(
  496. Pair(EncryptionUtils.generateUid(), "Folder 1"),
  497. Pair(EncryptionUtils.generateUid(), "Folder 2"),
  498. Pair(EncryptionUtils.generateUid(), "Folder 3")
  499. ),
  500. mutableMapOf(
  501. Pair(
  502. EncryptionUtils.generateUid(),
  503. DecryptedFile(
  504. "file 1.png",
  505. "image/png",
  506. "initializationVector",
  507. "authenticationTag",
  508. "key 1"
  509. )
  510. ),
  511. Pair(
  512. EncryptionUtils.generateUid(),
  513. DecryptedFile(
  514. "file 2.png",
  515. "image/png",
  516. "initializationVector 2",
  517. "authenticationTag 2",
  518. "key 2"
  519. )
  520. )
  521. ),
  522. EncryptionUtils.generateKey()
  523. )
  524. val users = mutableListOf(
  525. DecryptedUser(user.accountName, cert, null)
  526. )
  527. metadata.keyChecksums.add(encryptionUtilsV2.hashMetadataKey(metadata.metadataKey))
  528. return DecryptedFolderMetadataFile(metadata, users, mutableMapOf())
  529. }
  530. @Test
  531. fun testGZip() {
  532. val string = """
  533. This is a test.
  534. This is a test.
  535. This is a test.
  536. This is a test.
  537. This is a test.
  538. This is a test.
  539. This is a test.
  540. This is a test.
  541. This is a test.
  542. This is a test.
  543. This is a test.
  544. This is a test.
  545. This is a test.
  546. It contains linewraps and special characters:
  547. $$|²›³¥!’‘‘
  548. """.trimIndent()
  549. val gzipped = encryptionUtilsV2.gZipCompress(string)
  550. val result = encryptionUtilsV2.gZipDecompress(gzipped)
  551. assertEquals(string, result)
  552. }
  553. @Test
  554. fun gunzip() {
  555. val string = "H4sICNVkD2QAAwArycgsVgCiRIWS1OISPQDD9wZODwAAAA=="
  556. val decoded = EncryptionUtils.decodeStringToBase64Bytes(string)
  557. val gunzip = encryptionUtilsV2.gZipDecompress(decoded)
  558. assertEquals("this is a test.\n", gunzip)
  559. }
  560. // @Test
  561. // fun validate() {
  562. // // ALEX
  563. // val metadata1 = """{
  564. // "metadata": {
  565. // "authenticationTag": "zMozev5R09UopLrq7Je1lw==",
  566. // "ciphertext": "j0OBtUrEt4IveGiexjmGK7eKEaWrY70ZkteA5KxHDaZT/t2wwGy9j2FPQGpqXnW6OO3iAYPNgwFikI1smnfNvqdxzVDvhavl/IXa9Kg2niWyqK3D9zpz0YD6mDvl0XsOgTNVyGXNVREdWgzGEERCQoyHI1xowt/swe3KCXw+lf+XPF/t1PfHv0DiDVk70AeWGpPPPu6yggAIxB4Az6PEZhaQWweTC0an48l2FHj2MtB2PiMHtW2v7RMuE8Al3PtE4gOA8CMFrB+Npy6rKcFCXOgTZm5bp7q+J1qkhBDbiBYtvdsYujJ52Xa5SifTpEhGeWWLFnLLgPAQ8o6bXcWOyCoYfLfp4Jpft/Y7H8qzHbPewNSyD6maEv+xljjfU7hxibbszz5A4JjMdQy2BDGoTmJx7Mas+g6l6ZuHLVbdmgQOvD3waJBy6rOg0euux0Cn4bB4bIFEF2KvbhdGbY1Uiq9DYa7kEmSEnlcAYaHyroTkDg4ew7ER0vIBBMzKM3r+UdPVKKS66uyXtZc=",
  567. // "nonce": "W+lxQJeGq7XAJiGfcDohkg=="
  568. // },
  569. // "users": [{
  570. // "certificate": "-----BEGIN CERTIFICATE-----\nMIIDkDCCAnigAwIBAgIBADANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJERTEb\nMBkGA1UECAwSQmFkZW4tV3VlcnR0ZW1iZXJnMRIwEAYDVQQHDAlTdHV0dGdhcnQx\nEjAQBgNVBAoMCU5leHRjbG91ZDENMAsGA1UEAwwEam9objAeFw0yMzA3MTQwNzM0\nNTZaFw00MzA3MDkwNzM0NTZaMGExCzAJBgNVBAYTAkRFMRswGQYDVQQIDBJCYWRl\nbi1XdWVydHRlbWJlcmcxEjAQBgNVBAcMCVN0dXR0Z2FydDESMBAGA1UECgwJTmV4\ndGNsb3VkMQ0wCwYDVQQDDARqb2huMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEA7j3Er5YahJT0LAnSRLhpqbRo+E1AVnt98rvp3DmEfBHNzNB+DS9IBDkS\nSXM/YtfAci6Tcw8ujVBjrZX/WEmrf8ynQHxYmSaJSnP8uAT306/MceZpdpruEc9/\nS10a7vp54Zbld4NYdmfS71oVFVKgM7c/Vthx+rgu48fuxzbWAvVYLFcx47hz0DJT\nnjz2Za/R68uXpxfz7J9uEXYiqsAs/FobDsLZluT3RyywVRwKBed1EZxUeLIJiyxp\nUthhGfIb8b3Vf9jZoUVi3m5gmc4spJQHvYAkfZYHzd9ras8jBu1abQRxcu2CYnVo\n6Y0mTxhKhQS/n5gjv3ExiQF3wp/XYwIDAQABo1MwUTAdBgNVHQ4EFgQUmTeILVuB\ntv70fTGkXWGAueDp5kAwHwYDVR0jBBgwFoAUmTeILVuBtv70fTGkXWGAueDp5kAw\nDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAyVtq9XAvW7nxSW/8\nhp30z6xbzGiuviXhy/Jo91VEa8IRsWCCn3OmDFiVduTEowx76tf8clJP0gk7Pozi\n6dg/7Fin+FqQGXfCk8bLAh9gXKAikQ2GK8yRN3slRFwYC2mm23HrLdKXZHUqJcpB\nMz2zsSrOGPj1YsYOl/U8FU6KA7Yj7U3q7kDMYTAgzUPZAH+d1DISGWpZsMa0RYid\nvigCCLByiccmS/Co4Sb1esF58H+YtV5+nFBRwx881U2g2TgDKF1lPMK/y3d8B8mh\nUtW+lFxRpvyNUDpsMjOErOrtNFEYbgoUJLtqwBMmyGR+nmmh6xna331QWcRAmw0P\nnDO4ew==\n-----END CERTIFICATE-----\n",
  571. // "encryptedMetadataKey": "HVT49bYmwXbGs/dJ2avgU9unrKnPf03MYUI5ZysSR1Bz5pqz64gzH2GBAuUJ+Q4VmHtEfcMaWW7VXgzfCQv5xLBrk+RSgcLOKnlIya8jaDlfttWxbe8jJK+/0+QVPOc6ycA/t5HNCPg09hzj+gnb2L89UHxL5accZD0iEzb5cQbGrc/N6GthjgGrgFKtFf0HhDVplUr+DL9aTyKuKLBPjrjuZbv8M6ZfXO93mOMwSZH3c3rwDUHb/KEaTR/Og4pWQmrqr1VxGLqeV/+GKWhzMYThrOZAUz+5gsbckU2M5V9i+ph0yBI5BjOZVhNuDwW8yP8WtyRJwQc+UBRei/RGBQ==",
  572. // "userId": "john"
  573. // }],
  574. // "version": "2"
  575. // }
  576. //
  577. // """
  578. //
  579. // val signature1 =
  580. // "ewogICAgIm1ldGFkYXRhIjogewogICAgICAgICJhdXRoZW50aWNhdGlvblRhZyI6ICJ6TW96ZXY1UjA5VW9wTHJxN0plMWx3PT0iLAogICAgICAgICJjaXBoZXJ0ZXh0IjogImowT0J0VXJFdDRJdmVHaWV4am1HSzdlS0VhV3JZNzBaa3RlQTVLeEhEYVpUL3Qyd3dHeTlqMkZQUUdwcVhuVzZPTzNpQVlQTmd3RmlrSTFzbW5mTnZxZHh6VkR2aGF2bC9JWGE5S2cybmlXeXFLM0Q5enB6MFlENm1EdmwwWHNPZ1ROVnlHWE5WUkVkV2d6R0VFUkNRb3lISTF4b3d0L3N3ZTNLQ1h3K2xmK1hQRi90MVBmSHYwRGlEVms3MEFlV0dwUFBQdTZ5Z2dBSXhCNEF6NlBFWmhhUVd3ZVRDMGFuNDhsMkZIajJNdEIyUGlNSHRXMnY3Uk11RThBbDNQdEU0Z09BOENNRnJCK05weTZyS2NGQ1hPZ1RabTVicDdxK0oxcWtoQkRiaUJZdHZkc1l1ako1MlhhNVNpZlRwRWhHZVdXTEZuTExnUEFROG82YlhjV095Q29ZZkxmcDRKcGZ0L1k3SDhxekhiUGV3TlN5RDZtYUV2K3hsampmVTdoeGliYnN6ejVBNEpqTWRReTJCREdvVG1KeDdNYXMrZzZsNlp1SExWYmRtZ1FPdkQzd2FKQnk2ck9nMGV1dXgwQ240YkI0YklGRUYyS3ZiaGRHYlkxVWlxOURZYTdrRW1TRW5sY0FZYUh5cm9Ua0RnNGV3N0VSMHZJQkJNektNM3IrVWRQVktLUzY2dXlYdFpjPSIsCiAgICAgICAgIm5vbmNlIjogIlcrbHhRSmVHcTdYQUppR2ZjRG9oa2c9PSIKICAgIH0sCiAgICAidXNlcnMiOiB7CiAgICAgICAgImNlcnRpZmljYXRlIjogIi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLVxuTUlJRGtEQ0NBbmlnQXdJQkFnSUJBREFOQmdrcWhraUc5dzBCQVFVRkFEQmhNUXN3Q1FZRFZRUUdFd0pFUlRFYlxuTUJrR0ExVUVDQXdTUW1Ga1pXNHRWM1ZsY25SMFpXMWlaWEpuTVJJd0VBWURWUVFIREFsVGRIVjBkR2RoY25ReFxuRWpBUUJnTlZCQW9NQ1U1bGVIUmpiRzkxWkRFTk1Bc0dBMVVFQXd3RWFtOW9iakFlRncweU16QTNNVFF3TnpNMFxuTlRaYUZ3MDBNekEzTURrd056TTBOVFphTUdFeEN6QUpCZ05WQkFZVEFrUkZNUnN3R1FZRFZRUUlEQkpDWVdSbFxuYmkxWGRXVnlkSFJsYldKbGNtY3hFakFRQmdOVkJBY01DVk4wZFhSMFoyRnlkREVTTUJBR0ExVUVDZ3dKVG1WNFxuZEdOc2IzVmtNUTB3Q3dZRFZRUUREQVJxYjJodU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQlxuQ2dLQ0FRRUE3ajNFcjVZYWhKVDBMQW5TUkxocHFiUm8rRTFBVm50OThydnAzRG1FZkJITnpOQitEUzlJQkRrU1xuU1hNL1l0ZkFjaTZUY3c4dWpWQmpyWlgvV0VtcmY4eW5RSHhZbVNhSlNuUDh1QVQzMDYvTWNlWnBkcHJ1RWM5L1xuUzEwYTd2cDU0WmJsZDROWWRtZlM3MW9WRlZLZ003Yy9WdGh4K3JndTQ4ZnV4emJXQXZWWUxGY3g0N2h6MERKVFxubmp6MlphL1I2OHVYcHhmejdKOXVFWFlpcXNBcy9Gb2JEc0xabHVUM1J5eXdWUndLQmVkMUVaeFVlTElKaXl4cFxuVXRoaEdmSWI4YjNWZjlqWm9VVmkzbTVnbWM0c3BKUUh2WUFrZlpZSHpkOXJhczhqQnUxYWJRUnhjdTJDWW5Wb1xuNlkwbVR4aEtoUVMvbjVnanYzRXhpUUYzd3AvWFl3SURBUUFCbzFNd1VUQWRCZ05WSFE0RUZnUVVtVGVJTFZ1QlxudHY3MGZUR2tYV0dBdWVEcDVrQXdId1lEVlIwakJCZ3dGb0FVbVRlSUxWdUJ0djcwZlRHa1hXR0F1ZURwNWtBd1xuRHdZRFZSMFRBUUgvQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCQVFVRkFBT0NBUUVBeVZ0cTlYQXZXN254U1cvOFxuaHAzMHo2eGJ6R2l1dmlYaHkvSm85MVZFYThJUnNXQ0NuM09tREZpVmR1VEVvd3g3NnRmOGNsSlAwZ2s3UG96aVxuNmRnLzdGaW4rRnFRR1hmQ2s4YkxBaDlnWEtBaWtRMkdLOHlSTjNzbFJGd1lDMm1tMjNIckxkS1haSFVxSmNwQlxuTXoyenNTck9HUGoxWXNZT2wvVThGVTZLQTdZajdVM3E3a0RNWVRBZ3pVUFpBSCtkMURJU0dXcFpzTWEwUllpZFxudmlnQ0NMQnlpY2NtUy9DbzRTYjFlc0Y1OEgrWXRWNStuRkJSd3g4ODFVMmcyVGdES0YxbFBNSy95M2Q4QjhtaFxuVXRXK2xGeFJwdnlOVURwc01qT0VyT3J0TkZFWWJnb1VKTHRxd0JNbXlHUitubW1oNnhuYTMzMVFXY1JBbXcwUFxubkRPNGV3PT1cbi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS1cbiIsCiAgICAgICAgImVuY3J5cHRlZE1ldGFkYXRhS2V5IjogIkhWVDQ5Ylltd1hiR3MvZEoyYXZnVTl1bnJLblBmMDNNWVVJNVp5c1NSMUJ6NXBxejY0Z3pIMkdCQXVVSitRNFZtSHRFZmNNYVdXN1ZYZ3pmQ1F2NXhMQnJrK1JTZ2NMT0tubEl5YThqYURsZnR0V3hiZThqSksrLzArUVZQT2M2eWNBL3Q1SE5DUGcwOWh6aitnbmIyTDg5VUh4TDVhY2NaRDBpRXpiNWNRYkdyYy9ONkd0aGpnR3JnRkt0RmYwSGhEVnBsVXIrREw5YVR5S3VLTEJQanJqdVpidjhNNlpmWE85M21PTXdTWkgzYzNyd0RVSGIvS0VhVFIvT2c0cFdRbXJxcjFWeEdMcWVWLytHS1doek1ZVGhyT1pBVXorNWdzYmNrVTJNNVY5aStwaDB5Qkk1QmpPWlZoTnVEd1c4eVA4V3R5Ukp3UWMrVUJSZWkvUkdCUT09IiwKICAgICAgICAidXNlcklkIjogImpvaG4iCiAgICB9LAogICAgInZlcnNpb24iOiAiMiIKfQo="
  581. //
  582. // // TOBI
  583. // val metadata =
  584. // """{"metadata":{"authenticationTag":"qDcJnAAGtGDlHWiQMBfXgw\u003d\u003d","ciphertext":"3zUhwIgJWMB7DvrbsDaMvh8MbJdoTxL0OMPCCdYSfBt7gB+V/hwqelL1IOaLto3avhHGSebnrotF06iEP/jZwWg9hApIPTHc8B4XTOY0/kezqYyVqTyquTUZpDpqgVAheQskZZ8I4Ir0seajUkt4KtVRfzO6v8CePRrEg6uKwdYsqDcJnAAGtGDlHWiQMBfXgw\u003d\u003d|4hbOyn1ykQL+9D6SnPY3cQ\u003d\u003d","nonce":"4hbOyn1ykQL+9D6SnPY3cQ\u003d\u003d"},"users":[{"certificate":"-----BEGIN CERTIFICATE-----\nMIIC6DCCAdCgAwIBAgIBADANBgkqhkiG9w0BAQUFADANMQswCQYDVQQDDAJ0MTAe\nFw0yMzA3MjUwNzU3MTJaFw00MzA3MjAwNzU3MTJaMA0xCzAJBgNVBAMMAnQxMIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtafHmDBcBqIu4HmMxMDW3j0S\ny+S0YaKwHnBRt85KSwcEov0B5FOLuLknoBGx4Dn3u93ilThXXxacPMHeXL7WPuAs\n21/G7vsqwvrRRnCduf+FUO/AZeDCNErzpsQ8LmTa4PUloLPUcImpSjrHwhMs9Ekv\nEbLRjbeSmSp9XvM+1fV/3jkT5jkOSnCFx5TGwGN5uHqwUir4UWXasvg253NK2XmW\nipKCDCR9TmH1baP3pNdoiChdmErT1c6E4DbBXpTw8XgP5ZbYH+qg1UQ/hC8nRJ3D\nyCcHL+dg/GYraBMhDn4w2Vvq77xNNoNWQ9cT5Ay6cJbQLBQoJQirygQFrobYRQID\nAQABo1MwUTAdBgNVHQ4EFgQUE9zCeA9/QMAtVgLxD23X6ZcodhMwHwYDVR0jBBgw\nFoAUE9zCeA9/QMAtVgLxD23X6ZcodhMwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG\n9w0BAQUFAAOCAQEAZdy/YjJlvnz3FQwxp6oVtMJccpdxveEPfLzgaverhtd/vP8O\nAvDzOLgQJHmrDS91SG503eU4cYGyuNKwd77OyTnqMg+GUEmJhGfPpSVrEIdh65jv\nq61T4oqBdehevVmBq54rGiwL0DGv1DlXQlwiJZP4qni2KnOEFcnvL3gVtRnQjXQ+\nkHvlMshkK6w021EMV5NfjG2zg67wC65rLaej5f6Ssp2S7g2VtmE4aXq1bjAuEbqk\n4TiyZHLDdsJuqzyGyyOpMV7i9ucXDoaZt9cGS9hT2vRxTrSH63vKR8Xeig9+stLw\nt9ONcUqCKP7hd8rajtxM4JIIRExwD8OkgARWGg\u003d\u003d\n-----END CERTIFICATE-----\n","encryptedMetadataKey":"s4kDkkLpk1mSmXedP7huiCNC4DYmDAmA2VYGem5M8jIGPC6miVQoo4WXZrEBhdsLw7Msf5iT3A3fTaHhwsI8Jf4McsFyM9/FXT1mCEaGOEpNjbKOlJY1uPUFNOhLqUfFiBos6oBT53hWwoXWjytYvLBbXuXY5YLOysjgBh6URrgFUZAJAmcOJ6OFKgfIIthoqkQc7CQUY97VsRzAXzeYTANBc2yW1pSN51HqftvMzvewFRsJQLcu7a9NjpTdG9LiLhn5eLXOLymXEE/aaPHKXeprlXLzrdWU1xwZRJqV+to2FEiH6CQNsO4+9h5m0VjXekiNeAFrsXB5cJgUipGuzQ\u003d\u003d","userId":"t1"}],"version":"2.0"}"""
  585. //
  586. // val base = EncryptionUtils.encodeStringToBase64String(metadata)
  587. //
  588. // val signature =
  589. // "MIAGCSqGSIb3DQEHAqCAMIACAQExDTALBglghkgBZQMEAgEwCwYJKoZIhvcNAQcBoIAwggLoMIIB0KADAgECAgEAMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNVBAMMAnQxMB4XDTIzMDcyNTA3NTcxMloXDTQzMDcyMDA3NTcxMlowDTELMAkGA1UEAwwCdDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1p8eYMFwGoi7geYzEwNbePRLL5LRhorAecFG3zkpLBwSi/QHkU4u4uSegEbHgOfe73eKVOFdfFpw8wd5cvtY+4CzbX8bu+yrC+tFGcJ25/4VQ78Bl4MI0SvOmxDwuZNrg9SWgs9RwialKOsfCEyz0SS8RstGNt5KZKn1e8z7V9X/eORPmOQ5KcIXHlMbAY3m4erBSKvhRZdqy+Dbnc0rZeZaKkoIMJH1OYfVto/ek12iIKF2YStPVzoTgNsFelPDxeA/lltgf6qDVRD+ELydEncPIJwcv52D8ZitoEyEOfjDZW+rvvE02g1ZD1xPkDLpwltAsFCglCKvKBAWuhthFAgMBAAGjUzBRMB0GA1UdDgQWBBQT3MJ4D39AwC1WAvEPbdfplyh2EzAfBgNVHSMEGDAWgBQT3MJ4D39AwC1WAvEPbdfplyh2EzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBl3L9iMmW+fPcVDDGnqhW0wlxyl3G94Q98vOBq96uG13+8/w4C8PM4uBAkeasNL3VIbnTd5ThxgbK40rB3vs7JOeoyD4ZQSYmEZ8+lJWsQh2HrmO+rrVPiioF16F69WYGrnisaLAvQMa/UOVdCXCIlk/iqeLYqc4QVye8veBW1GdCNdD6Qe+UyyGQrrDTbUQxXk1+MbbODrvALrmstp6Pl/pKynZLuDZW2YThperVuMC4RuqThOLJkcsN2wm6rPIbLI6kxXuL25xcOhpm31wZL2FPa9HFOtIfre8pHxd6KD36y0vC3041xSoIo/uF3ytqO3EzgkghETHAPw6SABFYaAAAxggHUMIIB0AIBATASMA0xCzAJBgNVBAMMAnQxAgEAMAsGCWCGSAFlAwQCAaCBljAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yMzA3MjgwNzMwMTJaMCsGCSqGSIb3DQEJNDEeMBwwCwYJYIZIAWUDBAIBoQ0GCSqGSIb3DQEBCwUAMC8GCSqGSIb3DQEJBDEiBCAx7RTJg7hbY5Mkzjw3f6qhX7k/J0FdVz2cL3ow0AmyYjANBgkqhkiG9w0BAQsFAASCAQAbUmb9e7eoIcPNzDSmnzbrueBzgT8YszNGEI+1YCq8XdWN4kDztvP1ZNV21VCO6BvcbfUAnXXgcX5BPeLZNsgXPj3c8TbD59GQl3oT/tIchgMsA20RdAtIwvItlZKh+X6sp0OHkRPYSk/mEYKCKPqrKdJicRWex8ItCwpDR91KSOiKJrN/+DKOGG0sVI9gjzbtrHsN8HmVKxOoNV+wwipcLsWsEmuV+wvPCQ9HJidLX9Q17Bgfc+qJg19aB6iKLWPhjgnfpKGbK5VJuQTdDWPUJ2O4G3W/iwxJ0hAJ7tks4zIATmgGzhgTWYx5LVXbKcuL04xhIOjqwedHeCSBZSSaAAAAAAAA"
  590. //
  591. // val metadataFile = EncryptionUtils.deserializeJSON(
  592. // metadata,
  593. // object : TypeToken<EncryptedFolderMetadataFile>() {}
  594. // )
  595. // assertNotNull(metadataFile)
  596. //
  597. // val certJohnString = metadataFile.users[0].certificate
  598. // val certJohn = EncryptionUtils.convertCertFromString(certJohnString)
  599. //
  600. // val t1String = """-----BEGIN CERTIFICATE-----
  601. // MIIC6DCCAdCgAwIBAgIBADANBgkqhkiG9w0BAQUFADANMQswCQYDVQQDDAJ0MTAe
  602. // Fw0yMzA3MjUwNzU3MTJaFw00MzA3MjAwNzU3MTJaMA0xCzAJBgNVBAMMAnQxMIIB
  603. // IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtafHmDBcBqIu4HmMxMDW3j0S
  604. // y+S0YaKwHnBRt85KSwcEov0B5FOLuLknoBGx4Dn3u93ilThXXxacPMHeXL7WPuAs
  605. // 21/G7vsqwvrRRnCduf+FUO/AZeDCNErzpsQ8LmTa4PUloLPUcImpSjrHwhMs9Ekv
  606. // EbLRjbeSmSp9XvM+1fV/3jkT5jkOSnCFx5TGwGN5uHqwUir4UWXasvg253NK2XmW
  607. // ipKCDCR9TmH1baP3pNdoiChdmErT1c6E4DbBXpTw8XgP5ZbYH+qg1UQ/hC8nRJ3D
  608. // yCcHL+dg/GYraBMhDn4w2Vvq77xNNoNWQ9cT5Ay6cJbQLBQoJQirygQFrobYRQID
  609. // AQABo1MwUTAdBgNVHQ4EFgQUE9zCeA9/QMAtVgLxD23X6ZcodhMwHwYDVR0jBBgw
  610. // FoAUE9zCeA9/QMAtVgLxD23X6ZcodhMwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
  611. // 9w0BAQUFAAOCAQEAZdy/YjJlvnz3FQwxp6oVtMJccpdxveEPfLzgaverhtd/vP8O
  612. // AvDzOLgQJHmrDS91SG503eU4cYGyuNKwd77OyTnqMg+GUEmJhGfPpSVrEIdh65jv
  613. // q61T4oqBdehevVmBq54rGiwL0DGv1DlXQlwiJZP4qni2KnOEFcnvL3gVtRnQjXQ+
  614. // kHvlMshkK6w021EMV5NfjG2zg67wC65rLaej5f6Ssp2S7g2VtmE4aXq1bjAuEbqk
  615. // 4TiyZHLDdsJuqzyGyyOpMV7i9ucXDoaZt9cGS9hT2vRxTrSH63vKR8Xeig9+stLw
  616. // t9ONcUqCKP7hd8rajtxM4JIIRExwD8OkgARWGg==
  617. // -----END CERTIFICATE-----"""
  618. //
  619. // val t1cert = EncryptionUtils.convertCertFromString(t1String)
  620. // val t1PrivateKeyKey = EncryptionUtils.PEMtoPrivateKey(encryptionTestUtils.t1PrivateKey)
  621. //
  622. // // val signed = encryptionUtilsV2.getMessageSignature(
  623. // // t1cert,
  624. // // t1PrivateKeyKey,
  625. // // metadataFile
  626. // // )
  627. //
  628. // assertTrue(encryptionUtilsV2.verifySignedMessage(signature1, metadata1, listOf(certJohn, t1cert)))
  629. // }
  630. @Throws(Throwable::class)
  631. @Test
  632. fun testSigning() {
  633. val metadata =
  634. """{"metadata": {"authenticationTag": "zMozev5R09UopLrq7Je1lw==","ciphertext": "j0OBtUrEt4IveGiexjm
  635. |GK7eKEaWrY70ZkteA5KxHDaZT/t2wwGy9j2FPQGpqXnW6OO3iAYPNgwFikI1smnfNvqdxzVDvhavl/IXa9Kg2niWyqK3D9
  636. |zpz0YD6mDvl0XsOgTNVyGXNVREdWgzGEERCQoyHI1xowt/swe3KCXw+lf+XPF/t1PfHv0DiDVk70AeWGpPPPu6yggAIxB4
  637. |Az6PEZhaQWweTC0an48l2FHj2MtB2PiMHtW2v7RMuE8Al3PtE4gOA8CMFrB+Npy6rKcFCXOgTZm5bp7q+J1qkhBDbiBYtv
  638. |dsYujJ52Xa5SifTpEhGeWWLFnLLgPAQ8o6bXcWOyCoYfLfp4Jpft/Y7H8qzHbPewNSyD6maEv+xljjfU7hxibbszz5A4Jj
  639. |MdQy2BDGoTmJx7Mas+g6l6ZuHLVbdmgQOvD3waJBy6rOg0euux0Cn4bB4bIFEF2KvbhdGbY1Uiq9DYa7kEmSEnlcAYaHyr
  640. |oTkDg4ew7ER0vIBBMzKM3r+UdPVKKS66uyXtZc=","nonce": "W+lxQJeGq7XAJiGfcDohkg=="},"users": [{"cert
  641. |ificate": "-----BEGIN CERTIFICATE-----\nMIIDkDCCAnigAwIBAgIBADANBgkqhkiG9w0BAQUFADBhMQswCQYDVQ
  642. |QGEwJERTEb\nMBkGA1UECAwSQmFkZW4tV3VlcnR0ZW1iZXJnMRIwEAYDVQQHDAlTdHV0dGdhcnQx\nEjAQBgNVBAoMCU5l
  643. |eHRjbG91ZDENMAsGA1UEAwwEam9objAeFw0yMzA3MTQwNzM0\nNTZaFw00MzA3MDkwNzM0NTZaMGExCzAJBgNVBAYTAkRF
  644. |MRswGQYDVQQIDBJCYWRl\nbi1XdWVydHRlbWJlcmcxEjAQBgNVBAcMCVN0dXR0Z2FydDESMBAGA1UECgwJTmV4\ndGNsb3
  645. |VkMQ0wCwYDVQQDDARqb2huMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEA7j3Er5YahJT0LAnSRLhpqbRo+E
  646. |1AVnt98rvp3DmEfBHNzNB+DS9IBDkS\nSXM/YtfAci6Tcw8ujVBjrZX/WEmrf8ynQHxYmSaJSnP8uAT306/MceZpdpruEc
  647. |9/\nS10a7vp54Zbld4NYdmfS71oVFVKgM7c/Vthx+rgu48fuxzbWAvVYLFcx47hz0DJT\nnjz2Za/R68uXpxfz7J9uEXYi
  648. |qsAs/FobDsLZluT3RyywVRwKBed1EZxUeLIJiyxp\nUthhGfIb8b3Vf9jZoUVi3m5gmc4spJQHvYAkfZYHzd9ras8jBu1a
  649. |bQRxcu2CYnVo\n6Y0mTxhKhQS/n5gjv3ExiQF3wp/XYwIDAQABo1MwUTAdBgNVHQ4EFgQUmTeILVuB\ntv70fTGkXWGAue
  650. |Dp5kAwHwYDVR0jBBgwFoAUmTeILVuBtv70fTGkXWGAueDp5kAw\nDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAA
  651. |OCAQEAyVtq9XAvW7nxSW/8\nhp30z6xbzGiuviXhy/Jo91VEa8IRsWCCn3OmDFiVduTEowx76tf8clJP0gk7Pozi\n6dg/
  652. |7Fin+FqQGXfCk8bLAh9gXKAikQ2GK8yRN3slRFwYC2mm23HrLdKXZHUqJcpB\nMz2zsSrOGPj1YsYOl/U8FU6KA7Yj7U3q
  653. |7kDMYTAgzUPZAH+d1DISGWpZsMa0RYid\nvigCCLByiccmS/Co4Sb1esF58H+YtV5+nFBRwx881U2g2TgDKF1lPMK/y3d8
  654. |B8mh\nUtW+lFxRpvyNUDpsMjOErOrtNFEYbgoUJLtqwBMmyGR+nmmh6xna331QWcRAmw0P\nnDO4ew==\n-----END CER
  655. |TIFICATE-----\n","encryptedMetadataKey": "HVT49bYmwXbGs/dJ2avgU9unrKnPf03MYUI5ZysSR1Bz5pqz64gz
  656. |H2GBAuUJ+Q4VmHtEfcMaWW7VXgzfCQv5xLBrk+RSgcLOKnlIya8jaDlfttWxbe8jJK+/0+QVPOc6ycA/t5HNCPg09hzj+g
  657. |nb2L89UHxL5accZD0iEzb5cQbGrc/N6GthjgGrgFKtFf0HhDVplUr+DL9aTyKuKLBPjrjuZbv8M6ZfXO93mOMwSZH3c3rw
  658. |DUHb/KEaTR/Og4pWQmrqr1VxGLqeV/+GKWhzMYThrOZAUz+5gsbckU2M5V9i+ph0yBI5BjOZVhNuDwW8yP8WtyRJwQc+UB
  659. |Rei/RGBQ==","userId": "john"}],"version": "2"}
  660. """.trimMargin()
  661. val privateKey = EncryptionUtils.PEMtoPrivateKey(encryptionTestUtils.t1PrivateKey)
  662. val certificateT1 = EncryptionUtils.convertCertFromString(encryptionTestUtils.t1PublicKey)
  663. val certificateEnc2 = EncryptionUtils.convertCertFromString(enc2Cert)
  664. val signed = encryptionUtilsV2.signMessage(
  665. certificateT1,
  666. privateKey,
  667. metadata
  668. )
  669. val certs = listOf(
  670. certificateEnc2,
  671. certificateT1
  672. )
  673. assertTrue(encryptionUtilsV2.verifySignedData(signed, certs))
  674. }
  675. @Throws(Throwable::class)
  676. @Test
  677. fun sign() {
  678. val sut = "randomstring123"
  679. val privateKey = EncryptionUtils.PEMtoPrivateKey(encryptionTestUtils.t1PrivateKey)
  680. val certificate = EncryptionUtils.convertCertFromString(encryptionTestUtils.t1PublicKey)
  681. val signed = encryptionUtilsV2.signMessage(
  682. certificate,
  683. privateKey,
  684. sut
  685. )
  686. val certs = listOf(
  687. EncryptionUtils.convertCertFromString(enc2Cert),
  688. certificate
  689. )
  690. assertTrue(encryptionUtilsV2.verifySignedData(signed, certs))
  691. }
  692. @Test
  693. @Throws(Exception::class)
  694. fun testUpdateFileNameForEncryptedFile() {
  695. val folder = testFolder()
  696. val metadata = EncryptionTestUtils().generateFolderMetadataV2(
  697. client.userId,
  698. EncryptionTestIT.publicKey
  699. )
  700. RefreshFolderOperation.updateFileNameForEncryptedFile(storageManager, metadata, folder)
  701. assertEquals(folder.decryptedRemotePath.contains("null"), false)
  702. }
  703. /**
  704. * DecryptedFolderMetadata -> EncryptedFolderMetadata -> JSON -> encrypt -> decrypt -> JSON ->
  705. * EncryptedFolderMetadata -> DecryptedFolderMetadata
  706. */
  707. @Test
  708. @Throws(Exception::class, Throwable::class)
  709. fun encryptionMetadataV2() {
  710. val decryptedFolderMetadata1: DecryptedFolderMetadataFile =
  711. EncryptionTestUtils().generateFolderMetadataV2(client.userId, EncryptionTestIT.publicKey)
  712. val root = OCFile("/")
  713. storageManager.saveFile(root)
  714. val folder = OCFile("/enc")
  715. folder.parentId = storageManager.getFileByDecryptedRemotePath("/")?.fileId ?: throw IllegalStateException()
  716. storageManager.saveFile(folder)
  717. decryptedFolderMetadata1.filedrop.clear()
  718. // encrypt
  719. val encryptedFolderMetadata1 = encryptionUtilsV2.encryptFolderMetadataFile(
  720. decryptedFolderMetadata1,
  721. client.userId,
  722. folder,
  723. storageManager,
  724. client,
  725. EncryptionTestIT.publicKey,
  726. user,
  727. targetContext,
  728. arbitraryDataProvider
  729. )
  730. val signature = encryptionUtilsV2.getMessageSignature(enc1Cert, enc1PrivateKey, encryptedFolderMetadata1)
  731. // serialize
  732. val encryptedJson = EncryptionUtils.serializeJSON(encryptedFolderMetadata1, true)
  733. // de-serialize
  734. val encryptedFolderMetadata2 = EncryptionUtils.deserializeJSON(
  735. encryptedJson,
  736. object : TypeToken<EncryptedFolderMetadataFile?>() {}
  737. )
  738. // decrypt
  739. val decryptedFolderMetadata2 = encryptionUtilsV2.decryptFolderMetadataFile(
  740. encryptedFolderMetadata2!!,
  741. getUserId(user),
  742. EncryptionTestIT.privateKey,
  743. folder,
  744. fileDataStorageManager,
  745. client,
  746. decryptedFolderMetadata1.metadata.counter,
  747. signature,
  748. user,
  749. targetContext,
  750. arbitraryDataProvider
  751. )
  752. // V1 doesn't have decryptedMetadataKey so that we can ignore it for comparison
  753. for (user in decryptedFolderMetadata2.users) {
  754. user.decryptedMetadataKey = null
  755. }
  756. // compare
  757. assertTrue(
  758. EncryptionTestIT.compareJsonStrings(
  759. EncryptionUtils.serializeJSON(decryptedFolderMetadata1),
  760. EncryptionUtils.serializeJSON(decryptedFolderMetadata2)
  761. )
  762. )
  763. }
  764. @Throws(Throwable::class)
  765. @Test
  766. fun decryptFiledropV2() {
  767. val sut = EncryptedFiledrop(
  768. """QE5nJmA8QC3rBJxbpsZu6MvkomwHMKTYf/3dEz9Zq3ITHLK/wNAIqWTbDehBJ7SlTfXakkKR9o0sOkUDI7PD8qJyv5hW7LzifszYGe
  769. |xE0V1daFcCFApKrIEBABHVOq+ZHJd8IzNSz3hdA9bWd2eiaEGyQzgdTPELE6Ie84IwFANJHcaRB5B43aaDdbUXNJ4/oMboOReKTJ
  770. |/vT6ZGhve4DRPEsez0quyDZDNlin5hD6UaUzw=
  771. """.trimMargin(),
  772. "HC87OgVzbR2CXdWp7rKI5A==",
  773. "7PSq7INkM2WKfmEPpRpTPA==",
  774. listOf(
  775. EncryptedFiledropUser(
  776. "android3",
  777. """cNzk8cNyoTJ49Cj/x2WPlsMAnUWlZsfnKJ3VIRiczASeUYUFhaJpD8HDWE0uhkXSD7i9nzpe6pR7zllE7UE/QniDd+BQiF
  778. |80E5fSO1KVfFkLZRT+2pX5oPnl4CVtMnxb4xG7J1nAUqMhfS8PtQIr0+S7NKDdrUc41aNOB/4kH0D9LSo/bSC38L7ewv
  779. |mISM6ZFi1bfI1505kZV0HqcW12nZwHwe3s6rYkoSPBOPX1oPkvMYTVLkYuU+7DNL4HW7D9dc9X4bsSGLdj4joRi9FURi
  780. |mMv6MOrWOnYlX2zmMKAF3nEjLlhngKG7pUi/qMIlft2AhRM4cJuuIQ29vvTGFFDQ==
  781. """.trimMargin()
  782. )
  783. )
  784. )
  785. val privateKey =
  786. """MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDPNCnYcPgGQwCzL8sxLTiE0atn5tiW1nfPQc1aY/+aXvkpF4h2vT
  787. |S/hQg2SCNFUlw8aYKksk5IH5FFcPv9QFG/TQDQOnZhi7moVPnVwLkx+cDfWQQs1EOhI/ZPdSo7MdaRLttbZZs/GJfnr1ziYZTxLO
  788. |UUxT541cnSpqGTKmUXhGMoX+jQTmcn1NyBD537NdetOxSdMfvBIobjRQ70/9c1HFGQSrJa+DmPiis6iFkd1LH6WWRbreC6DsRSqK
  789. |ne3sD1ujx39k+VxtBe035c2L9PbTMMW3kBdZxlRkV1tUQhDAys0K+CyvNIFsOjqvQKTnXNfWO+kVnpOkpbTK4imuPbAgMBAAECgf
  790. |9T537U/6TuwJLSj4bfYev8qYaakfVIpyMkL33e4YBQnUzhlCPBVYgpHkDPwznk2XhjQQiVcRAycmUHBmy4aPkcOjuBmd87aTj03k
  791. |niDk+doFDNU8myuwWTw/1fHdElRnLyZxEKrb391HD4SVVQMuxnw8UoC4iNcPnYneY/GTiTtB3dVcRKdabX3Oak2TFiJyJBtTz4RN
  792. |sRYVXM3jyCbxj8uV+XNr+3OuQe5u7cV5gkXOXHqcNczOrxGzSXVGULuw8FiHIlhId7tot3dGdyVvWD9YIwwGA/9/3g8JixqpQHKZ
  793. |6YJAeqltydisGa3CIIEzBAh52GJC7yzMKSC2ZAtW0CgYEA6B/O+EgtZthiXOwivqZmKKGgWGLSOGjVsExSa1iiTTz3EFwcdD54mU
  794. |TKc6hw787NFlfN1m7B7EDQxIldRDI3One1q2dj87taco/qFqKsHuAuC3gmZIp2F4l2P8NpdHHFMzUzsfs+grY/wLHZiJdfOTdulA
  795. |s9go5mDloMC96n0/UCgYEA5IQo7c4ZxwhlssIn89XaOlKGoIct07wsBMu47HZYFqgG2/NUN8zRfSdSvot+6zinAb6Z3iGZ2FBL+C
  796. |MmoEMGwuXSQjWxeD//UU6V5AZqlgis5s9WakKWmkTkVV3bPSwW0DuNcqbMk7BxAXcQ6QGIiBtzeaPuL/3gzA9e9vm8xo8CgYEAqL
  797. |I9S6nA/UZzLg8bLS1nf03/Z1ziZMajzk2ZdJRk1/dfow8eSskAAnvBGo8nDNFhsUQ8vwOdgeKVFtCx7JcGFkLbz+cC+CaIFExNFw
  798. |hASOwp6oH2fQk3y+FGBA8ze8IXTCD1IftzMbHb4WIfsyo3tTB497S3jkOJHhMJQDMgC2UCgYEAzjUgRe98vWkrdFLWAKfSxFxiFg
  799. |vF49JjGnTHy8HDHbbEccizD6NoyvooJb/1aMd3lRBtAtDpZhSXaTQ3D9lMCaWfxZV0LyH5AGLcyaasmfT8KU+iGEM8abuPHCWUyC
  800. |+36nJC4tn3s7I9V2gdP1Xd4Yx7+KFgN7huGVYpiM61dasCgYAQs5mPHRBeU+BHtPRyaLHhYq+jjYeocwyOpfw5wkiH3jsyUWTK9+
  801. |GlAoV75SYvQVIQS0VH1C1/ajz9yV02frAaUXbGtZJbyeAcyy3DjCc7iF0swJ4slP3gGVJipVF4aQ0d9wMoJ7SBaaTR0ohXeUWmTT
  802. |X+VGf+cZQ2IefKVnz9mg==
  803. """.trimMargin()
  804. val decryptedFile = EncryptionUtilsV2().decryptFiledrop(sut, privateKey, arbitraryDataProvider, user)
  805. assertEquals("test.txt", decryptedFile.filename)
  806. }
  807. }