repo created
This commit is contained in:
commit
1ef725ef20
2483 changed files with 278273 additions and 0 deletions
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotEquals
|
||||
import org.junit.Test
|
||||
|
||||
class BitmapUtilsIT {
|
||||
@Test
|
||||
@Suppress("MagicNumber")
|
||||
fun usernameToColor() {
|
||||
assertEquals(BitmapUtils.Color(0, 0, 0), BitmapUtils.Color(0, 0, 0))
|
||||
assertEquals(BitmapUtils.Color(221, 203, 85), BitmapUtils.usernameToColor("User"))
|
||||
assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.usernameToColor("Admin"))
|
||||
assertEquals(BitmapUtils.Color(0, 130, 201), BitmapUtils.usernameToColor(""))
|
||||
assertEquals(BitmapUtils.Color(201, 136, 121), BitmapUtils.usernameToColor("68b329da9893e34099c7d8ad5cb9c940"))
|
||||
|
||||
// tests from server
|
||||
assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.usernameToColor("Alishia Ann Lowry"))
|
||||
assertEquals(BitmapUtils.Color(0, 130, 201), BitmapUtils.usernameToColor("Arham Johnson"))
|
||||
assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.usernameToColor("Brayden Truong"))
|
||||
assertEquals(BitmapUtils.Color(151, 80, 164), BitmapUtils.usernameToColor("Daphne Roy"))
|
||||
assertEquals(BitmapUtils.Color(195, 114, 133), BitmapUtils.usernameToColor("Ellena Wright Frederic Conway"))
|
||||
assertEquals(BitmapUtils.Color(214, 180, 97), BitmapUtils.usernameToColor("Gianluca Hills"))
|
||||
assertEquals(BitmapUtils.Color(214, 180, 97), BitmapUtils.usernameToColor("Haseeb Stephens"))
|
||||
assertEquals(BitmapUtils.Color(151, 80, 164), BitmapUtils.usernameToColor("Idris Mac"))
|
||||
assertEquals(BitmapUtils.Color(0, 130, 201), BitmapUtils.usernameToColor("Kristi Fisher"))
|
||||
assertEquals(BitmapUtils.Color(188, 92, 145), BitmapUtils.usernameToColor("Lillian Wall"))
|
||||
assertEquals(BitmapUtils.Color(221, 203, 85), BitmapUtils.usernameToColor("Lorelai Taylor"))
|
||||
assertEquals(BitmapUtils.Color(151, 80, 164), BitmapUtils.usernameToColor("Madina Knight"))
|
||||
assertEquals(BitmapUtils.Color(121, 90, 171), BitmapUtils.usernameToColor("Rae Hope"))
|
||||
assertEquals(BitmapUtils.Color(188, 92, 145), BitmapUtils.usernameToColor("Santiago Singleton"))
|
||||
assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.usernameToColor("Sid Combs"))
|
||||
assertEquals(BitmapUtils.Color(30, 120, 193), BitmapUtils.usernameToColor("Vivienne Jacobs"))
|
||||
assertEquals(BitmapUtils.Color(110, 166, 143), BitmapUtils.usernameToColor("Zaki Cortes"))
|
||||
assertEquals(BitmapUtils.Color(91, 100, 179), BitmapUtils.usernameToColor("a user"))
|
||||
assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.usernameToColor("admin"))
|
||||
assertEquals(BitmapUtils.Color(151, 80, 164), BitmapUtils.usernameToColor("admin@cloud.example.com"))
|
||||
assertEquals(BitmapUtils.Color(221, 203, 85), BitmapUtils.usernameToColor("another user"))
|
||||
assertEquals(BitmapUtils.Color(36, 142, 181), BitmapUtils.usernameToColor("asd"))
|
||||
assertEquals(BitmapUtils.Color(0, 130, 201), BitmapUtils.usernameToColor("bar"))
|
||||
assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.usernameToColor("foo"))
|
||||
assertEquals(BitmapUtils.Color(182, 70, 157), BitmapUtils.usernameToColor("wasd"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@Suppress("MagicNumber")
|
||||
fun checkEqual() {
|
||||
assertEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.Color(208, 158, 109))
|
||||
assertNotEquals(BitmapUtils.Color(208, 158, 109), BitmapUtils.Color(208, 158, 100))
|
||||
}
|
||||
|
||||
@Test
|
||||
@Suppress("MagicNumber")
|
||||
fun checkHashCode() {
|
||||
assertEquals(BitmapUtils.Color(208, 158, 109).hashCode(), BitmapUtils.Color(208, 158, 109).hashCode())
|
||||
assertNotEquals(BitmapUtils.Color(208, 158, 109).hashCode(), BitmapUtils.Color(208, 158, 100).hashCode())
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2022 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import com.owncloud.android.AbstractIT
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class DisplayUtilsIT : AbstractIT() {
|
||||
@Test
|
||||
fun testPixelToDP() {
|
||||
val px = 123
|
||||
val dp = DisplayUtils.convertPixelToDp(px, targetContext)
|
||||
val newPx = DisplayUtils.convertDpToPixel(dp, targetContext)
|
||||
|
||||
assertEquals(px.toLong(), newPx.toLong())
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2023 Alper Ozturk <alper_ozturk@proton.me>
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.junit.After
|
||||
import org.junit.Assert.fail
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class DrawableUtilTests {
|
||||
|
||||
private var sut: DrawableUtil? = null
|
||||
private var context: Context? = null
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
sut = DrawableUtil()
|
||||
context = InstrumentationRegistry.getInstrumentation().context
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAddDrawableAsOverlayWhenGivenValidDrawablesShouldContainTwoDrawable() {
|
||||
val bitmap: Bitmap = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888)
|
||||
val drawable = BitmapDrawable(context?.resources, bitmap)
|
||||
|
||||
val layerDrawable = sut?.addDrawableAsOverlay(drawable, drawable)
|
||||
|
||||
if (layerDrawable == null) {
|
||||
fail("Layer drawable expected to be not null")
|
||||
}
|
||||
|
||||
assert(layerDrawable?.numberOfLayers == 2)
|
||||
}
|
||||
|
||||
@After
|
||||
fun destroy() {
|
||||
sut = null
|
||||
context = null
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2023 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedFile
|
||||
import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedFolderMetadataFile
|
||||
import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedMetadata
|
||||
import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedUser
|
||||
import com.owncloud.android.lib.resources.status.E2EVersion
|
||||
|
||||
class EncryptionTestUtils {
|
||||
val t1PrivateKey =
|
||||
"MIIEugIBADANBgkqhkiG9w0BAQEFAASCBKQwggSgAgEAAoIBAQC1p8eYMFwGoi7geYzEwNbePRLL5LRhorAecFG3zkpLBwSi/QHkU4" +
|
||||
"u4uSegEbHgOfe73eKVOFdfFpw8wd5cvtY+4CzbX8bu+yrC+tFGcJ25/4VQ78Bl4MI0SvOmxDwuZNrg9SWgs9RwialKOsfCEyz0" +
|
||||
"SS8RstGNt5KZKn1e8z7V9X/eORPmOQ5KcIXHlMbAY3m4erBSKvhRZdqy+Dbnc0rZeZaKkoIMJH1OYfVto/ek12iIKF2YStPVzo" +
|
||||
"TgNsFelPDxeA/lltgf6qDVRD+ELydEncPIJwcv52D8ZitoEyEOfjDZW+rvvE02g1ZD1xPkDLpwltAsFCglCKvKBAWuhthFAgMB" +
|
||||
"AAECgf8BN1MLcq+6m8C1tzNvN/UDd9c0rUpexM6D5eC4O+6B7YGidEqIhHVIzUj0e2HUgpRBbURxsvF1FWdIT2gu7dnULtOGWQ" +
|
||||
"xNujJ0kGwXfAnqxh/rACDFb5TS3sJawEExC5yJw14bCEbE/0uBF5uiTU/U9AV7PKHlqAKsS2RtcwPNceB8zDu0hh/Mb/uS7274" +
|
||||
"TsxUllx0WzGZrozO1K6AlOete9rXmmpghpFTNVhxgf0pxe3hrK+tZGSL9di+Wft9eCvSbdG/FzeXgwVqmGtWU7kSB7FqstEEJO" +
|
||||
"4VpOSyEfcXGHTHwdZjrhBUuAcjWE8E0mCKa8htRE52czb3C0f7ZYkCgYEA5eH3vmHEgQjXzSSEtbmDLRq9X9SB7pIAIXHj2UuE" +
|
||||
"OTkLUJ/7xLTHqt82jqZaZzns1RZIJXKZjH85CswQp/py2/qD240KvA/N+ELZaciaV+Wg+m4+iHdi0DyPkaKaBtFG1nsR2GbVWO" +
|
||||
"1OsaTUZTG4D7RCUErU6XVmNPQKSk5uRA0CgYEAykskpX3KKuWq5nxV4vwgPmxz+uAfCtaGhcPEUg764SR+n0ODAvGiEJU7B0Q2" +
|
||||
"oX621pDOQeRfFufiMWfD8ByhErs1HFCmW69YPlR8qamfc8tHG5UM+r3bb49sDEYU4qr1Ji5Zzs4XgfmToKLbWdzzhaW6YxqO7N" +
|
||||
"ntIIh2169PPxkCgYBF2TAWl8xGTLKNcYAlW1XBObO6z24fWBtUDi/mEWz+mheXCtVMAoX8pFAGbgNgBBiy8k8/mZ+QMgPaBQE2" +
|
||||
"mQGXV3oDFsrhM4go298Fpl9HP8126lJz0pqinRQecyKL2cDFYKWedDh1Cb30ehnTGZVMqD/R97rTqMlCY7hQtZ4JbQKBgEXpLD" +
|
||||
"QJQeoLT0GybJgyXA5WuspT1EaRlxH5cwqM5MUUMLJnyYol6cVjXXAIcfzj5tpGVxHMk9Q9tR0v6DY+HqhzjEpJ0QRUl+GKnz6f" +
|
||||
"QVzqPpvYqhCptoFahpPDUIp5XJmiYSUoclVX5F4aikYHJx3kBYMkdYqDUgDxSGkHzBJZAoGAHV44xgTW02dgeB5GfDJVWCJKAU" +
|
||||
"GsYOFuUehKUBXSJ0929hdP0sjOQDJN3DEDISzmgdWX5NyLJxEYgFWNivpePjWCWzOzyua3nPSpvxPIUB7xh27gjT91glj1hEmy" +
|
||||
"sCd7+9yoMPiCXR7iigRycxegI/Krd39QzISSk9O0finfytU="
|
||||
|
||||
val t1PublicKey = """-----BEGIN CERTIFICATE-----
|
||||
MIIC6DCCAdCgAwIBAgIBADANBgkqhkiG9w0BAQUFADANMQswCQYDVQQDDAJ0MTAe
|
||||
Fw0yMzA3MjUwNzU3MTJaFw00MzA3MjAwNzU3MTJaMA0xCzAJBgNVBAMMAnQxMIIB
|
||||
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtafHmDBcBqIu4HmMxMDW3j0S
|
||||
y+S0YaKwHnBRt85KSwcEov0B5FOLuLknoBGx4Dn3u93ilThXXxacPMHeXL7WPuAs
|
||||
21/G7vsqwvrRRnCduf+FUO/AZeDCNErzpsQ8LmTa4PUloLPUcImpSjrHwhMs9Ekv
|
||||
EbLRjbeSmSp9XvM+1fV/3jkT5jkOSnCFx5TGwGN5uHqwUir4UWXasvg253NK2XmW
|
||||
ipKCDCR9TmH1baP3pNdoiChdmErT1c6E4DbBXpTw8XgP5ZbYH+qg1UQ/hC8nRJ3D
|
||||
yCcHL+dg/GYraBMhDn4w2Vvq77xNNoNWQ9cT5Ay6cJbQLBQoJQirygQFrobYRQID
|
||||
AQABo1MwUTAdBgNVHQ4EFgQUE9zCeA9/QMAtVgLxD23X6ZcodhMwHwYDVR0jBBgw
|
||||
FoAUE9zCeA9/QMAtVgLxD23X6ZcodhMwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
|
||||
9w0BAQUFAAOCAQEAZdy/YjJlvnz3FQwxp6oVtMJccpdxveEPfLzgaverhtd/vP8O
|
||||
AvDzOLgQJHmrDS91SG503eU4cYGyuNKwd77OyTnqMg+GUEmJhGfPpSVrEIdh65jv
|
||||
q61T4oqBdehevVmBq54rGiwL0DGv1DlXQlwiJZP4qni2KnOEFcnvL3gVtRnQjXQ+
|
||||
kHvlMshkK6w021EMV5NfjG2zg67wC65rLaej5f6Ssp2S7g2VtmE4aXq1bjAuEbqk
|
||||
4TiyZHLDdsJuqzyGyyOpMV7i9ucXDoaZt9cGS9hT2vRxTrSH63vKR8Xeig9+stLw
|
||||
t9ONcUqCKP7hd8rajtxM4JIIRExwD8OkgARWGg==
|
||||
-----END CERTIFICATE-----"""
|
||||
|
||||
val johnPrivateKey =
|
||||
"""MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDuPcSvlhqElPQsCdJEuGmptGj4TUBWe33yu+ncOYR8Ec3M0H4NL0gE
|
||||
|ORJJcz9i18ByLpNzDy6NUGOtlf9YSat/zKdAfFiZJolKc/y4BPfTr8xx5ml2mu4Rz39LXRru+nnhluV3g1h2Z9LvWhUVUqAztz9W2H
|
||||
|H6uC7jx+7HNtYC9VgsVzHjuHPQMlOePPZlr9Hry5enF/Psn24RdiKqwCz8WhsOwtmW5PdHLLBVHAoF53URnFR4sgmLLGlS2GEZ8hvx
|
||||
|vdV/2NmhRWLebmCZziyklAe9gCR9lgfN32tqzyMG7VptBHFy7YJidWjpjSZPGEqFBL+fmCO/cTGJAXfCn9djAgMBAAECggEAV2QBCg
|
||||
|edopShHKZdoyeiWsX621o7B341LR0RI99VYc2GGGNCWcPGPwZQVvEXh0JtLXU4UTR4dw3OApbLG6+qYS7JCzaRqVwhcFYrlbT804Hh
|
||||
|FMbYWNFsEsxyfUqh3peyrbWUZsqfYI+lKHd61F+CtHW7nje3V6jISnXEeP78cgioKOX8gsCG8DEWsmaLrQz0PyMwdhucRfa8Bm6qeX
|
||||
|NY+wCMg8lyH/+OLlyCZTdkaWbTBBD5UXGbZly8iX17McmsYhdjFyx1l0NQnVMAYjOpXXEkeEixZpSfm3GYxmdaQqZFkpbI/FbQF0yD
|
||||
|7hLrGwiRTDcyPUz+QypUv8CZxpXbgQKBgQD3btuYmb+BpPZjryfa3worv/3XQCTs08V0TX3mDxHVQL95TgP+L8/Z/brxIMBNpwG1wk
|
||||
|iCWLYLer68+qioMTohuzeUx7hRKcoHa9ezW8m7m9AcPmAnzNticPYv835BQjEu/avU98rwIDihsYgxcjU3L7/P2ajVgUDigQxmE3gO
|
||||
|OwKBgQD2fXBLwch0P5g2GCyOPYvSgyF/umS7mcyUVTE4WOoJNDf8Q+Bx1dA2yAKQaoVghqW4uCfOAo/rERvGAYZ7fm7nFwx1jZ8ToT
|
||||
|dKZwybIFPjF/zkfuZLajYxVOPnzuQrsXnjcGg/ltMKZg3NqnGQGnD1S3eOhZ+dIOBmb7+jSO4A+QKBgASqnpGeNLJpPgxbPVEva62v
|
||||
|jUYF+6xLwimTXJB+MEPpWLMc+Y5NsInX8zKg/393atzWsS9kJOrKgdZmk8+4PfRs53ty2NMPCrRhIExNqtxS7/XYZ0/Y2TpeDwaQfQ
|
||||
|0WBn9wYVE+6yDkOq0x//OOx9ommGN/I2QDcAnVjTpPm7AJAoGAYT8cDsdlTnfIlY70BSpC/8q8bKgdFeaXz+3MfW6W5wqzC9O7uS2h
|
||||
|9/rxCAj+lhaJS1dcXOql3Rfi3Tu80vwOxR1SzQ4StKvmJHSDhLA8aFwOahemxBojR1M2lz4IxzQ94n12o5/dozygNYQJSdEkv6IGiT
|
||||
|QuxM8zuTZdZQ5g2AECgYAujetfkwgVW7/gumpMKytoY0VuTzF4Y/XZfqBMVIiPIuUl57JbDzrcx6YVXX3PavxNWmBLBmMq3SHMbdva
|
||||
|H7LnU/8rvkT8xRVLg/w/bRJc3Lb3oUjrdhkUQUYDoOfMoFA+ceZ2L6bnSXwm86KKV+xoXWpxAoL4AvdNrMhoWw3+yg=="""
|
||||
.trimMargin()
|
||||
|
||||
val johnPublicKey = """-----BEGIN CERTIFICATE-----
|
||||
MIIDkDCCAnigAwIBAgIBADANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJERTEb
|
||||
MBkGA1UECAwSQmFkZW4tV3VlcnR0ZW1iZXJnMRIwEAYDVQQHDAlTdHV0dGdhcnQx
|
||||
EjAQBgNVBAoMCU5leHRjbG91ZDENMAsGA1UEAwwEam9objAeFw0yMzA3MTQwNzM0
|
||||
NTZaFw00MzA3MDkwNzM0NTZaMGExCzAJBgNVBAYTAkRFMRswGQYDVQQIDBJCYWRl
|
||||
bi1XdWVydHRlbWJlcmcxEjAQBgNVBAcMCVN0dXR0Z2FydDESMBAGA1UECgwJTmV4
|
||||
dGNsb3VkMQ0wCwYDVQQDDARqb2huMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEA7j3Er5YahJT0LAnSRLhpqbRo+E1AVnt98rvp3DmEfBHNzNB+DS9IBDkS
|
||||
SXM/YtfAci6Tcw8ujVBjrZX/WEmrf8ynQHxYmSaJSnP8uAT306/MceZpdpruEc9/
|
||||
S10a7vp54Zbld4NYdmfS71oVFVKgM7c/Vthx+rgu48fuxzbWAvVYLFcx47hz0DJT
|
||||
njz2Za/R68uXpxfz7J9uEXYiqsAs/FobDsLZluT3RyywVRwKBed1EZxUeLIJiyxp
|
||||
UthhGfIb8b3Vf9jZoUVi3m5gmc4spJQHvYAkfZYHzd9ras8jBu1abQRxcu2CYnVo
|
||||
6Y0mTxhKhQS/n5gjv3ExiQF3wp/XYwIDAQABo1MwUTAdBgNVHQ4EFgQUmTeILVuB
|
||||
tv70fTGkXWGAueDp5kAwHwYDVR0jBBgwFoAUmTeILVuBtv70fTGkXWGAueDp5kAw
|
||||
DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAyVtq9XAvW7nxSW/8
|
||||
hp30z6xbzGiuviXhy/Jo91VEa8IRsWCCn3OmDFiVduTEowx76tf8clJP0gk7Pozi
|
||||
6dg/7Fin+FqQGXfCk8bLAh9gXKAikQ2GK8yRN3slRFwYC2mm23HrLdKXZHUqJcpB
|
||||
Mz2zsSrOGPj1YsYOl/U8FU6KA7Yj7U3q7kDMYTAgzUPZAH+d1DISGWpZsMa0RYid
|
||||
vigCCLByiccmS/Co4Sb1esF58H+YtV5+nFBRwx881U2g2TgDKF1lPMK/y3d8B8mh
|
||||
UtW+lFxRpvyNUDpsMjOErOrtNFEYbgoUJLtqwBMmyGR+nmmh6xna331QWcRAmw0P
|
||||
nDO4ew==
|
||||
-----END CERTIFICATE-----"""
|
||||
|
||||
@Throws(java.lang.Exception::class)
|
||||
fun generateFolderMetadataV2(userId: String, cert: String): DecryptedFolderMetadataFile {
|
||||
val metadata = DecryptedMetadata().apply {
|
||||
metadataKey = EncryptionUtils.generateKey()
|
||||
keyChecksums.add(EncryptionUtilsV2().hashMetadataKey(metadataKey))
|
||||
}
|
||||
|
||||
val file1 = DecryptedFile(
|
||||
"image1.png",
|
||||
"image/png",
|
||||
"gKm3n+mJzeY26q4OfuZEqg==",
|
||||
"PboI9tqHHX3QeAA22PIu4w==",
|
||||
"WANM0gRv+DhaexIsI0T3Lg=="
|
||||
)
|
||||
|
||||
val file2 = DecryptedFile(
|
||||
"image2.png",
|
||||
"image/png",
|
||||
"hnJLF8uhDvDoFK4ajuvwrg==",
|
||||
"qOQZdu5soFO77Y7y4rAOVA==",
|
||||
"9dfzbIYDt28zTyZfbcll+g=="
|
||||
)
|
||||
|
||||
val users = mutableListOf(
|
||||
DecryptedUser(userId, cert)
|
||||
)
|
||||
|
||||
// val filedrop = mutableMapOf(
|
||||
// Pair(
|
||||
// "eie8iaeiaes8e87td6",
|
||||
// DecryptedFile(
|
||||
// "test2.txt",
|
||||
// "txt/plain",
|
||||
// "hnJLF8uhDvDoFK4ajuvwrg==",
|
||||
// "qOQZdu5soFO77Y7y4rAOVA==",
|
||||
// "9dfzbIYDt28zTyZfbcll+g=="
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
|
||||
metadata.files["ia7OEEEyXMoRa1QWQk8r"] = file1
|
||||
metadata.files["n9WXAIXO2wRY4R8nXwmo"] = file2
|
||||
|
||||
return DecryptedFolderMetadataFile(metadata, users, mutableMapOf(), E2EVersion.V2_0.value)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2023 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import com.owncloud.android.EncryptionIT
|
||||
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl
|
||||
import com.owncloud.android.datamodel.e2e.v1.decrypted.Data
|
||||
import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile
|
||||
import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFolderMetadataFileV1
|
||||
import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedMetadata
|
||||
import com.owncloud.android.lib.resources.e2ee.CsrHelper
|
||||
import com.owncloud.android.operations.RefreshFolderOperation
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class EncryptionUtilsIT : EncryptionIT() {
|
||||
@Throws(
|
||||
java.security.NoSuchAlgorithmException::class,
|
||||
java.io.IOException::class,
|
||||
org.bouncycastle.operator.OperatorCreationException::class
|
||||
)
|
||||
@Test
|
||||
fun saveAndRestorePublicKey() {
|
||||
val arbitraryDataProvider = ArbitraryDataProviderImpl(targetContext)
|
||||
val keyPair = EncryptionUtils.generateKeyPair()
|
||||
val e2eUser = "e2e-user"
|
||||
val key = CsrHelper().generateCsrPemEncodedString(keyPair, e2eUser)
|
||||
|
||||
EncryptionUtils.savePublicKey(user, key, e2eUser, arbitraryDataProvider)
|
||||
|
||||
assertEquals(key, EncryptionUtils.getPublicKey(user, e2eUser, arbitraryDataProvider))
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testUpdateFileNameForEncryptedFileV1() {
|
||||
val folder = testFolder()
|
||||
|
||||
val decryptedFilename = "image.png"
|
||||
val mockEncryptedFilename = "encrypted_file_name.png"
|
||||
|
||||
val decryptedMetadata = DecryptedMetadata()
|
||||
val filesData = DecryptedFile().apply {
|
||||
encrypted = Data().apply {
|
||||
filename = decryptedFilename
|
||||
}
|
||||
}
|
||||
val files = mapOf(mockEncryptedFilename to filesData)
|
||||
val metadata = DecryptedFolderMetadataFileV1(decryptedMetadata, files)
|
||||
|
||||
RefreshFolderOperation.updateFileNameForEncryptedFileV1(storageManager, metadata, folder)
|
||||
assertEquals(folder.decryptedRemotePath.contains("null"), false)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,913 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2023 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.nextcloud.client.account.MockUser
|
||||
import com.nextcloud.common.User
|
||||
import com.owncloud.android.EncryptionIT
|
||||
import com.owncloud.android.datamodel.OCFile
|
||||
import com.owncloud.android.datamodel.e2e.v1.decrypted.Data
|
||||
import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFolderMetadataFileV1
|
||||
import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedFile
|
||||
import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedFolderMetadataFile
|
||||
import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedMetadata
|
||||
import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedUser
|
||||
import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFiledrop
|
||||
import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFiledropUser
|
||||
import com.owncloud.android.datamodel.e2e.v2.encrypted.EncryptedFolderMetadataFile
|
||||
import com.owncloud.android.operations.RefreshFolderOperation
|
||||
import com.owncloud.android.util.EncryptionTestIT
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import org.junit.Assert.assertNotEquals
|
||||
import org.junit.Test
|
||||
|
||||
@Suppress("TooManyFunctions", "LargeClass")
|
||||
class EncryptionUtilsV2IT : EncryptionIT() {
|
||||
private val encryptionTestUtils = EncryptionTestUtils()
|
||||
private val encryptionUtilsV2 = EncryptionUtilsV2()
|
||||
|
||||
private val enc1UserId = "enc1"
|
||||
private val enc1PrivateKey = """
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAo
|
||||
IBAQDsn0JKS/THu328z1IgN0VzYU53HjSX03WJIgWkmyTaxbiKpoJaKbksXmfSpgzV
|
||||
GzKFvGfZ03fwFrN7Q8P8R2e8SNiell7mh1TDw9/0P7Bt/ER8PJrXORo+GviKHxaLr7
|
||||
Y0BJX9i/nW/L0L/VaE8CZTAqYBdcSJGgHJjY4UMf892ZPTa9T2Dl3ggdMZ7BQ2kiCi
|
||||
CC3qV99b0igRJGmmLQaGiAflhFzuDQPMifUMq75wI8RSRPdxUAtjTfkl68QHu7Umye
|
||||
yy33OQgdUKaTl5zcS3VSQbNjveVCNM4RDH1RlEc+7Wf1BY8APqT6jbiBcROJD2CeoL
|
||||
H2eiIJCi+61ZkSGfAgMBAAECggEBALFStCHrhBf+GL9a+qer4/8QZ/X6i91PmaBX/7
|
||||
SYk2jjjWVSXRNmex+V6+Y/jBRT2mvAgm8J+7LPwFdatE+lz0aZrMRD2gCWYF6Itpda
|
||||
90OlLkmQPVWWtGTgX2ta2tF5r2iSGzk0IdoL8zw98Q2UzpOcw30KnWtFMxuxWk0mHq
|
||||
pgp00g80cDWg3+RPbWOhdLp5bflQ36fKDfmjq05cGlIk6unnVyC5HXpvh4d4k2EWlX
|
||||
rjGsndVBPCjGkZePlLRgDHxT06r+5XdJ+1CBDZgCsmjGz3M8uOHyCfVW0WhB7ynzDT
|
||||
agVgz0iqpuhAi9sPt6iWWwpAnRw8cQgqEKw9bvKKECgYEA/WPi2PJtL6u/xlysh/H7
|
||||
A717CId6fPHCMDace39ZNtzUzc0nT5BemlcF0wZ74NeJSur3Q395YzB+eBMLs5p8mA
|
||||
95wgGvJhM65/J+HX+k9kt6Z556zLMvtG+j1yo4D0VEwm3xahB4SUUP+1kD7dNvo4+8
|
||||
xeSCyjzNllvYZZC0DrECgYEA7w8pEqhHHn0a+twkPCZJS+gQTB9Rm+FBNGJqB3XpWs
|
||||
TeLUxYRbVGk0iDve+eeeZ41drxcdyWP+WcL34hnrjgI1Fo4mK88saajpwUIYMy6+qM
|
||||
LY+jC2NRSBox56eH7nsVYvQQK9eKqv9wbB+PF9SwOIvuETN7fd8mAY02UnoaaU8CgY
|
||||
BoHRKocXPLkpZJuuppMVQiRUi4SHJbxDo19Tp2w+y0TihiJ1lvp7I3WGpcOt3LlMQk
|
||||
tEbExSvrRZGxZKH6Og/XqwQsYuTEkEIz679F/5yYVosE6GkskrOXQAfh8Mb3/04xVV
|
||||
tMaVgDQw0+CWVD4wyL+BNofGwBDNqsXTCdCsfxAQKBgQCDv2EtbRw0y1HRKv21QIxo
|
||||
ju5cZW4+cDfVPN+eWPdQFOs1H7wOPsc0aGRiiupV2BSEF3O1ApKziEE5U1QH+29bR4
|
||||
R8L1pemeGX8qCNj5bCubKjcWOz5PpouDcEqimZ3q98p3E6GEHN15UHoaTkx0yO/V8o
|
||||
j6zhQ9fYRxDHB5ACtQKBgQCOO7TJUO1IaLTjcrwS4oCfJyRnAdz49L1AbVJkIBK0fh
|
||||
JLecOFu3ZlQl/RStQb69QKb5MNOIMmQhg8WOxZxHcpmIDbkDAm/J/ovJXFSoBdOr5o
|
||||
uQsYsDZhsWW97zvLMzg5pH9/3/1BNz5q3Vu4HgfBSwWGt4E2NENj+XA+QAVmGA==
|
||||
""".trimIndent()
|
||||
|
||||
private val enc1Cert = """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDpzCCAo+gAwIBAgIBADANBgkqhkiG9w0BAQUFADBuMRowGAYDVQQDDBF3d3cu
|
||||
bmV4dGNsb3VkLmNvbTESMBAGA1UECgwJTmV4dGNsb3VkMRIwEAYDVQQHDAlTdHV0
|
||||
dGdhcnQxGzAZBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzELMAkGA1UEBhMCREUw
|
||||
HhcNMTcwOTI2MTAwNDMwWhcNMzcwOTIxMTAwNDMwWjBuMRowGAYDVQQDDBF3d3cu
|
||||
bmV4dGNsb3VkLmNvbTESMBAGA1UECgwJTmV4dGNsb3VkMRIwEAYDVQQHDAlTdHV0
|
||||
dGdhcnQxGzAZBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzELMAkGA1UEBhMCREUw
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDsn0JKS/THu328z1IgN0Vz
|
||||
YU53HjSX03WJIgWkmyTaxbiKpoJaKbksXmfSpgzVGzKFvGfZ03fwFrN7Q8P8R2e8
|
||||
SNiell7mh1TDw9/0P7Bt/ER8PJrXORo+GviKHxaLr7Y0BJX9i/nW/L0L/VaE8CZT
|
||||
AqYBdcSJGgHJjY4UMf892ZPTa9T2Dl3ggdMZ7BQ2kiCiCC3qV99b0igRJGmmLQaG
|
||||
iAflhFzuDQPMifUMq75wI8RSRPdxUAtjTfkl68QHu7Umyeyy33OQgdUKaTl5zcS3
|
||||
VSQbNjveVCNM4RDH1RlEc+7Wf1BY8APqT6jbiBcROJD2CeoLH2eiIJCi+61ZkSGf
|
||||
AgMBAAGjUDBOMB0GA1UdDgQWBBTFrXz2tk1HivD9rQ75qeoyHrAgIjAfBgNVHSME
|
||||
GDAWgBTFrXz2tk1HivD9rQ75qeoyHrAgIjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3
|
||||
DQEBBQUAA4IBAQARQTX21QKO77gAzBszFJ6xVnjfa23YZF26Z4X1KaM8uV8TGzuN
|
||||
JA95XmReeP2iO3r8EWXS9djVCD64m2xx6FOsrUI8HZaw1JErU8mmOaLAe8q9RsOm
|
||||
9Eq37e4vFp2YUEInYUqs87ByUcA4/8g3lEYeIUnRsRsWsA45S3wD7wy07t+KAn7j
|
||||
yMmfxdma6hFfG9iN/egN6QXUAyIPXvUvlUuZ7/BhWBj/3sHMrF9quy9Q2DOI8F3t
|
||||
1wdQrkq4BtStKhciY5AIXz9SqsctFHTv4Lwgtkapoel4izJnO0ZqYTXVe7THwri9
|
||||
H/gua6uJDWH9jk2/CiZDWfsyFuNUuXvDSp05
|
||||
-----END CERTIFICATE-----
|
||||
""".trimIndent()
|
||||
|
||||
private val enc2Cert = """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC7DCCAdSgAwIBAgIBADANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDDARlbmMz
|
||||
MB4XDTIwMDcwODA3MzE1OFoXDTQwMDcwMzA3MzE1OFowDzENMAsGA1UEAwwEZW5j
|
||||
MzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAI/83eC/EF3xOocwjO+Z
|
||||
ZkPc1TFxt3aUgjEvrpZu45LOqesG67kkkVDYgjeg3Biz9XRUQXqtXaAyxRZH8GiH
|
||||
PFyKUiP1bUlCptd8X+hk9vxeN25YS5OS2RrxU9tDQ/dVOHr20427UvVCighotQnR
|
||||
/6+md1FQMV92PFxji7OP5TWOE1y389X6eb7kSPLs8Tu+2PpqaNVQ9C/89Y8KNYWs
|
||||
x9Zo+kbQhjfFFUikEpkuzMgT9QLaeq6xuXIPP+y1tzNmF6NTL0a2GoYULuxYWnCe
|
||||
joFyXj77LuLmK+KXfPdhvlxa5Kl9XHSxKPHBVVQpwPqNMT+b2T1VLE2l7M9NfImy
|
||||
iLcCAwEAAaNTMFEwHQYDVR0OBBYEFBKubDeR2lXwuyTrdyv6O7euPS4PMB8GA1Ud
|
||||
IwQYMBaAFBKubDeR2lXwuyTrdyv6O7euPS4PMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
|
||||
KoZIhvcNAQEFBQADggEBAChCOIH8CkEpm1eqjsuuNPa93aduLjtnZXat5eIKsKCl
|
||||
rL9nFslpg/DO5SeU5ynPY9F2QjX5CN/3RxDXum9vFfpXhTJphOv8N0uHU4ucmQxE
|
||||
DN388Vt5VtN3V2pzNUL3JSiG6qeYG047/r/zhGFVpcgb2465G5mEwFT0qnkEseCC
|
||||
VVZ63GN8hZgUobyRXxMIhkfWlbO1dgABB4VNyudq0CW8urmewkkbUBwCslvtUvPM
|
||||
WuzpQjq2A80bvbrAqO5VUfvMcqRiUWkDgfa6cHXyV0o4N11mMIoxsMgh+PFYr6lR
|
||||
BHkuQHqKEwP8kkWugIFj3TMcy9dYtXfMXWvzFaDoE4s=
|
||||
-----END CERTIFICATE-----
|
||||
""".trimIndent()
|
||||
|
||||
private val enc2PrivateKey = """
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCP/N3gvxBd8TqH
|
||||
MIzvmWZD3NUxcbd2lIIxL66WbuOSzqnrBuu5JJFQ2II3oNwYs/V0VEF6rV2gMsUW
|
||||
R/BohzxcilIj9W1JQqbXfF/oZPb8XjduWEuTktka8VPbQ0P3VTh69tONu1L1QooI
|
||||
aLUJ0f+vpndRUDFfdjxcY4uzj+U1jhNct/PV+nm+5Ejy7PE7vtj6amjVUPQv/PWP
|
||||
CjWFrMfWaPpG0IY3xRVIpBKZLszIE/UC2nqusblyDz/stbczZhejUy9GthqGFC7s
|
||||
WFpwno6Bcl4++y7i5ivil3z3Yb5cWuSpfVx0sSjxwVVUKcD6jTE/m9k9VSxNpezP
|
||||
TXyJsoi3AgMBAAECggEACWwKFtlZ2FPfORZ3unwGwZ0TRFOFJljMdiyBF6307Vfh
|
||||
rZP729clPS2Vw88eZ+1qu+yBhmYO0NtRo0Yc2LI0xHd2rYyzVI5sfYBRhFMLCHOf
|
||||
2/QiKet7knRFQP1TVr14Xy+Eo2slIBB1GNzFL/nSaeuSNjtxp6YEiCUpcJwTayAi
|
||||
Squ5QWMxhlciLKvwUkraFRBqkugvMz3jXzuk/i+DcYlOgoj+tytweNn/azOMH9MH
|
||||
mWI+3owYspjzE1rVpbrcWImvlnbInd0z9KaQPpBf7Njj7wtyBMaYww4K4GCMhboD
|
||||
SQCYgpnznWkPIN3jyXtmNVSsZ1nvD+Laod+0p7giOQKBgQDA6KEKctYpbt051yTe
|
||||
2UP8hpq+MUSS7FIXiHlUc8s0PSujouypUyzfrPeL6yquI0GtKHkMVCWwfT+otMZR
|
||||
VnklofrmPTPovvsUQFM4Di411NZwzfxEbBFyVXAUWcLd9NxJ1hZW7w+hLk/N5Bej
|
||||
DOa2CncZmifyMNIlvIn7T1vDyQKBgQC/FE8HaDBoN98m/3rEjx7/rVtX8dCei5By
|
||||
Fzg/yQ2u4ELbf/Qk/n4k75sy0690EwnFdJxVn2gdNgS1YDv8YP/N5Wfq8xnX9V9B
|
||||
irWY/W24cN2qDNXm5i8o5wklyt+fDVqMcEHFfONUpLC+RYmOdc1rrFxPaQOYYYpp
|
||||
dWsnuG0ofwKBgBm6rUf8ew35qG3/gP5sEgJLXbZCUfgapvRWkoAuFYs5IWno4BHR
|
||||
cym+IyI5Um75atgSjtqTGpfIjMYOnmjY1L2tNg6hWRwQ5OIVlkPiuE0bvyI6hwwF
|
||||
MeqC9LjyI+iAsSTz9fTQW9BOofw/ENwBa4AaMzpp8iv+UPkRhYHMWtvpAoGAX6As
|
||||
RMqxnxaHCR9GM2Rk4RPC6OpNu2qhKVfRgKp/vIrjKrKIXpM2UgnPo8oovnBgrX7E
|
||||
Vl1mX2gPRy4YFx/8JPCv5vcucdOMjmJ6q0v5QxrI9DdkPR/pbhDhlRZIf3LRZAMy
|
||||
B0GPC2c4RKDMTI1L9pzVvbASaoo2GLz4mXJEvsUCgYEAibwFNXz1H52sZtL6/1zQ
|
||||
1rHCTS8qkryBhxl5eYa6MV5YkbLJZZstF0w2nLxkPba8NttS/nJqjX/iJobD5uLb
|
||||
UzeD8jMeAWPNt4DZCtA4ossNYcXIMKqBVFKOANMvAAvLMpVdlNYSucNnTSQcLwI6
|
||||
2J9mW5WvAAaG+j28Q/GKSuE=
|
||||
""".trimIndent()
|
||||
|
||||
@Test
|
||||
fun testEncryptDecryptMetadata() {
|
||||
val metadataKey = EncryptionUtils.generateKey()
|
||||
|
||||
val metadata = DecryptedMetadata(
|
||||
mutableListOf("hash1", "hash of key 2"),
|
||||
false,
|
||||
1,
|
||||
mutableMapOf(
|
||||
Pair(EncryptionUtils.generateUid(), "Folder 1"),
|
||||
Pair(EncryptionUtils.generateUid(), "Folder 2"),
|
||||
Pair(EncryptionUtils.generateUid(), "Folder 3")
|
||||
),
|
||||
mutableMapOf(
|
||||
Pair(
|
||||
EncryptionUtils.generateUid(),
|
||||
DecryptedFile(
|
||||
"file 1.png",
|
||||
"image/png",
|
||||
"initializationVector",
|
||||
"authenticationTag",
|
||||
"key 1"
|
||||
)
|
||||
),
|
||||
Pair(
|
||||
EncryptionUtils.generateUid(),
|
||||
DecryptedFile(
|
||||
"file 2.png",
|
||||
"image/png",
|
||||
"initializationVector 2",
|
||||
"authenticationTag 2",
|
||||
"key 2"
|
||||
)
|
||||
)
|
||||
),
|
||||
metadataKey
|
||||
)
|
||||
val encrypted = encryptionUtilsV2.encryptMetadata(metadata, metadataKey)
|
||||
val decrypted = encryptionUtilsV2.decryptMetadata(encrypted, metadataKey)
|
||||
|
||||
assertEquals(metadata, decrypted)
|
||||
}
|
||||
|
||||
@Throws(Throwable::class)
|
||||
@Test
|
||||
fun encryptDecryptSymmetric() {
|
||||
val string = "123"
|
||||
val metadataKey = EncryptionUtils.generateKeyString()
|
||||
|
||||
val e = EncryptionUtils.encryptStringSymmetricAsString(
|
||||
string,
|
||||
metadataKey.toByteArray()
|
||||
)
|
||||
|
||||
val d = EncryptionUtils.decryptStringSymmetric(e, metadataKey.toByteArray())
|
||||
assertEquals(string, d)
|
||||
|
||||
val encryptedMetadata = EncryptionUtils.encryptStringSymmetric(
|
||||
string,
|
||||
metadataKey.toByteArray(),
|
||||
EncryptionUtils.ivDelimiter
|
||||
)
|
||||
|
||||
val d2 = EncryptionUtils.decryptStringSymmetric(
|
||||
encryptedMetadata.ciphertext,
|
||||
metadataKey.toByteArray()
|
||||
)
|
||||
assertEquals(string, d2)
|
||||
|
||||
val decrypted = EncryptionUtils.decryptStringSymmetric(
|
||||
encryptedMetadata.ciphertext,
|
||||
metadataKey.toByteArray(),
|
||||
encryptedMetadata.authenticationTag,
|
||||
encryptedMetadata.nonce
|
||||
)
|
||||
|
||||
assertEquals(string, EncryptionUtils.decodeBase64BytesToString(decrypted))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEncryptDecryptUser() {
|
||||
val metadataKeyBase64 = EncryptionUtils.generateKeyString()
|
||||
val metadataKey = EncryptionUtils.decodeStringToBase64Bytes(metadataKeyBase64)
|
||||
|
||||
val user = DecryptedUser("t1", encryptionTestUtils.t1PublicKey)
|
||||
|
||||
val encryptedUser = encryptionUtilsV2.encryptUser(user, metadataKey)
|
||||
assertNotEquals(encryptedUser.encryptedMetadataKey, metadataKeyBase64)
|
||||
|
||||
val decryptedMetadataKey = encryptionUtilsV2.decryptMetadataKey(encryptedUser, encryptionTestUtils.t1PrivateKey)
|
||||
val decryptedMetadataKeyBase64 = EncryptionUtils.encodeBytesToBase64String(decryptedMetadataKey)
|
||||
|
||||
assertEquals(metadataKeyBase64, decryptedMetadataKeyBase64)
|
||||
}
|
||||
|
||||
@Throws(com.owncloud.android.operations.UploadException::class, Throwable::class)
|
||||
@Test
|
||||
fun testEncryptDecryptMetadataFile() {
|
||||
val enc1 = MockUser("enc1", "Nextcloud")
|
||||
|
||||
val root = OCFile("/")
|
||||
storageManager.saveFile(root)
|
||||
|
||||
val folder = OCFile("/enc/").apply {
|
||||
parentId = storageManager.getFileByDecryptedRemotePath("/")?.fileId ?: throw IllegalStateException()
|
||||
}
|
||||
|
||||
val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
|
||||
|
||||
val encrypted = encryptionUtilsV2.encryptFolderMetadataFile(
|
||||
metadataFile,
|
||||
enc1.accountName,
|
||||
folder,
|
||||
storageManager,
|
||||
client,
|
||||
enc1PrivateKey,
|
||||
user,
|
||||
targetContext,
|
||||
arbitraryDataProvider
|
||||
)
|
||||
|
||||
val signature = encryptionUtilsV2.getMessageSignature(enc1Cert, enc1PrivateKey, encrypted)
|
||||
|
||||
val decrypted = encryptionUtilsV2.decryptFolderMetadataFile(
|
||||
encrypted,
|
||||
enc1.accountName,
|
||||
enc1PrivateKey,
|
||||
folder,
|
||||
storageManager,
|
||||
client,
|
||||
0,
|
||||
signature,
|
||||
user,
|
||||
targetContext,
|
||||
arbitraryDataProvider
|
||||
)
|
||||
|
||||
assertEquals(metadataFile, decrypted)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addFile() {
|
||||
val enc1 = MockUser("enc1", "Nextcloud")
|
||||
val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
|
||||
assertEquals(2, metadataFile.metadata.files.size)
|
||||
assertEquals(1, metadataFile.metadata.counter)
|
||||
|
||||
val updatedMetadata = encryptionUtilsV2.addFileToMetadata(
|
||||
EncryptionUtils.generateUid(),
|
||||
OCFile("/test.jpg").apply {
|
||||
mimeType = MimeType.JPEG
|
||||
},
|
||||
EncryptionUtils.generateIV(),
|
||||
EncryptionUtils.generateUid(), // random string, not real tag
|
||||
EncryptionUtils.generateKey(),
|
||||
metadataFile,
|
||||
storageManager
|
||||
)
|
||||
|
||||
assertEquals(3, updatedMetadata.metadata.files.size)
|
||||
assertEquals(2, updatedMetadata.metadata.counter)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun removeFile() {
|
||||
val enc1 = MockUser("enc1", "Nextcloud")
|
||||
val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
|
||||
assertEquals(2, metadataFile.metadata.files.size)
|
||||
|
||||
val filename = metadataFile.metadata.files.keys.first()
|
||||
|
||||
encryptionUtilsV2.removeFileFromMetadata(filename, metadataFile)
|
||||
|
||||
assertEquals(1, metadataFile.metadata.files.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun renameFile() {
|
||||
val enc1 = MockUser("enc1", "Nextcloud")
|
||||
val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
|
||||
assertEquals(2, metadataFile.metadata.files.size)
|
||||
|
||||
val key = metadataFile.metadata.files.keys.first()
|
||||
val decryptedFile = metadataFile.metadata.files[key]
|
||||
val filename = decryptedFile?.filename
|
||||
val newFilename = "New File 1"
|
||||
|
||||
encryptionUtilsV2.renameFile(key, newFilename, metadataFile)
|
||||
|
||||
assertEquals(newFilename, metadataFile.metadata.files[key]?.filename)
|
||||
assertNotEquals(filename, newFilename)
|
||||
assertNotEquals(filename, metadataFile.metadata.files[key]?.filename)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addFolder() {
|
||||
val folder = OCFile("/e/")
|
||||
val enc1 = MockUser("enc1", "Nextcloud")
|
||||
val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
|
||||
assertEquals(2, metadataFile.metadata.files.size)
|
||||
assertEquals(3, metadataFile.metadata.folders.size)
|
||||
|
||||
val updatedMetadata = encryptionUtilsV2.addFolderToMetadata(
|
||||
EncryptionUtils.generateUid(),
|
||||
"new subfolder",
|
||||
metadataFile,
|
||||
folder,
|
||||
storageManager
|
||||
)
|
||||
|
||||
assertEquals(2, updatedMetadata.metadata.files.size)
|
||||
assertEquals(4, updatedMetadata.metadata.folders.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun removeFolder() {
|
||||
val folder = OCFile("/e/")
|
||||
val enc1 = MockUser("enc1", "Nextcloud")
|
||||
val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
|
||||
assertEquals(2, metadataFile.metadata.files.size)
|
||||
assertEquals(3, metadataFile.metadata.folders.size)
|
||||
|
||||
val encryptedFileName = EncryptionUtils.generateUid()
|
||||
var updatedMetadata = encryptionUtilsV2.addFolderToMetadata(
|
||||
encryptedFileName,
|
||||
"new subfolder",
|
||||
metadataFile,
|
||||
folder,
|
||||
storageManager
|
||||
)
|
||||
|
||||
assertEquals(2, updatedMetadata.metadata.files.size)
|
||||
assertEquals(4, updatedMetadata.metadata.folders.size)
|
||||
|
||||
updatedMetadata = encryptionUtilsV2.removeFolderFromMetadata(
|
||||
encryptedFileName,
|
||||
updatedMetadata
|
||||
)
|
||||
|
||||
assertEquals(2, updatedMetadata.metadata.files.size)
|
||||
assertEquals(3, updatedMetadata.metadata.folders.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun verifyMetadata() {
|
||||
val folder = OCFile("/e/")
|
||||
val enc1 = MockUser("enc1", "Nextcloud")
|
||||
val metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
|
||||
val encrypted = encryptionUtilsV2.encryptFolderMetadataFile(
|
||||
metadataFile,
|
||||
enc1UserId,
|
||||
folder,
|
||||
storageManager,
|
||||
client,
|
||||
enc1PrivateKey,
|
||||
user,
|
||||
targetContext,
|
||||
arbitraryDataProvider
|
||||
)
|
||||
|
||||
val signature = encryptionUtilsV2.getMessageSignature(enc1Cert, enc1PrivateKey, encrypted)
|
||||
|
||||
encryptionUtilsV2.verifyMetadata(encrypted, metadataFile, 0, signature)
|
||||
|
||||
assertTrue(true) // if we reach this, test is successful
|
||||
}
|
||||
|
||||
private fun generateDecryptedFileV1(): com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile {
|
||||
return com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile().apply {
|
||||
encrypted = Data().apply {
|
||||
key = EncryptionUtils.generateKeyString()
|
||||
filename = "Random filename.jpg"
|
||||
mimetype = MimeType.JPEG
|
||||
version = 1.0
|
||||
}
|
||||
initializationVector = EncryptionUtils.generateKeyString()
|
||||
authenticationTag = EncryptionUtils.generateKeyString()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMigrateDecryptedV1ToV2() {
|
||||
val v1 = generateDecryptedFileV1()
|
||||
val v2 = encryptionUtilsV2.migrateDecryptedFileV1ToV2(v1)
|
||||
|
||||
assertEquals(v1.encrypted.filename, v2.filename)
|
||||
assertEquals(v1.encrypted.mimetype, v2.mimetype)
|
||||
assertEquals(v1.authenticationTag, v2.authenticationTag)
|
||||
assertEquals(v1.initializationVector, v2.nonce)
|
||||
assertEquals(v1.encrypted.key, v2.key)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMigrateMetadataV1ToV2() {
|
||||
OCFile("/").apply {
|
||||
storageManager.saveFile(this)
|
||||
}
|
||||
|
||||
val folder = OCFile("/enc/").apply {
|
||||
parentId = storageManager.getFileByDecryptedRemotePath("/")?.fileId ?: throw IllegalStateException()
|
||||
}
|
||||
|
||||
val v1 = DecryptedFolderMetadataFileV1().apply {
|
||||
metadata = com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedMetadata().apply {
|
||||
metadataKeys = mapOf(Pair(0, EncryptionUtils.generateKeyString()))
|
||||
}
|
||||
files = mapOf(
|
||||
Pair(EncryptionUtils.generateUid(), generateDecryptedFileV1()),
|
||||
Pair(EncryptionUtils.generateUid(), generateDecryptedFileV1()),
|
||||
Pair(
|
||||
EncryptionUtils.generateUid(),
|
||||
com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile().apply {
|
||||
encrypted = Data().apply {
|
||||
key = EncryptionUtils.generateKeyString()
|
||||
filename = "subFolder"
|
||||
mimetype = MimeType.WEBDAV_FOLDER
|
||||
}
|
||||
initializationVector = EncryptionUtils.generateKeyString()
|
||||
authenticationTag = null
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
val v2 = encryptionUtilsV2.migrateV1ToV2(
|
||||
v1,
|
||||
enc1UserId,
|
||||
enc1Cert,
|
||||
folder,
|
||||
storageManager
|
||||
)
|
||||
|
||||
assertEquals(2, v2.metadata.files.size)
|
||||
assertEquals(1, v2.metadata.folders.size)
|
||||
assertEquals(1, v2.users.size) // only one user upon migration
|
||||
}
|
||||
|
||||
@Throws(com.owncloud.android.operations.UploadException::class, Throwable::class)
|
||||
@Test
|
||||
fun addSharee() {
|
||||
val enc1 = MockUser("enc1", "Nextcloud")
|
||||
val enc2 = MockUser("enc2", "Nextcloud")
|
||||
|
||||
val root = OCFile("/")
|
||||
storageManager.saveFile(root)
|
||||
|
||||
val folder = OCFile("/enc/").apply {
|
||||
parentId = storageManager.getFileByDecryptedRemotePath("/")?.fileId ?: throw IllegalStateException()
|
||||
}
|
||||
|
||||
var metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
|
||||
|
||||
metadataFile = encryptionUtilsV2.addShareeToMetadata(metadataFile, enc2.accountName, enc2Cert)
|
||||
|
||||
val encryptedMetadataFile = encryptionUtilsV2.encryptFolderMetadataFile(
|
||||
metadataFile,
|
||||
client.userId,
|
||||
folder,
|
||||
storageManager,
|
||||
client,
|
||||
enc1PrivateKey,
|
||||
user,
|
||||
targetContext,
|
||||
arbitraryDataProvider
|
||||
)
|
||||
|
||||
val signature = encryptionUtilsV2.getMessageSignature(enc1Cert, enc1PrivateKey, encryptedMetadataFile)
|
||||
|
||||
val decryptedByEnc1 = encryptionUtilsV2.decryptFolderMetadataFile(
|
||||
encryptedMetadataFile,
|
||||
enc1.accountName,
|
||||
enc1PrivateKey,
|
||||
folder,
|
||||
storageManager,
|
||||
client,
|
||||
metadataFile.metadata.counter,
|
||||
signature,
|
||||
user,
|
||||
targetContext,
|
||||
arbitraryDataProvider
|
||||
)
|
||||
assertEquals(metadataFile.metadata, decryptedByEnc1.metadata)
|
||||
|
||||
val decryptedByEnc2 = encryptionUtilsV2.decryptFolderMetadataFile(
|
||||
encryptedMetadataFile,
|
||||
enc2.accountName,
|
||||
enc2PrivateKey,
|
||||
folder,
|
||||
storageManager,
|
||||
client,
|
||||
metadataFile.metadata.counter,
|
||||
signature,
|
||||
user,
|
||||
targetContext,
|
||||
arbitraryDataProvider
|
||||
)
|
||||
assertEquals(metadataFile.metadata, decryptedByEnc2.metadata)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun removeSharee() {
|
||||
val enc1 = MockUser("enc1", "Nextcloud")
|
||||
val enc2 = MockUser("enc2", "Nextcloud")
|
||||
var metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
|
||||
metadataFile = encryptionUtilsV2.addShareeToMetadata(metadataFile, enc2.accountName, enc2Cert)
|
||||
|
||||
assertEquals(2, metadataFile.users.size)
|
||||
|
||||
metadataFile = encryptionUtilsV2.removeShareeFromMetadata(metadataFile, enc2.accountName)
|
||||
|
||||
assertEquals(1, metadataFile.users.size)
|
||||
}
|
||||
|
||||
private fun generateDecryptedFolderMetadataFile(user: User, cert: String): DecryptedFolderMetadataFile {
|
||||
val metadata = DecryptedMetadata(
|
||||
mutableListOf("hash1", "hash of key 2"),
|
||||
false,
|
||||
1,
|
||||
mutableMapOf(
|
||||
Pair(EncryptionUtils.generateUid(), "Folder 1"),
|
||||
Pair(EncryptionUtils.generateUid(), "Folder 2"),
|
||||
Pair(EncryptionUtils.generateUid(), "Folder 3")
|
||||
),
|
||||
mutableMapOf(
|
||||
Pair(
|
||||
EncryptionUtils.generateUid(),
|
||||
DecryptedFile(
|
||||
"file 1.png",
|
||||
"image/png",
|
||||
"initializationVector",
|
||||
"authenticationTag",
|
||||
"key 1"
|
||||
)
|
||||
),
|
||||
Pair(
|
||||
EncryptionUtils.generateUid(),
|
||||
DecryptedFile(
|
||||
"file 2.png",
|
||||
"image/png",
|
||||
"initializationVector 2",
|
||||
"authenticationTag 2",
|
||||
"key 2"
|
||||
)
|
||||
)
|
||||
),
|
||||
EncryptionUtils.generateKey()
|
||||
)
|
||||
|
||||
val users = mutableListOf(
|
||||
DecryptedUser(user.accountName, cert)
|
||||
)
|
||||
|
||||
metadata.keyChecksums.add(encryptionUtilsV2.hashMetadataKey(metadata.metadataKey))
|
||||
|
||||
return DecryptedFolderMetadataFile(metadata, users, mutableMapOf())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGZip() {
|
||||
val string = """
|
||||
This is a test.
|
||||
This is a test.
|
||||
This is a test.
|
||||
This is a test.
|
||||
This is a test.
|
||||
This is a test.
|
||||
This is a test.
|
||||
This is a test.
|
||||
This is a test.
|
||||
This is a test.
|
||||
This is a test.
|
||||
This is a test.
|
||||
This is a test.
|
||||
It contains linewraps and special characters:
|
||||
$$|²›³¥!’‘‘
|
||||
|
||||
""".trimIndent()
|
||||
|
||||
val gzipped = encryptionUtilsV2.gZipCompress(string)
|
||||
|
||||
val result = encryptionUtilsV2.gZipDecompress(gzipped)
|
||||
|
||||
assertEquals(string, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun gunzip() {
|
||||
val string = "H4sICNVkD2QAAwArycgsVgCiRIWS1OISPQDD9wZODwAAAA=="
|
||||
val decoded = EncryptionUtils.decodeStringToBase64Bytes(string)
|
||||
val gunzip = encryptionUtilsV2.gZipDecompress(decoded)
|
||||
|
||||
assertEquals("this is a test.\n", gunzip)
|
||||
}
|
||||
|
||||
// @Test
|
||||
// fun validate() {
|
||||
// // ALEX
|
||||
// val metadata1 = """{
|
||||
// "metadata": {
|
||||
// "authenticationTag": "zMozev5R09UopLrq7Je1lw==",
|
||||
// "ciphertext": "j0OBtUrEt4IveGiexjmGK7eKEaWrY70ZkteA5KxHDaZT/t2wwGy9j2FPQGpqXnW6OO3iAYPNgwFikI1smnfNvqdxzVDvhavl/IXa9Kg2niWyqK3D9zpz0YD6mDvl0XsOgTNVyGXNVREdWgzGEERCQoyHI1xowt/swe3KCXw+lf+XPF/t1PfHv0DiDVk70AeWGpPPPu6yggAIxB4Az6PEZhaQWweTC0an48l2FHj2MtB2PiMHtW2v7RMuE8Al3PtE4gOA8CMFrB+Npy6rKcFCXOgTZm5bp7q+J1qkhBDbiBYtvdsYujJ52Xa5SifTpEhGeWWLFnLLgPAQ8o6bXcWOyCoYfLfp4Jpft/Y7H8qzHbPewNSyD6maEv+xljjfU7hxibbszz5A4JjMdQy2BDGoTmJx7Mas+g6l6ZuHLVbdmgQOvD3waJBy6rOg0euux0Cn4bB4bIFEF2KvbhdGbY1Uiq9DYa7kEmSEnlcAYaHyroTkDg4ew7ER0vIBBMzKM3r+UdPVKKS66uyXtZc=",
|
||||
// "nonce": "W+lxQJeGq7XAJiGfcDohkg=="
|
||||
// },
|
||||
// "users": [{
|
||||
// "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",
|
||||
// "encryptedMetadataKey": "HVT49bYmwXbGs/dJ2avgU9unrKnPf03MYUI5ZysSR1Bz5pqz64gzH2GBAuUJ+Q4VmHtEfcMaWW7VXgzfCQv5xLBrk+RSgcLOKnlIya8jaDlfttWxbe8jJK+/0+QVPOc6ycA/t5HNCPg09hzj+gnb2L89UHxL5accZD0iEzb5cQbGrc/N6GthjgGrgFKtFf0HhDVplUr+DL9aTyKuKLBPjrjuZbv8M6ZfXO93mOMwSZH3c3rwDUHb/KEaTR/Og4pWQmrqr1VxGLqeV/+GKWhzMYThrOZAUz+5gsbckU2M5V9i+ph0yBI5BjOZVhNuDwW8yP8WtyRJwQc+UBRei/RGBQ==",
|
||||
// "userId": "john"
|
||||
// }],
|
||||
// "version": "2"
|
||||
// }
|
||||
//
|
||||
// """
|
||||
//
|
||||
// val signature1 =
|
||||
// "ewogICAgIm1ldGFkYXRhIjogewogICAgICAgICJhdXRoZW50aWNhdGlvblRhZyI6ICJ6TW96ZXY1UjA5VW9wTHJxN0plMWx3PT0iLAogICAgICAgICJjaXBoZXJ0ZXh0IjogImowT0J0VXJFdDRJdmVHaWV4am1HSzdlS0VhV3JZNzBaa3RlQTVLeEhEYVpUL3Qyd3dHeTlqMkZQUUdwcVhuVzZPTzNpQVlQTmd3RmlrSTFzbW5mTnZxZHh6VkR2aGF2bC9JWGE5S2cybmlXeXFLM0Q5enB6MFlENm1EdmwwWHNPZ1ROVnlHWE5WUkVkV2d6R0VFUkNRb3lISTF4b3d0L3N3ZTNLQ1h3K2xmK1hQRi90MVBmSHYwRGlEVms3MEFlV0dwUFBQdTZ5Z2dBSXhCNEF6NlBFWmhhUVd3ZVRDMGFuNDhsMkZIajJNdEIyUGlNSHRXMnY3Uk11RThBbDNQdEU0Z09BOENNRnJCK05weTZyS2NGQ1hPZ1RabTVicDdxK0oxcWtoQkRiaUJZdHZkc1l1ako1MlhhNVNpZlRwRWhHZVdXTEZuTExnUEFROG82YlhjV095Q29ZZkxmcDRKcGZ0L1k3SDhxekhiUGV3TlN5RDZtYUV2K3hsampmVTdoeGliYnN6ejVBNEpqTWRReTJCREdvVG1KeDdNYXMrZzZsNlp1SExWYmRtZ1FPdkQzd2FKQnk2ck9nMGV1dXgwQ240YkI0YklGRUYyS3ZiaGRHYlkxVWlxOURZYTdrRW1TRW5sY0FZYUh5cm9Ua0RnNGV3N0VSMHZJQkJNektNM3IrVWRQVktLUzY2dXlYdFpjPSIsCiAgICAgICAgIm5vbmNlIjogIlcrbHhRSmVHcTdYQUppR2ZjRG9oa2c9PSIKICAgIH0sCiAgICAidXNlcnMiOiB7CiAgICAgICAgImNlcnRpZmljYXRlIjogIi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLVxuTUlJRGtEQ0NBbmlnQXdJQkFnSUJBREFOQmdrcWhraUc5dzBCQVFVRkFEQmhNUXN3Q1FZRFZRUUdFd0pFUlRFYlxuTUJrR0ExVUVDQXdTUW1Ga1pXNHRWM1ZsY25SMFpXMWlaWEpuTVJJd0VBWURWUVFIREFsVGRIVjBkR2RoY25ReFxuRWpBUUJnTlZCQW9NQ1U1bGVIUmpiRzkxWkRFTk1Bc0dBMVVFQXd3RWFtOW9iakFlRncweU16QTNNVFF3TnpNMFxuTlRaYUZ3MDBNekEzTURrd056TTBOVFphTUdFeEN6QUpCZ05WQkFZVEFrUkZNUnN3R1FZRFZRUUlEQkpDWVdSbFxuYmkxWGRXVnlkSFJsYldKbGNtY3hFakFRQmdOVkJBY01DVk4wZFhSMFoyRnlkREVTTUJBR0ExVUVDZ3dKVG1WNFxuZEdOc2IzVmtNUTB3Q3dZRFZRUUREQVJxYjJodU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQlxuQ2dLQ0FRRUE3ajNFcjVZYWhKVDBMQW5TUkxocHFiUm8rRTFBVm50OThydnAzRG1FZkJITnpOQitEUzlJQkRrU1xuU1hNL1l0ZkFjaTZUY3c4dWpWQmpyWlgvV0VtcmY4eW5RSHhZbVNhSlNuUDh1QVQzMDYvTWNlWnBkcHJ1RWM5L1xuUzEwYTd2cDU0WmJsZDROWWRtZlM3MW9WRlZLZ003Yy9WdGh4K3JndTQ4ZnV4emJXQXZWWUxGY3g0N2h6MERKVFxubmp6MlphL1I2OHVYcHhmejdKOXVFWFlpcXNBcy9Gb2JEc0xabHVUM1J5eXdWUndLQmVkMUVaeFVlTElKaXl4cFxuVXRoaEdmSWI4YjNWZjlqWm9VVmkzbTVnbWM0c3BKUUh2WUFrZlpZSHpkOXJhczhqQnUxYWJRUnhjdTJDWW5Wb1xuNlkwbVR4aEtoUVMvbjVnanYzRXhpUUYzd3AvWFl3SURBUUFCbzFNd1VUQWRCZ05WSFE0RUZnUVVtVGVJTFZ1QlxudHY3MGZUR2tYV0dBdWVEcDVrQXdId1lEVlIwakJCZ3dGb0FVbVRlSUxWdUJ0djcwZlRHa1hXR0F1ZURwNWtBd1xuRHdZRFZSMFRBUUgvQkFVd0F3RUIvekFOQmdrcWhraUc5dzBCQVFVRkFBT0NBUUVBeVZ0cTlYQXZXN254U1cvOFxuaHAzMHo2eGJ6R2l1dmlYaHkvSm85MVZFYThJUnNXQ0NuM09tREZpVmR1VEVvd3g3NnRmOGNsSlAwZ2s3UG96aVxuNmRnLzdGaW4rRnFRR1hmQ2s4YkxBaDlnWEtBaWtRMkdLOHlSTjNzbFJGd1lDMm1tMjNIckxkS1haSFVxSmNwQlxuTXoyenNTck9HUGoxWXNZT2wvVThGVTZLQTdZajdVM3E3a0RNWVRBZ3pVUFpBSCtkMURJU0dXcFpzTWEwUllpZFxudmlnQ0NMQnlpY2NtUy9DbzRTYjFlc0Y1OEgrWXRWNStuRkJSd3g4ODFVMmcyVGdES0YxbFBNSy95M2Q4QjhtaFxuVXRXK2xGeFJwdnlOVURwc01qT0VyT3J0TkZFWWJnb1VKTHRxd0JNbXlHUitubW1oNnhuYTMzMVFXY1JBbXcwUFxubkRPNGV3PT1cbi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS1cbiIsCiAgICAgICAgImVuY3J5cHRlZE1ldGFkYXRhS2V5IjogIkhWVDQ5Ylltd1hiR3MvZEoyYXZnVTl1bnJLblBmMDNNWVVJNVp5c1NSMUJ6NXBxejY0Z3pIMkdCQXVVSitRNFZtSHRFZmNNYVdXN1ZYZ3pmQ1F2NXhMQnJrK1JTZ2NMT0tubEl5YThqYURsZnR0V3hiZThqSksrLzArUVZQT2M2eWNBL3Q1SE5DUGcwOWh6aitnbmIyTDg5VUh4TDVhY2NaRDBpRXpiNWNRYkdyYy9ONkd0aGpnR3JnRkt0RmYwSGhEVnBsVXIrREw5YVR5S3VLTEJQanJqdVpidjhNNlpmWE85M21PTXdTWkgzYzNyd0RVSGIvS0VhVFIvT2c0cFdRbXJxcjFWeEdMcWVWLytHS1doek1ZVGhyT1pBVXorNWdzYmNrVTJNNVY5aStwaDB5Qkk1QmpPWlZoTnVEd1c4eVA4V3R5Ukp3UWMrVUJSZWkvUkdCUT09IiwKICAgICAgICAidXNlcklkIjogImpvaG4iCiAgICB9LAogICAgInZlcnNpb24iOiAiMiIKfQo="
|
||||
//
|
||||
// // TOBI
|
||||
// val metadata =
|
||||
// """{"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"}"""
|
||||
//
|
||||
// val base = EncryptionUtils.encodeStringToBase64String(metadata)
|
||||
//
|
||||
// val signature =
|
||||
// "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"
|
||||
//
|
||||
// val metadataFile = EncryptionUtils.deserializeJSON(
|
||||
// metadata,
|
||||
// object : TypeToken<EncryptedFolderMetadataFile>() {}
|
||||
// )
|
||||
// assertNotNull(metadataFile)
|
||||
//
|
||||
// val certJohnString = metadataFile.users[0].certificate
|
||||
// val certJohn = EncryptionUtils.convertCertFromString(certJohnString)
|
||||
//
|
||||
// val t1String = """-----BEGIN CERTIFICATE-----
|
||||
// MIIC6DCCAdCgAwIBAgIBADANBgkqhkiG9w0BAQUFADANMQswCQYDVQQDDAJ0MTAe
|
||||
// Fw0yMzA3MjUwNzU3MTJaFw00MzA3MjAwNzU3MTJaMA0xCzAJBgNVBAMMAnQxMIIB
|
||||
// IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtafHmDBcBqIu4HmMxMDW3j0S
|
||||
// y+S0YaKwHnBRt85KSwcEov0B5FOLuLknoBGx4Dn3u93ilThXXxacPMHeXL7WPuAs
|
||||
// 21/G7vsqwvrRRnCduf+FUO/AZeDCNErzpsQ8LmTa4PUloLPUcImpSjrHwhMs9Ekv
|
||||
// EbLRjbeSmSp9XvM+1fV/3jkT5jkOSnCFx5TGwGN5uHqwUir4UWXasvg253NK2XmW
|
||||
// ipKCDCR9TmH1baP3pNdoiChdmErT1c6E4DbBXpTw8XgP5ZbYH+qg1UQ/hC8nRJ3D
|
||||
// yCcHL+dg/GYraBMhDn4w2Vvq77xNNoNWQ9cT5Ay6cJbQLBQoJQirygQFrobYRQID
|
||||
// AQABo1MwUTAdBgNVHQ4EFgQUE9zCeA9/QMAtVgLxD23X6ZcodhMwHwYDVR0jBBgw
|
||||
// FoAUE9zCeA9/QMAtVgLxD23X6ZcodhMwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
|
||||
// 9w0BAQUFAAOCAQEAZdy/YjJlvnz3FQwxp6oVtMJccpdxveEPfLzgaverhtd/vP8O
|
||||
// AvDzOLgQJHmrDS91SG503eU4cYGyuNKwd77OyTnqMg+GUEmJhGfPpSVrEIdh65jv
|
||||
// q61T4oqBdehevVmBq54rGiwL0DGv1DlXQlwiJZP4qni2KnOEFcnvL3gVtRnQjXQ+
|
||||
// kHvlMshkK6w021EMV5NfjG2zg67wC65rLaej5f6Ssp2S7g2VtmE4aXq1bjAuEbqk
|
||||
// 4TiyZHLDdsJuqzyGyyOpMV7i9ucXDoaZt9cGS9hT2vRxTrSH63vKR8Xeig9+stLw
|
||||
// t9ONcUqCKP7hd8rajtxM4JIIRExwD8OkgARWGg==
|
||||
// -----END CERTIFICATE-----"""
|
||||
//
|
||||
// val t1cert = EncryptionUtils.convertCertFromString(t1String)
|
||||
// val t1PrivateKeyKey = EncryptionUtils.PEMtoPrivateKey(encryptionTestUtils.t1PrivateKey)
|
||||
//
|
||||
// // val signed = encryptionUtilsV2.getMessageSignature(
|
||||
// // t1cert,
|
||||
// // t1PrivateKeyKey,
|
||||
// // metadataFile
|
||||
// // )
|
||||
//
|
||||
// assertTrue(encryptionUtilsV2.verifySignedMessage(signature1, metadata1, listOf(certJohn, t1cert)))
|
||||
// }
|
||||
|
||||
@Throws(Throwable::class)
|
||||
@Test
|
||||
fun testSigning() {
|
||||
val metadata =
|
||||
"""{"metadata": {"authenticationTag": "zMozev5R09UopLrq7Je1lw==","ciphertext": "j0OBtUrEt4IveGiexjm
|
||||
|GK7eKEaWrY70ZkteA5KxHDaZT/t2wwGy9j2FPQGpqXnW6OO3iAYPNgwFikI1smnfNvqdxzVDvhavl/IXa9Kg2niWyqK3D9
|
||||
|zpz0YD6mDvl0XsOgTNVyGXNVREdWgzGEERCQoyHI1xowt/swe3KCXw+lf+XPF/t1PfHv0DiDVk70AeWGpPPPu6yggAIxB4
|
||||
|Az6PEZhaQWweTC0an48l2FHj2MtB2PiMHtW2v7RMuE8Al3PtE4gOA8CMFrB+Npy6rKcFCXOgTZm5bp7q+J1qkhBDbiBYtv
|
||||
|dsYujJ52Xa5SifTpEhGeWWLFnLLgPAQ8o6bXcWOyCoYfLfp4Jpft/Y7H8qzHbPewNSyD6maEv+xljjfU7hxibbszz5A4Jj
|
||||
|MdQy2BDGoTmJx7Mas+g6l6ZuHLVbdmgQOvD3waJBy6rOg0euux0Cn4bB4bIFEF2KvbhdGbY1Uiq9DYa7kEmSEnlcAYaHyr
|
||||
|oTkDg4ew7ER0vIBBMzKM3r+UdPVKKS66uyXtZc=","nonce": "W+lxQJeGq7XAJiGfcDohkg=="},"users": [{"cert
|
||||
|ificate": "-----BEGIN CERTIFICATE-----\nMIIDkDCCAnigAwIBAgIBADANBgkqhkiG9w0BAQUFADBhMQswCQYDVQ
|
||||
|QGEwJERTEb\nMBkGA1UECAwSQmFkZW4tV3VlcnR0ZW1iZXJnMRIwEAYDVQQHDAlTdHV0dGdhcnQx\nEjAQBgNVBAoMCU5l
|
||||
|eHRjbG91ZDENMAsGA1UEAwwEam9objAeFw0yMzA3MTQwNzM0\nNTZaFw00MzA3MDkwNzM0NTZaMGExCzAJBgNVBAYTAkRF
|
||||
|MRswGQYDVQQIDBJCYWRl\nbi1XdWVydHRlbWJlcmcxEjAQBgNVBAcMCVN0dXR0Z2FydDESMBAGA1UECgwJTmV4\ndGNsb3
|
||||
|VkMQ0wCwYDVQQDDARqb2huMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEA7j3Er5YahJT0LAnSRLhpqbRo+E
|
||||
|1AVnt98rvp3DmEfBHNzNB+DS9IBDkS\nSXM/YtfAci6Tcw8ujVBjrZX/WEmrf8ynQHxYmSaJSnP8uAT306/MceZpdpruEc
|
||||
|9/\nS10a7vp54Zbld4NYdmfS71oVFVKgM7c/Vthx+rgu48fuxzbWAvVYLFcx47hz0DJT\nnjz2Za/R68uXpxfz7J9uEXYi
|
||||
|qsAs/FobDsLZluT3RyywVRwKBed1EZxUeLIJiyxp\nUthhGfIb8b3Vf9jZoUVi3m5gmc4spJQHvYAkfZYHzd9ras8jBu1a
|
||||
|bQRxcu2CYnVo\n6Y0mTxhKhQS/n5gjv3ExiQF3wp/XYwIDAQABo1MwUTAdBgNVHQ4EFgQUmTeILVuB\ntv70fTGkXWGAue
|
||||
|Dp5kAwHwYDVR0jBBgwFoAUmTeILVuBtv70fTGkXWGAueDp5kAw\nDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAA
|
||||
|OCAQEAyVtq9XAvW7nxSW/8\nhp30z6xbzGiuviXhy/Jo91VEa8IRsWCCn3OmDFiVduTEowx76tf8clJP0gk7Pozi\n6dg/
|
||||
|7Fin+FqQGXfCk8bLAh9gXKAikQ2GK8yRN3slRFwYC2mm23HrLdKXZHUqJcpB\nMz2zsSrOGPj1YsYOl/U8FU6KA7Yj7U3q
|
||||
|7kDMYTAgzUPZAH+d1DISGWpZsMa0RYid\nvigCCLByiccmS/Co4Sb1esF58H+YtV5+nFBRwx881U2g2TgDKF1lPMK/y3d8
|
||||
|B8mh\nUtW+lFxRpvyNUDpsMjOErOrtNFEYbgoUJLtqwBMmyGR+nmmh6xna331QWcRAmw0P\nnDO4ew==\n-----END CER
|
||||
|TIFICATE-----\n","encryptedMetadataKey": "HVT49bYmwXbGs/dJ2avgU9unrKnPf03MYUI5ZysSR1Bz5pqz64gz
|
||||
|H2GBAuUJ+Q4VmHtEfcMaWW7VXgzfCQv5xLBrk+RSgcLOKnlIya8jaDlfttWxbe8jJK+/0+QVPOc6ycA/t5HNCPg09hzj+g
|
||||
|nb2L89UHxL5accZD0iEzb5cQbGrc/N6GthjgGrgFKtFf0HhDVplUr+DL9aTyKuKLBPjrjuZbv8M6ZfXO93mOMwSZH3c3rw
|
||||
|DUHb/KEaTR/Og4pWQmrqr1VxGLqeV/+GKWhzMYThrOZAUz+5gsbckU2M5V9i+ph0yBI5BjOZVhNuDwW8yP8WtyRJwQc+UB
|
||||
|Rei/RGBQ==","userId": "john"}],"version": "2"}
|
||||
""".trimMargin()
|
||||
|
||||
val base64Metadata = EncryptionUtils.encodeStringToBase64String(metadata)
|
||||
|
||||
val privateKey = EncryptionUtils.PEMtoPrivateKey(encryptionTestUtils.t1PrivateKey)
|
||||
val certificateT1 = EncryptionUtils.convertCertFromString(encryptionTestUtils.t1PublicKey)
|
||||
val certificateEnc2 = EncryptionUtils.convertCertFromString(enc2Cert)
|
||||
|
||||
val signed = encryptionUtilsV2.signMessage(
|
||||
certificateT1,
|
||||
privateKey,
|
||||
metadata
|
||||
)
|
||||
|
||||
val base64Ans = encryptionUtilsV2.extractSignedString(signed)
|
||||
|
||||
// verify
|
||||
val certs = listOf(
|
||||
certificateEnc2,
|
||||
certificateT1
|
||||
)
|
||||
assertTrue(encryptionUtilsV2.verifySignedMessage(signed, certs))
|
||||
assertTrue(encryptionUtilsV2.verifySignedMessage(base64Ans, base64Metadata, certs))
|
||||
}
|
||||
|
||||
@Throws(Throwable::class)
|
||||
@Test
|
||||
fun sign() {
|
||||
val sut = "randomstring123"
|
||||
val json = "randomstring123"
|
||||
val jsonBase64 = EncryptionUtils.encodeStringToBase64String(json)
|
||||
|
||||
val privateKey = EncryptionUtils.PEMtoPrivateKey(encryptionTestUtils.t1PrivateKey)
|
||||
val certificate = EncryptionUtils.convertCertFromString(encryptionTestUtils.t1PublicKey)
|
||||
|
||||
val signed = encryptionUtilsV2.signMessage(
|
||||
certificate,
|
||||
privateKey,
|
||||
sut
|
||||
)
|
||||
|
||||
val base64Ans = encryptionUtilsV2.extractSignedString(signed)
|
||||
|
||||
// verify
|
||||
val certs = listOf(
|
||||
EncryptionUtils.convertCertFromString(enc2Cert),
|
||||
certificate
|
||||
)
|
||||
assertTrue(encryptionUtilsV2.verifySignedMessage(signed, certs))
|
||||
assertTrue(encryptionUtilsV2.verifySignedMessage(base64Ans, jsonBase64, certs))
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testUpdateFileNameForEncryptedFile() {
|
||||
val folder = testFolder()
|
||||
|
||||
val metadata = EncryptionTestUtils().generateFolderMetadataV2(
|
||||
client.userId,
|
||||
EncryptionTestIT.publicKey
|
||||
)
|
||||
|
||||
RefreshFolderOperation.updateFileNameForEncryptedFile(storageManager, metadata, folder)
|
||||
|
||||
assertEquals(folder.decryptedRemotePath.contains("null"), false)
|
||||
}
|
||||
|
||||
/**
|
||||
* DecryptedFolderMetadata -> EncryptedFolderMetadata -> JSON -> encrypt -> decrypt -> JSON ->
|
||||
* EncryptedFolderMetadata -> DecryptedFolderMetadata
|
||||
*/
|
||||
@Test
|
||||
@Throws(Exception::class, Throwable::class)
|
||||
fun encryptionMetadataV2() {
|
||||
val decryptedFolderMetadata1: DecryptedFolderMetadataFile =
|
||||
EncryptionTestUtils().generateFolderMetadataV2(client.userId, EncryptionTestIT.publicKey)
|
||||
val root = OCFile("/")
|
||||
storageManager.saveFile(root)
|
||||
|
||||
val folder = OCFile("/enc")
|
||||
folder.parentId = storageManager.getFileByDecryptedRemotePath("/")?.fileId ?: throw IllegalStateException()
|
||||
|
||||
storageManager.saveFile(folder)
|
||||
|
||||
decryptedFolderMetadata1.filedrop.clear()
|
||||
|
||||
// encrypt
|
||||
val encryptedFolderMetadata1 = encryptionUtilsV2.encryptFolderMetadataFile(
|
||||
decryptedFolderMetadata1,
|
||||
client.userId,
|
||||
folder,
|
||||
storageManager,
|
||||
client,
|
||||
EncryptionTestIT.publicKey,
|
||||
user,
|
||||
targetContext,
|
||||
arbitraryDataProvider
|
||||
)
|
||||
|
||||
val signature = encryptionUtilsV2.getMessageSignature(enc1Cert, enc1PrivateKey, encryptedFolderMetadata1)
|
||||
|
||||
// serialize
|
||||
val encryptedJson = EncryptionUtils.serializeJSON(encryptedFolderMetadata1, true)
|
||||
|
||||
// de-serialize
|
||||
val encryptedFolderMetadata2 = EncryptionUtils.deserializeJSON(
|
||||
encryptedJson,
|
||||
object : TypeToken<EncryptedFolderMetadataFile?>() {}
|
||||
)
|
||||
|
||||
// decrypt
|
||||
val decryptedFolderMetadata2 = encryptionUtilsV2.decryptFolderMetadataFile(
|
||||
encryptedFolderMetadata2!!,
|
||||
getUserId(user),
|
||||
EncryptionTestIT.privateKey,
|
||||
folder,
|
||||
fileDataStorageManager,
|
||||
client,
|
||||
decryptedFolderMetadata1.metadata.counter,
|
||||
signature,
|
||||
user,
|
||||
targetContext,
|
||||
arbitraryDataProvider
|
||||
)
|
||||
|
||||
// compare
|
||||
assertTrue(
|
||||
EncryptionTestIT.compareJsonStrings(
|
||||
EncryptionUtils.serializeJSON(decryptedFolderMetadata1),
|
||||
EncryptionUtils.serializeJSON(decryptedFolderMetadata2)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Throws(Throwable::class)
|
||||
@Test
|
||||
fun decryptFiledropV2() {
|
||||
val sut = EncryptedFiledrop(
|
||||
"""QE5nJmA8QC3rBJxbpsZu6MvkomwHMKTYf/3dEz9Zq3ITHLK/wNAIqWTbDehBJ7SlTfXakkKR9o0sOkUDI7PD8qJyv5hW7LzifszYGe
|
||||
|xE0V1daFcCFApKrIEBABHVOq+ZHJd8IzNSz3hdA9bWd2eiaEGyQzgdTPELE6Ie84IwFANJHcaRB5B43aaDdbUXNJ4/oMboOReKTJ
|
||||
|/vT6ZGhve4DRPEsez0quyDZDNlin5hD6UaUzw=
|
||||
""".trimMargin(),
|
||||
"HC87OgVzbR2CXdWp7rKI5A==",
|
||||
"7PSq7INkM2WKfmEPpRpTPA==",
|
||||
listOf(
|
||||
EncryptedFiledropUser(
|
||||
"android3",
|
||||
"""cNzk8cNyoTJ49Cj/x2WPlsMAnUWlZsfnKJ3VIRiczASeUYUFhaJpD8HDWE0uhkXSD7i9nzpe6pR7zllE7UE/QniDd+BQiF
|
||||
|80E5fSO1KVfFkLZRT+2pX5oPnl4CVtMnxb4xG7J1nAUqMhfS8PtQIr0+S7NKDdrUc41aNOB/4kH0D9LSo/bSC38L7ewv
|
||||
|mISM6ZFi1bfI1505kZV0HqcW12nZwHwe3s6rYkoSPBOPX1oPkvMYTVLkYuU+7DNL4HW7D9dc9X4bsSGLdj4joRi9FURi
|
||||
|mMv6MOrWOnYlX2zmMKAF3nEjLlhngKG7pUi/qMIlft2AhRM4cJuuIQ29vvTGFFDQ==
|
||||
""".trimMargin()
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val privateKey =
|
||||
"""MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDPNCnYcPgGQwCzL8sxLTiE0atn5tiW1nfPQc1aY/+aXvkpF4h2vT
|
||||
|S/hQg2SCNFUlw8aYKksk5IH5FFcPv9QFG/TQDQOnZhi7moVPnVwLkx+cDfWQQs1EOhI/ZPdSo7MdaRLttbZZs/GJfnr1ziYZTxLO
|
||||
|UUxT541cnSpqGTKmUXhGMoX+jQTmcn1NyBD537NdetOxSdMfvBIobjRQ70/9c1HFGQSrJa+DmPiis6iFkd1LH6WWRbreC6DsRSqK
|
||||
|ne3sD1ujx39k+VxtBe035c2L9PbTMMW3kBdZxlRkV1tUQhDAys0K+CyvNIFsOjqvQKTnXNfWO+kVnpOkpbTK4imuPbAgMBAAECgf
|
||||
|9T537U/6TuwJLSj4bfYev8qYaakfVIpyMkL33e4YBQnUzhlCPBVYgpHkDPwznk2XhjQQiVcRAycmUHBmy4aPkcOjuBmd87aTj03k
|
||||
|niDk+doFDNU8myuwWTw/1fHdElRnLyZxEKrb391HD4SVVQMuxnw8UoC4iNcPnYneY/GTiTtB3dVcRKdabX3Oak2TFiJyJBtTz4RN
|
||||
|sRYVXM3jyCbxj8uV+XNr+3OuQe5u7cV5gkXOXHqcNczOrxGzSXVGULuw8FiHIlhId7tot3dGdyVvWD9YIwwGA/9/3g8JixqpQHKZ
|
||||
|6YJAeqltydisGa3CIIEzBAh52GJC7yzMKSC2ZAtW0CgYEA6B/O+EgtZthiXOwivqZmKKGgWGLSOGjVsExSa1iiTTz3EFwcdD54mU
|
||||
|TKc6hw787NFlfN1m7B7EDQxIldRDI3One1q2dj87taco/qFqKsHuAuC3gmZIp2F4l2P8NpdHHFMzUzsfs+grY/wLHZiJdfOTdulA
|
||||
|s9go5mDloMC96n0/UCgYEA5IQo7c4ZxwhlssIn89XaOlKGoIct07wsBMu47HZYFqgG2/NUN8zRfSdSvot+6zinAb6Z3iGZ2FBL+C
|
||||
|MmoEMGwuXSQjWxeD//UU6V5AZqlgis5s9WakKWmkTkVV3bPSwW0DuNcqbMk7BxAXcQ6QGIiBtzeaPuL/3gzA9e9vm8xo8CgYEAqL
|
||||
|I9S6nA/UZzLg8bLS1nf03/Z1ziZMajzk2ZdJRk1/dfow8eSskAAnvBGo8nDNFhsUQ8vwOdgeKVFtCx7JcGFkLbz+cC+CaIFExNFw
|
||||
|hASOwp6oH2fQk3y+FGBA8ze8IXTCD1IftzMbHb4WIfsyo3tTB497S3jkOJHhMJQDMgC2UCgYEAzjUgRe98vWkrdFLWAKfSxFxiFg
|
||||
|vF49JjGnTHy8HDHbbEccizD6NoyvooJb/1aMd3lRBtAtDpZhSXaTQ3D9lMCaWfxZV0LyH5AGLcyaasmfT8KU+iGEM8abuPHCWUyC
|
||||
|+36nJC4tn3s7I9V2gdP1Xd4Yx7+KFgN7huGVYpiM61dasCgYAQs5mPHRBeU+BHtPRyaLHhYq+jjYeocwyOpfw5wkiH3jsyUWTK9+
|
||||
|GlAoV75SYvQVIQS0VH1C1/ajz9yV02frAaUXbGtZJbyeAcyy3DjCc7iF0swJ4slP3gGVJipVF4aQ0d9wMoJ7SBaaTR0ohXeUWmTT
|
||||
|X+VGf+cZQ2IefKVnz9mg==
|
||||
""".trimMargin()
|
||||
|
||||
val decryptedFile = EncryptionUtilsV2().decryptFiledrop(sut, privateKey, arbitraryDataProvider, user)
|
||||
assertEquals("test.txt", decryptedFile.filename)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import androidx.test.espresso.idling.CountingIdlingResource
|
||||
|
||||
object EspressoIdlingResource {
|
||||
|
||||
private const val RESOURCE = "GLOBAL"
|
||||
|
||||
@JvmField val countingIdlingResource = CountingIdlingResource(RESOURCE)
|
||||
|
||||
fun increment() {
|
||||
countingIdlingResource.increment()
|
||||
}
|
||||
|
||||
fun decrement() {
|
||||
if (!countingIdlingResource.isIdleNow) {
|
||||
countingIdlingResource.decrement()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2022 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import com.owncloud.android.AbstractIT
|
||||
import com.owncloud.android.datamodel.OCFile
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
|
||||
class FileExportUtilsIT : AbstractIT() {
|
||||
@Test
|
||||
fun exportFile() {
|
||||
val file = createFile("export.txt", 10)
|
||||
|
||||
val sut = FileExportUtils()
|
||||
|
||||
val expectedFile = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
|
||||
File("/sdcard/Downloads/export.txt")
|
||||
} else {
|
||||
File("/storage/emulated/0/Download/export.txt")
|
||||
}
|
||||
|
||||
assertFalse(expectedFile.exists())
|
||||
|
||||
sut.exportFile("export.txt", "/text/plain", targetContext.contentResolver, null, file)
|
||||
|
||||
assertTrue(expectedFile.exists())
|
||||
assertEquals(file.length(), expectedFile.length())
|
||||
assertTrue(expectedFile.delete())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun exportOCFile() {
|
||||
val file = createFile("export.txt", 10)
|
||||
val ocFile = OCFile("/export.txt").apply {
|
||||
storagePath = file.absolutePath
|
||||
}
|
||||
|
||||
val sut = FileExportUtils()
|
||||
|
||||
val expectedFile = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
|
||||
File("/sdcard/Downloads/export.txt")
|
||||
} else {
|
||||
File("/storage/emulated/0/Download/export.txt")
|
||||
}
|
||||
|
||||
assertFalse(expectedFile.exists())
|
||||
|
||||
sut.exportFile("export.txt", "/text/plain", targetContext.contentResolver, ocFile, null)
|
||||
|
||||
assertTrue(expectedFile.exists())
|
||||
assertEquals(file.length(), expectedFile.length())
|
||||
assertTrue(expectedFile.delete())
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import android.content.Context
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.owncloud.android.AbstractIT
|
||||
import com.owncloud.android.datamodel.OCFile
|
||||
import com.owncloud.android.utils.FileStorageUtils.checkIfEnoughSpace
|
||||
import com.owncloud.android.utils.FileStorageUtils.pathToUserFriendlyDisplay
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
|
||||
class FileStorageUtilsIT : AbstractIT() {
|
||||
private fun openFile(name: String): File {
|
||||
val ctx: Context = ApplicationProvider.getApplicationContext()
|
||||
val externalFilesDir = ctx.getExternalFilesDir(null)
|
||||
return File(externalFilesDir, name)
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("MagicNumber")
|
||||
fun testEnoughSpaceWithoutLocalFile() {
|
||||
val ocFile = OCFile("/test.txt")
|
||||
val file = openFile("test.txt")
|
||||
file.createNewFile()
|
||||
|
||||
ocFile.storagePath = file.absolutePath
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertTrue(checkIfEnoughSpace(200L, ocFile))
|
||||
|
||||
ocFile.fileLength = 0
|
||||
assertTrue(checkIfEnoughSpace(200L, ocFile))
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertFalse(checkIfEnoughSpace(50L, ocFile))
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertFalse(checkIfEnoughSpace(100L, ocFile))
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("MagicNumber")
|
||||
fun testEnoughSpaceWithLocalFile() {
|
||||
val ocFile = OCFile("/test.txt")
|
||||
val file = openFile("test.txt")
|
||||
file.writeText("123123")
|
||||
|
||||
ocFile.storagePath = file.absolutePath
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertTrue(checkIfEnoughSpace(200L, ocFile))
|
||||
|
||||
ocFile.fileLength = 0
|
||||
assertTrue(checkIfEnoughSpace(200L, ocFile))
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertFalse(checkIfEnoughSpace(50L, ocFile))
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertFalse(checkIfEnoughSpace(100L, ocFile))
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("MagicNumber")
|
||||
fun testEnoughSpaceWithoutLocalFolder() {
|
||||
val ocFile = OCFile("/test/")
|
||||
val file = openFile("test")
|
||||
File(file, "1.txt").writeText("123123")
|
||||
|
||||
ocFile.storagePath = file.absolutePath
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertTrue(checkIfEnoughSpace(200L, ocFile))
|
||||
|
||||
ocFile.fileLength = 0
|
||||
assertTrue(checkIfEnoughSpace(200L, ocFile))
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertFalse(checkIfEnoughSpace(50L, ocFile))
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertFalse(checkIfEnoughSpace(100L, ocFile))
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("MagicNumber")
|
||||
fun testEnoughSpaceWithLocalFolder() {
|
||||
val ocFile = OCFile("/test/")
|
||||
val folder = openFile("test")
|
||||
folder.mkdirs()
|
||||
val file = File(folder, "1.txt")
|
||||
file.createNewFile()
|
||||
file.writeText("123123")
|
||||
|
||||
ocFile.storagePath = folder.absolutePath
|
||||
ocFile.mimeType = "DIR"
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertTrue(checkIfEnoughSpace(200L, ocFile))
|
||||
|
||||
ocFile.fileLength = 0
|
||||
assertTrue(checkIfEnoughSpace(200L, ocFile))
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertFalse(checkIfEnoughSpace(50L, ocFile))
|
||||
|
||||
ocFile.fileLength = 44
|
||||
assertTrue(checkIfEnoughSpace(50L, ocFile))
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertTrue(checkIfEnoughSpace(100L, ocFile))
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("MagicNumber")
|
||||
fun testEnoughSpaceWithNoLocalFolder() {
|
||||
val ocFile = OCFile("/test/")
|
||||
|
||||
ocFile.mimeType = "DIR"
|
||||
|
||||
ocFile.fileLength = 100
|
||||
assertTrue(checkIfEnoughSpace(200L, ocFile))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPathToUserFriendlyDisplay() {
|
||||
assertEquals("/", pathToUserFriendlyDisplay("/"))
|
||||
assertEquals("/sdcard/", pathToUserFriendlyDisplay("/sdcard/"))
|
||||
assertEquals("/sdcard/test/1/", pathToUserFriendlyDisplay("/sdcard/test/1/"))
|
||||
assertEquals("Internal storage/Movies/", pathToUserFriendlyDisplay("/storage/emulated/0/Movies/"))
|
||||
assertEquals("Internal storage/", pathToUserFriendlyDisplay("/storage/emulated/0/"))
|
||||
}
|
||||
|
||||
private fun pathToUserFriendlyDisplay(path: String): String {
|
||||
return pathToUserFriendlyDisplay(path, targetContext, targetContext.resources)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2020 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import com.owncloud.android.AbstractIT
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
|
||||
class FileUtilTest : AbstractIT() {
|
||||
@Test
|
||||
fun assertNullInput() {
|
||||
Assert.assertEquals("", FileUtil.getFilenameFromPathString(null))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertEmptyInput() {
|
||||
Assert.assertEquals("", FileUtil.getFilenameFromPathString(""))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertFileInput() {
|
||||
val file = getDummyFile("empty.txt")
|
||||
Assert.assertEquals("empty.txt", FileUtil.getFilenameFromPathString(file.absolutePath))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertSlashInput() {
|
||||
val tempPath = File(FileStorageUtils.getTemporalPath(account.name) + File.pathSeparator + "folder")
|
||||
if (!tempPath.exists()) {
|
||||
Assert.assertTrue(tempPath.mkdirs())
|
||||
}
|
||||
Assert.assertEquals("", FileUtil.getFilenameFromPathString(tempPath.absolutePath))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertDotFileInput() {
|
||||
val file = getDummyFile(".dotfile.ext")
|
||||
Assert.assertEquals(".dotfile.ext", FileUtil.getFilenameFromPathString(file.absolutePath))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertFolderInput() {
|
||||
val tempPath = File(FileStorageUtils.getTemporalPath(account.name))
|
||||
if (!tempPath.exists()) {
|
||||
Assert.assertTrue(tempPath.mkdirs())
|
||||
}
|
||||
|
||||
Assert.assertEquals("", FileUtil.getFilenameFromPathString(tempPath.absolutePath))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertNoFileExtensionInput() {
|
||||
val file = getDummyFile("file")
|
||||
Assert.assertEquals("file", FileUtil.getFilenameFromPathString(file.absolutePath))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import com.nextcloud.client.account.UserAccountManager
|
||||
import com.nextcloud.client.account.UserAccountManagerImpl
|
||||
import com.nextcloud.client.mixins.SessionMixin
|
||||
import com.owncloud.android.AbstractIT
|
||||
import com.owncloud.android.ui.activity.FileDisplayActivity
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
class SessionMixinTest : AbstractIT() {
|
||||
|
||||
private lateinit var userAccountManager: UserAccountManager
|
||||
private lateinit var session: SessionMixin
|
||||
|
||||
private var scenario: ActivityScenario<FileDisplayActivity>? = null
|
||||
val intent = Intent(ApplicationProvider.getApplicationContext(), FileDisplayActivity::class.java)
|
||||
|
||||
@get:Rule
|
||||
val activityRule = ActivityScenarioRule<FileDisplayActivity>(intent)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
userAccountManager = UserAccountManagerImpl.fromContext(targetContext)
|
||||
|
||||
scenario = activityRule.scenario
|
||||
scenario?.onActivity { sut ->
|
||||
session = SessionMixin(
|
||||
sut,
|
||||
userAccountManager
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun startAccountCreation() {
|
||||
session.startAccountCreation()
|
||||
|
||||
scenario = activityRule.scenario
|
||||
scenario?.onActivity { sut ->
|
||||
assert(sut.account.name == userAccountManager.accounts.first().name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2020 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.owncloud.android.utils
|
||||
|
||||
import com.nextcloud.client.preferences.SubFolderRule
|
||||
import com.owncloud.android.AbstractIT
|
||||
import com.owncloud.android.datamodel.MediaFolder
|
||||
import com.owncloud.android.datamodel.MediaFolderType
|
||||
import com.owncloud.android.datamodel.SyncedFolder
|
||||
import org.apache.commons.io.FileUtils
|
||||
import org.junit.AfterClass
|
||||
import org.junit.Assert
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.util.Arrays
|
||||
|
||||
class SyncedFolderUtilsTest : AbstractIT() {
|
||||
@Test
|
||||
fun assertCoverFilenameUnqualified() {
|
||||
Assert.assertFalse(SyncedFolderUtils.isFileNameQualifiedForAutoUpload(COVER))
|
||||
Assert.assertFalse(SyncedFolderUtils.isFileNameQualifiedForAutoUpload("cover.JPG"))
|
||||
Assert.assertFalse(SyncedFolderUtils.isFileNameQualifiedForAutoUpload("cover.jpeg"))
|
||||
Assert.assertFalse(SyncedFolderUtils.isFileNameQualifiedForAutoUpload("cover.JPEG"))
|
||||
Assert.assertFalse(SyncedFolderUtils.isFileNameQualifiedForAutoUpload("COVER.jpg"))
|
||||
Assert.assertFalse(SyncedFolderUtils.isFileNameQualifiedForAutoUpload(FOLDER))
|
||||
Assert.assertFalse(SyncedFolderUtils.isFileNameQualifiedForAutoUpload("Folder.jpeg"))
|
||||
Assert.assertFalse(SyncedFolderUtils.isFileNameQualifiedForAutoUpload("FOLDER.jpg"))
|
||||
Assert.assertFalse(SyncedFolderUtils.isFileNameQualifiedForAutoUpload(THUMBDATA_FILE))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertImageFilenameQualified() {
|
||||
Assert.assertTrue(SyncedFolderUtils.isFileNameQualifiedForAutoUpload("image.jpg"))
|
||||
Assert.assertTrue(SyncedFolderUtils.isFileNameQualifiedForAutoUpload("screenshot.JPG"))
|
||||
Assert.assertTrue(SyncedFolderUtils.isFileNameQualifiedForAutoUpload(IMAGE_JPEG))
|
||||
Assert.assertTrue(SyncedFolderUtils.isFileNameQualifiedForAutoUpload("image.JPEG"))
|
||||
Assert.assertTrue(SyncedFolderUtils.isFileNameQualifiedForAutoUpload("SCREENSHOT.jpg"))
|
||||
Assert.assertTrue(SyncedFolderUtils.isFileNameQualifiedForAutoUpload(SELFIE))
|
||||
Assert.assertTrue(SyncedFolderUtils.isFileNameQualifiedForAutoUpload("screenshot.PNG"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertMediaFolderNullSafe() {
|
||||
val folder: MediaFolder? = null
|
||||
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertMediaFolderCustomQualified() {
|
||||
val folder = MediaFolder()
|
||||
folder.type = MediaFolderType.CUSTOM
|
||||
Assert.assertTrue(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertMediaFolderVideoUnqualified() {
|
||||
val folder = MediaFolder().apply {
|
||||
absolutePath = getDummyFile(THUMBDATA_FOLDER).absolutePath
|
||||
type = MediaFolderType.VIDEO
|
||||
numberOfFiles = 0L
|
||||
}
|
||||
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertMediaFolderVideoQualified() {
|
||||
val folder = MediaFolder().apply {
|
||||
absolutePath = getDummyFile(THUMBDATA_FOLDER).absolutePath
|
||||
type = MediaFolderType.VIDEO
|
||||
numberOfFiles = 20L
|
||||
}
|
||||
Assert.assertTrue(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertMediaFolderImagesQualified() {
|
||||
val folder = MediaFolder().apply {
|
||||
absolutePath = getDummyFile(THUMBDATA_FOLDER).absolutePath
|
||||
type = MediaFolderType.IMAGE
|
||||
numberOfFiles = 4L
|
||||
filePaths = Arrays.asList(
|
||||
getDummyFile(SELFIE).absolutePath,
|
||||
getDummyFile(SCREENSHOT).absolutePath,
|
||||
getDummyFile(IMAGE_JPEG).absolutePath,
|
||||
getDummyFile(IMAGE_BITMAP).absolutePath
|
||||
)
|
||||
}
|
||||
Assert.assertTrue(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertMediaFolderImagesEmptyUnqualified() {
|
||||
val folder = MediaFolder().apply {
|
||||
absolutePath = getDummyFile(THUMBDATA_FOLDER).absolutePath
|
||||
type = MediaFolderType.IMAGE
|
||||
numberOfFiles = 0L
|
||||
}
|
||||
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertMediaFolderImagesNoImagesUnqualified() {
|
||||
val folder = MediaFolder().apply {
|
||||
absolutePath = getDummyFile(THUMBDATA_FOLDER).absolutePath
|
||||
type = MediaFolderType.IMAGE
|
||||
numberOfFiles = 3L
|
||||
filePaths = Arrays.asList(
|
||||
getDummyFile(SONG_ZERO).absolutePath,
|
||||
getDummyFile(SONG_ONE).absolutePath,
|
||||
getDummyFile(SONG_TWO).absolutePath
|
||||
)
|
||||
}
|
||||
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertMediaFolderImagesMusicAlbumWithCoverArtUnqualified() {
|
||||
val folder = MediaFolder().apply {
|
||||
absolutePath = getDummyFile(THUMBDATA_FOLDER).absolutePath
|
||||
type = MediaFolderType.IMAGE
|
||||
numberOfFiles = 3L
|
||||
filePaths = Arrays.asList(
|
||||
getDummyFile(COVER).absolutePath,
|
||||
getDummyFile(SONG_ONE).absolutePath,
|
||||
getDummyFile(SONG_TWO).absolutePath
|
||||
)
|
||||
}
|
||||
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertMediaFolderImagesMusicAlbumWithFolderArtUnqualified() {
|
||||
val folder = MediaFolder().apply {
|
||||
absolutePath = getDummyFile(THUMBDATA_FOLDER).absolutePath
|
||||
type = MediaFolderType.IMAGE
|
||||
numberOfFiles = 3L
|
||||
filePaths = Arrays.asList(
|
||||
getDummyFile(FOLDER).absolutePath,
|
||||
getDummyFile(SONG_ONE).absolutePath,
|
||||
getDummyFile(SONG_TWO).absolutePath
|
||||
)
|
||||
}
|
||||
|
||||
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertSyncedFolderNullSafe() {
|
||||
val folder: SyncedFolder? = null
|
||||
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertUnqualifiedContentSyncedFolder() {
|
||||
val localFolder = getDummyFile(THUMBDATA_FOLDER + File.separatorChar)
|
||||
getDummyFile(THUMBDATA_FOLDER + File.separatorChar + THUMBDATA_FILE)
|
||||
val folder = SyncedFolder(
|
||||
localFolder.absolutePath,
|
||||
"",
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
account.name,
|
||||
1,
|
||||
1,
|
||||
true,
|
||||
0L,
|
||||
MediaFolderType.IMAGE,
|
||||
false,
|
||||
SubFolderRule.YEAR_MONTH,
|
||||
false,
|
||||
SyncedFolder.NOT_SCANNED_YET
|
||||
)
|
||||
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertUnqualifiedSyncedFolder() {
|
||||
getDummyFile(THUMBNAILS_FOLDER + File.separatorChar + IMAGE_JPEG)
|
||||
getDummyFile(THUMBNAILS_FOLDER + File.separatorChar + IMAGE_BITMAP)
|
||||
val folder = SyncedFolder(
|
||||
FileStorageUtils.getTemporalPath(account.name) + File.separatorChar + THUMBNAILS_FOLDER,
|
||||
"",
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
account.name,
|
||||
1,
|
||||
1,
|
||||
true,
|
||||
0L,
|
||||
MediaFolderType.IMAGE,
|
||||
false,
|
||||
SubFolderRule.YEAR_MONTH,
|
||||
false,
|
||||
SyncedFolder.NOT_SCANNED_YET
|
||||
)
|
||||
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val SELFIE = "selfie.png"
|
||||
private const val SCREENSHOT = "screenshot.JPG"
|
||||
private const val IMAGE_JPEG = "image.jpeg"
|
||||
private const val IMAGE_BITMAP = "image.bmp"
|
||||
private const val SONG_ZERO = "song0.mp3"
|
||||
private const val SONG_ONE = "song1.mp3"
|
||||
private const val SONG_TWO = "song2.mp3"
|
||||
private const val FOLDER = "folder.JPG"
|
||||
private const val COVER = "cover.jpg"
|
||||
private const val THUMBNAILS_FOLDER = ".thumbnails/"
|
||||
private const val THUMBDATA_FOLDER = "valid_folder/"
|
||||
private const val THUMBDATA_FILE = ".thumbdata4--1967290299"
|
||||
private const val ITERATION = 100
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun setUp() {
|
||||
val tempPath =
|
||||
File(
|
||||
FileStorageUtils.getTemporalPath(account.name) + File.separatorChar +
|
||||
THUMBNAILS_FOLDER
|
||||
)
|
||||
if (!tempPath.exists()) {
|
||||
tempPath.mkdirs()
|
||||
}
|
||||
|
||||
createFile(SELFIE, ITERATION)
|
||||
createFile(SCREENSHOT, ITERATION)
|
||||
createFile(IMAGE_JPEG, ITERATION)
|
||||
createFile(IMAGE_BITMAP, ITERATION)
|
||||
createFile(SONG_ZERO, ITERATION)
|
||||
createFile(SONG_ONE, ITERATION)
|
||||
createFile(SONG_TWO, ITERATION)
|
||||
createFile(FOLDER, ITERATION)
|
||||
createFile(COVER, ITERATION)
|
||||
|
||||
createFile(THUMBDATA_FOLDER + File.separatorChar + THUMBDATA_FILE, ITERATION)
|
||||
createFile(THUMBNAILS_FOLDER + File.separatorChar + IMAGE_JPEG, ITERATION)
|
||||
createFile(THUMBNAILS_FOLDER + File.separatorChar + IMAGE_BITMAP, ITERATION)
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@JvmStatic
|
||||
fun tearDown() {
|
||||
FileUtils.deleteDirectory(File(FileStorageUtils.getTemporalPath(account.name)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2023 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.owncloud.android.utils.theme
|
||||
|
||||
import com.owncloud.android.AbstractIT
|
||||
import com.owncloud.android.lib.resources.status.NextcloudVersion
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion
|
||||
import junit.framework.TestCase.assertFalse
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class CapabilityUtilsIT : AbstractIT() {
|
||||
@Test
|
||||
fun checkOutdatedWarning() {
|
||||
assertFalse(test(NextcloudVersion.nextcloud_28))
|
||||
assertFalse(test(NextcloudVersion.nextcloud_27))
|
||||
|
||||
assertTrue(test(NextcloudVersion.nextcloud_26))
|
||||
assertTrue(test(NextcloudVersion.nextcloud_25))
|
||||
assertTrue(test(NextcloudVersion.nextcloud_24))
|
||||
assertTrue(test(NextcloudVersion.nextcloud_23))
|
||||
assertTrue(test(NextcloudVersion.nextcloud_22))
|
||||
assertTrue(test(NextcloudVersion.nextcloud_21))
|
||||
assertTrue(test(OwnCloudVersion.nextcloud_20))
|
||||
assertTrue(test(OwnCloudVersion.nextcloud_19))
|
||||
assertTrue(test(OwnCloudVersion.nextcloud_18))
|
||||
assertTrue(test(OwnCloudVersion.nextcloud_17))
|
||||
assertTrue(test(OwnCloudVersion.nextcloud_16))
|
||||
}
|
||||
|
||||
private fun test(version: OwnCloudVersion): Boolean {
|
||||
return CapabilityUtils.checkOutdatedWarning(targetContext.resources, version, false)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue