-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13456 from nextcloud/refactor/setup-dialog
Refactor Setup Dialog
- Loading branch information
Showing
15 changed files
with
185 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3wSNveXIhRsKl86pUnL7\n/AIAH+IJya5vqP0lv+yCBkd728szrLRYRWxPNC4VDbzyRHBr0RWj0ibsLJvU2OeF\n5p4er1tMIGgB0AEwiuDXBBz/RrxjPdhlilq7mvvqeUS2M3t5iroIxM6VEGQrhVrb\nb3U+7c6Lt7dIHAHEVOXnZiHYhhhduEmIzbsrAZFuMjlnWXTiMhuuWBf6t1nPyCHa\noA96loWibbvIsMegC73J3Ej5sgLkz/TjlrYmv6p3RGAEs74KHfggy4Fzw9TxBAAY\nyIX0NY8Rhb10XKrOSXrvRYuL/wkJ3P5XVK/NfsuLKbrhuUjDSgKplY9xCtOSaEPJ\nVQIDAQAB\n-----END PUBLIC KEY-----", | ||
"certificate": "-----BEGIN CERTIFICATE-----\nMIIC9DCCAdygAwIBAgIBADANBgkqhkiG9w0BAQUFADATMREwDwYDVQQDDAhuYXJy\nYXRvcjAeFw0yNDA1MjcxMzEyNDVaFw00NDA1MjIxMzEyNDVaMBMxETAPBgNVBAMM\nCG5hcnJhdG9yMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjA2EEYeN\nc3BdVDPkJK/AWPB1kd9sWAonZt/V4sbAE6fGy4qU21xfInZQaMHyhqdMXga10juE\nJLPKuyyRz+qijASryW+WzCJ3A9QeHHO+CiLc09yuB80JRpH0oHsol6WrdO1n5zuH\nlPtAdCwi4OeRmvazfBysbP2gaUl7DxackqbMei8a0MoyDxUB11hp0tpyYAU1/sXZ\nLGh4R4q4/F2KlSeYY9D62OJ8wNTgv9AYF/HRxXxWmVftB1En/DdvVr1zJGraHiRm\nQbaEnmsSGK8QHHm4h37cfD5f7rW1WO5A8KyJKwluOIXjMfL1YijAPpNW6EHhSlfT\n5RVLCHxvrzMHewIDAQABo1MwUTAdBgNVHQ4EFgQUzT6RHEHtpdjr8N3ABJK0wpFt\n1PMwHwYDVR0jBBgwFoAUzT6RHEHtpdjr8N3ABJK0wpFt1PMwDwYDVR0TAQH/BAUw\nAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAJ1q3CSBHrLauOZAD56BeElgh/ahbegsE\nZ4w7q4FdhkixLIwe6yrMmSvpNTuxRDHUrVLXxQmN0X3Yb7BLNXnnIUfH9EozaV7p\nYjOLWD2XCfLJmpGIBVvqZhyZrTl69jkBaVHF78aj1vt+qKihHUAVnG+qGH0PFms+\nG0KyY8bNYg+2HQiSTva1kgGPUA/8nQNj3lwi+r03tgqbw88fQKRPeMUJWdh/yV9U\noBdPHt+TBsUFZQZP3lBBS9lYhDT9fNoGX12WPAEUjYNhHVX+Qdup8Mg3aUMITXXJ\nvlGsN1SknlLoN0RwBFbyH9BCzqAdEIj5qQM3YDzIIyyy6AAnswNEUg==\n-----END CERTIFICATE-----" | ||
} |
45 changes: 45 additions & 0 deletions
45
app/src/androidTest/java/com/nextcloud/utils/CertificateValidatorTests.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
* Nextcloud - Android Client | ||
* | ||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <[email protected]> | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
package com.nextcloud.utils | ||
|
||
import androidx.test.platform.app.InstrumentationRegistry | ||
import com.google.gson.Gson | ||
import com.owncloud.android.datamodel.Credentials | ||
import com.owncloud.android.ui.dialog.setupEncryption.CertificateValidator | ||
import org.junit.After | ||
import org.junit.Before | ||
import org.junit.Test | ||
import java.io.InputStreamReader | ||
|
||
class CertificateValidatorTests { | ||
|
||
private var sut: CertificateValidator? = null | ||
|
||
@Before | ||
fun setup() { | ||
sut = CertificateValidator() | ||
} | ||
|
||
@After | ||
fun destroy() { | ||
sut = null | ||
} | ||
|
||
@Test | ||
fun testValidateWhenGivenValidServerKeyAndCertificateShouldReturnTrue() { | ||
val inputStream = | ||
InstrumentationRegistry.getInstrumentation().context.assets.open("credentials.json") | ||
|
||
val credentials = InputStreamReader(inputStream).use { reader -> | ||
Gson().fromJson(reader, Credentials::class.java) | ||
} | ||
|
||
val isCertificateValid = sut?.validate(credentials.publicKey, credentials.certificate) ?: false | ||
assert(isCertificateValid) | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
app/src/androidTest/java/com/owncloud/android/datamodel/Credentials.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/* | ||
* Nextcloud - Android Client | ||
* | ||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <[email protected]> | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
package com.owncloud.android.datamodel | ||
|
||
data class Credentials( | ||
val publicKey: String, | ||
val certificate: String | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
app/src/main/java/com/owncloud/android/ui/dialog/setupEncryption/CertificateValidator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* Nextcloud - Android Client | ||
* | ||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <[email protected]> | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
package com.owncloud.android.ui.dialog.setupEncryption | ||
|
||
import android.util.Base64 | ||
import com.nextcloud.utils.extensions.getContentOfPublicKey | ||
import com.owncloud.android.lib.common.utils.Log_OC | ||
import java.io.ByteArrayInputStream | ||
import java.security.KeyFactory | ||
import java.security.cert.CertificateFactory | ||
import java.security.cert.X509Certificate | ||
import java.security.spec.X509EncodedKeySpec | ||
import javax.inject.Inject | ||
|
||
@Suppress("EmptyClassBlock") | ||
class CertificateValidator @Inject constructor() { | ||
private val tag = "CertificateValidator" | ||
|
||
/** | ||
* Validates certificate with given public key | ||
* | ||
* @param serverPublicKeyString Public key with header | ||
* @param certificate Certificate in PEM format | ||
*/ | ||
@Suppress("TooGenericExceptionCaught") | ||
fun validate(serverPublicKeyString: String, certificate: String): Boolean { | ||
val contentOfServerKey = serverPublicKeyString.getContentOfPublicKey() | ||
|
||
return try { | ||
val decodedPublicKey = Base64.decode(contentOfServerKey, Base64.NO_WRAP) | ||
|
||
val keySpec = X509EncodedKeySpec(decodedPublicKey) | ||
val keyFactory = KeyFactory.getInstance("RSA") | ||
val serverPublicKey = keyFactory.generatePublic(keySpec) | ||
|
||
val certificateFactory = CertificateFactory.getInstance("X.509") | ||
val certificateInputStream = ByteArrayInputStream(certificate.toByteArray()) | ||
val x509Certificate = certificateFactory.generateCertificate(certificateInputStream) as X509Certificate | ||
|
||
// Check date of the certificate | ||
x509Certificate.checkValidity() | ||
|
||
// Verify certificate with serverPublicKey | ||
x509Certificate.verify(serverPublicKey) | ||
Log_OC.d(tag, "Client certificate is valid against server public key") | ||
true | ||
} catch (e: Exception) { | ||
Log_OC.d(tag, "Client certificate is not valid against the server public key") | ||
false | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
* SPDX-FileCopyrightText: 2024 Alper Ozturk <[email protected]> | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
package com.owncloud.android.ui.dialog | ||
package com.owncloud.android.ui.dialog.setupEncryption | ||
|
||
import android.accounts.AccountManager | ||
import android.annotation.SuppressLint | ||
|
@@ -22,6 +22,7 @@ import com.google.android.material.button.MaterialButton | |
import com.google.android.material.dialog.MaterialAlertDialogBuilder | ||
import com.nextcloud.client.account.User | ||
import com.nextcloud.client.di.Injectable | ||
import com.nextcloud.client.network.ClientFactory | ||
import com.nextcloud.utils.extensions.getParcelableArgument | ||
import com.owncloud.android.R | ||
import com.owncloud.android.databinding.SetupEncryptionDialogBinding | ||
|
@@ -33,6 +34,7 @@ import com.owncloud.android.lib.resources.e2ee.CsrHelper | |
import com.owncloud.android.lib.resources.users.DeletePublicKeyRemoteOperation | ||
import com.owncloud.android.lib.resources.users.GetPrivateKeyRemoteOperation | ||
import com.owncloud.android.lib.resources.users.GetPublicKeyRemoteOperation | ||
import com.owncloud.android.lib.resources.users.GetServerPublicKeyRemoteOperation | ||
import com.owncloud.android.lib.resources.users.SendCSRRemoteOperation | ||
import com.owncloud.android.lib.resources.users.StorePrivateKeyRemoteOperation | ||
import com.owncloud.android.utils.EncryptionUtils | ||
|
@@ -50,6 +52,14 @@ class SetupEncryptionDialogFragment : DialogFragment(), Injectable { | |
@Inject | ||
lateinit var viewThemeUtils: ViewThemeUtils | ||
|
||
@JvmField | ||
@Inject | ||
var clientFactory: ClientFactory? = null | ||
|
||
@JvmField | ||
@Inject | ||
var certificateValidator: CertificateValidator? = null | ||
|
||
private var user: User? = null | ||
private var arbitraryDataProvider: ArbitraryDataProvider? = null | ||
private var positiveButton: MaterialButton? = null | ||
|
@@ -270,34 +280,50 @@ class SetupEncryptionDialogFragment : DialogFragment(), Injectable { | |
// if available | ||
// - store public key | ||
// - decrypt private key, store unencrypted private key in database | ||
|
||
val context = mWeakContext.get() ?: return null | ||
val publicKeyOperation = GetPublicKeyRemoteOperation() | ||
val certificateOperation = GetPublicKeyRemoteOperation() | ||
val serverPublicKeyOperation = GetServerPublicKeyRemoteOperation() | ||
val user = user ?: return null | ||
|
||
val publicKeyResult = publicKeyOperation.executeNextcloudClient(user, context) | ||
val privateKeyOperation = GetPrivateKeyRemoteOperation() | ||
val privateKeyResult = privateKeyOperation.executeNextcloudClient(user, context) | ||
val certificateResult = certificateOperation.executeNextcloudClient(user, context) | ||
val serverPublicKeyResult = serverPublicKeyOperation.executeNextcloudClient(user, context) | ||
|
||
if (!publicKeyResult.isSuccess) { | ||
var encryptedPrivateKey: com.owncloud.android.lib.ocs.responses.PrivateKey? = null | ||
if (privateKeyResult.isSuccess) { | ||
encryptedPrivateKey = privateKeyResult.resultData | ||
} | ||
|
||
if (!certificateResult.isSuccess || !serverPublicKeyResult.isSuccess) { | ||
Log_OC.d(TAG, "certificate or server public key not fetched") | ||
return null | ||
} | ||
|
||
Log_OC.d(TAG, "public key successful downloaded for " + user.accountName) | ||
val serverKey = serverPublicKeyResult.resultData | ||
val certificateAsString = certificateResult.resultData | ||
val isCertificateValid = certificateValidator?.validate(serverKey, certificateAsString) | ||
|
||
if (isCertificateValid == false) { | ||
Log_OC.d(TAG, "Could not save certificate, certificate is not valid") | ||
return null | ||
} | ||
|
||
if (arbitraryDataProvider == null) { | ||
return null | ||
} | ||
|
||
val publicKeyFromServer = publicKeyResult.resultData | ||
arbitraryDataProvider?.storeOrUpdateKeyValue( | ||
user.accountName, | ||
EncryptionUtils.PUBLIC_KEY, | ||
publicKeyFromServer | ||
certificateAsString | ||
) | ||
|
||
val privateKeyResult = GetPrivateKeyRemoteOperation().executeNextcloudClient(user, context) | ||
if (privateKeyResult.isSuccess) { | ||
Log_OC.d(TAG, "private key successful downloaded for " + user.accountName) | ||
keyResult = KEY_EXISTING_USED | ||
return privateKeyResult.resultData.getKey() | ||
return encryptedPrivateKey?.getKey() | ||
} | ||
|
||
return null | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters