Browse Source

improve RecoverUtil and determineVaultState

Jan-Peter Klein 3 tháng trước cách đây
mục cha
commit
895614353e

+ 41 - 46
src/main/java/org/cryptomator/common/RecoverUtil.java

@@ -11,10 +11,8 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
 import java.security.SecureRandom;
-import java.util.Optional;
 import java.util.stream.Stream;
 
-import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
 import static org.cryptomator.cryptofs.common.Constants.DATA_DIR_NAME;
 import static org.cryptomator.cryptolib.api.CryptorProvider.Scheme.SIV_CTRMAC;
 import static org.cryptomator.cryptolib.api.CryptorProvider.Scheme.SIV_GCM;
@@ -22,64 +20,61 @@ import static org.cryptomator.cryptolib.api.CryptorProvider.Scheme.SIV_GCM;
 public class RecoverUtil {
 
 	public static CryptorProvider.Scheme detectCipherCombo(byte[] masterkey, Path pathToVault) {
-		try {
-			Path dDirPath = pathToVault.resolve(DATA_DIR_NAME);
-
-			Optional<Path> firstC9rFile;
-			try (Stream<Path> paths = Files.walk(dDirPath)) {
-				firstC9rFile = paths.filter(path -> path.toString().endsWith(".c9r")).findFirst();
-			}
-			if (firstC9rFile.isEmpty()) {
-				throw new IllegalStateException("No .c9r file found.");
-			}
-
-			Path c9rFile = firstC9rFile.get();
-			if (canDecryptFileHeader(c9rFile, new Masterkey(masterkey), SIV_GCM)) {
-				return SIV_GCM;
-			}
-			if (canDecryptFileHeader(c9rFile, new Masterkey(masterkey), SIV_CTRMAC)) {
-				return SIV_CTRMAC;
-			}
-
-			return null;
+		try (Stream<Path> paths = Files.walk(pathToVault.resolve(DATA_DIR_NAME))) {
+			return paths.filter(path -> path.toString().endsWith(".c9r"))
+					.findFirst()
+					.map(c9rFile -> determineScheme(c9rFile, masterkey))
+					.orElseThrow(() -> new IllegalStateException("No .c9r file found."));
 		} catch (IOException e) {
 			throw new IllegalStateException("Failed to detect cipher combo.", e);
 		}
 	}
 
-	private static boolean canDecryptFileHeader(Path c9rFile, Masterkey masterkey, CryptorProvider.Scheme scheme) {
-		try (Cryptor cryptor = CryptorProvider.forScheme(scheme).provide(masterkey, SecureRandom.getInstanceStrong())) {
+	private static CryptorProvider.Scheme determineScheme(Path c9rFile, byte[] masterkey) {
+		try {
 			ByteBuffer header = ByteBuffer.wrap(Files.readAllBytes(c9rFile));
-			cryptor.fileHeaderCryptor().decryptHeader(header);
+			return tryDecrypt(header, new Masterkey(masterkey), SIV_GCM) ? SIV_GCM :
+					tryDecrypt(header, new Masterkey(masterkey), SIV_CTRMAC) ? SIV_CTRMAC : null;
+		} catch (IOException e) {
+			return null;
+		}
+	}
+
+	private static boolean tryDecrypt(ByteBuffer header, Masterkey masterkey, CryptorProvider.Scheme scheme) {
+		try (Cryptor cryptor = CryptorProvider.forScheme(scheme).provide(masterkey, SecureRandom.getInstanceStrong())) {
+			cryptor.fileHeaderCryptor().decryptHeader(header.duplicate());
 			return true;
 		} catch (Exception e) {
 			return false;
 		}
 	}
 
-	public static VaultState.Value tryBackUpConfig(Path pathToConfig, VaultState.Value vaultState) {
-		try (Stream<Path> files = Files.list(pathToConfig.getParent())) {
-			Path backupFile = files.filter(file -> {
-				String fileName = file.getFileName().toString();
-				return switch (vaultState) {
-					case VAULT_CONFIG_MISSING -> fileName.startsWith("vault.cryptomator") && fileName.endsWith(".bkup");
-					case MASTERKEY_MISSING -> fileName.startsWith("masterkey.cryptomator") && fileName.endsWith(".bkup");
-					default -> false;
-				};
-			}).findFirst().orElse(null);
+	public static boolean restoreBackupIfAvailable(Path configPath, VaultState.Value vaultState) {
+		try (Stream<Path> files = Files.list(configPath.getParent())) {
+			return files
+					.filter(file -> matchesBackupFile(file.getFileName().toString(), vaultState))
+					.findFirst()
+					.map(backupFile -> copyBackupFile(backupFile, configPath))
+					.orElse(false);
+		} catch (IOException e) {
+			return false;
+		}
+	}
 
-			if (backupFile != null) {
-				try {
-					Files.copy(backupFile, pathToConfig, StandardCopyOption.REPLACE_EXISTING);
-					return LOCKED;
-				} catch (IOException e) {
-					return vaultState;
-				}
-			} else {
-				return vaultState;
-			}
+	private static boolean matchesBackupFile(String fileName, VaultState.Value vaultState) {
+		return switch (vaultState) {
+			case VAULT_CONFIG_MISSING -> fileName.startsWith("vault.cryptomator") && fileName.endsWith(".bkup");
+			case MASTERKEY_MISSING -> fileName.startsWith("masterkey.cryptomator") && fileName.endsWith(".bkup");
+			default -> false;
+		};
+	}
+
+	private static boolean copyBackupFile(Path backupFile, Path configPath) {
+		try {
+			Files.copy(backupFile, configPath, StandardCopyOption.REPLACE_EXISTING);
+			return true;
 		} catch (IOException e) {
-			return vaultState;
+			return false;
 		}
 	}
 

+ 21 - 7
src/main/java/org/cryptomator/common/vaults/VaultListManager.java

@@ -172,19 +172,33 @@ public class VaultListManager {
 	}
 
 	private static VaultState.Value determineVaultState(Path pathToVault, VaultSettings vaultSettings) throws IOException {
-		Path pathToVaultConfig = Path.of(pathToVault.toString(),"vault.cryptomator");
-		Path pathToMasterkey = Path.of(pathToVault.toString(),"masterkey.cryptomator");
+		Path pathToVaultConfig = pathToVault.resolve("vault.cryptomator");
+		Path pathToMasterkey = pathToVault.resolve("masterkey.cryptomator");
 
-		if (!Files.exists(pathToVault)) {
+		if (Files.notExists(pathToVault)) {
 			return VaultState.Value.MISSING;
 		}
-		else if (Files.notExists(pathToVaultConfig)) {
-			return RecoverUtil.tryBackUpConfig(pathToVaultConfig, VAULT_CONFIG_MISSING);
+
+		boolean vaultConfigRestored = Files.notExists(pathToVaultConfig) &&
+				RecoverUtil.restoreBackupIfAvailable(pathToVaultConfig, VaultState.Value.VAULT_CONFIG_MISSING);
+
+		boolean masterkeyRestored = Files.notExists(pathToMasterkey) &&
+				KeyLoadingStrategy.isMasterkeyFileVault(vaultSettings.lastKnownKeyLoader.get()) &&
+				RecoverUtil.restoreBackupIfAvailable(pathToMasterkey, VaultState.Value.MASTERKEY_MISSING);
+
+		if (vaultConfigRestored || masterkeyRestored) {
+			return LOCKED;
 		}
-		else if (Files.notExists(pathToMasterkey) &&
+
+		if (Files.notExists(pathToVaultConfig)) {
+			return VaultState.Value.VAULT_CONFIG_MISSING;
+		}
+
+		if (Files.notExists(pathToMasterkey) &&
 				KeyLoadingStrategy.isMasterkeyFileVault(vaultSettings.lastKnownKeyLoader.get())) {
-			return RecoverUtil.tryBackUpConfig(pathToMasterkey, MASTERKEY_MISSING);
+			return VaultState.Value.MASTERKEY_MISSING;
 		}
+
 		return checkDirStructure(pathToVault);
 	}