From 78a50548abc5ca89fbec2631c0d69ec0aa8db5ea Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 5 Apr 2022 09:19:58 +0200 Subject: [PATCH] optionally allow extended key validation in `RecoveryKeyFactory#validateRecoveryKey` --- .../ui/recoverykey/RecoveryKeyFactory.java | 25 ++++++++++++++++--- .../recoverykey/RecoveryKeyFactoryTest.java | 18 +++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyFactory.java b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyFactory.java index 311f5746e..a1180dd9f 100644 --- a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyFactory.java +++ b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyFactory.java @@ -7,6 +7,7 @@ import org.cryptomator.cryptolib.api.CryptoException; import org.cryptomator.cryptolib.api.InvalidPassphraseException; import org.cryptomator.cryptolib.api.Masterkey; import org.cryptomator.cryptolib.common.MasterkeyFileAccess; +import org.jetbrains.annotations.Nullable; import javax.inject.Inject; import javax.inject.Singleton; @@ -16,6 +17,7 @@ import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Collection; +import java.util.function.Predicate; import static org.cryptomator.common.Constants.MASTERKEY_BACKUP_SUFFIX; import static org.cryptomator.common.Constants.MASTERKEY_FILENAME; @@ -102,12 +104,29 @@ public class RecoveryKeyFactory { * @return true if this seems to be a legitimate recovery key */ public boolean validateRecoveryKey(String recoveryKey) { + return validateRecoveryKey(recoveryKey, null); + } + + /** + * Checks whether a String is a syntactically correct recovery key with a valid checksum and passes the extended validation. + * + * @param recoveryKey A word sequence which might be a recovery key + * @param extendedValidation Additional verification of the decoded key (optional) + * @return true if this seems to be a legitimate recovery key and passes the extended validation + */ + public boolean validateRecoveryKey(String recoveryKey, @Nullable Predicate extendedValidation) { + byte[] key = new byte[0]; try { - byte[] key = decodeRecoveryKey(recoveryKey); - Arrays.fill(key, (byte) 0x00); - return true; + key = decodeRecoveryKey(recoveryKey); + if (extendedValidation != null) { + return extendedValidation.test(key); + } else { + return true; + } } catch (IllegalArgumentException e) { return false; + } finally { + Arrays.fill(key, (byte) 0x00); } } diff --git a/src/test/java/org/cryptomator/ui/recoverykey/RecoveryKeyFactoryTest.java b/src/test/java/org/cryptomator/ui/recoverykey/RecoveryKeyFactoryTest.java index c9061451e..ea5d0fd3a 100644 --- a/src/test/java/org/cryptomator/ui/recoverykey/RecoveryKeyFactoryTest.java +++ b/src/test/java/org/cryptomator/ui/recoverykey/RecoveryKeyFactoryTest.java @@ -7,10 +7,13 @@ import org.cryptomator.cryptolib.common.MasterkeyFileAccess; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mockito; import java.io.IOException; import java.nio.file.Path; +import java.util.function.Predicate; public class RecoveryKeyFactoryTest { @@ -75,4 +78,19 @@ public class RecoveryKeyFactoryTest { Assertions.assertTrue(result); } + @ParameterizedTest(name = "success = {0}") + @DisplayName("validateRecoveryKey() with extended validation") + @ValueSource(booleans = {true, false}) + public void testValidateValidateRecoveryKeyWithValidKey(boolean extendedValidationResult) { + Predicate validator = Mockito.mock(Predicate.class); + Mockito.doReturn(extendedValidationResult).when(validator).test(Mockito.any()); + boolean result = inTest.validateRecoveryKey(""" + pathway lift abuse plenty export texture gentleman landscape beyond ceiling around leaf cafe charity \ + border breakdown victory surely computer cat linger restrict infer crowd live computer true written amazed \ + investor boot depth left theory snow whereby terminal weekly reject happiness circuit partial cup ad \ + """, validator); + Mockito.verify(validator).test(Mockito.any()); + Assertions.assertEquals(extendedValidationResult, result); + } + } \ No newline at end of file