|
@@ -6,11 +6,11 @@ import java.nio.file.Path;
|
|
|
import java.nio.file.StandardCopyOption;
|
|
|
import java.nio.file.StandardOpenOption;
|
|
|
|
|
|
-import javax.inject.Provider;
|
|
|
-
|
|
|
-import org.cryptomator.crypto.engine.Cryptor;
|
|
|
-import org.cryptomator.crypto.engine.InvalidPassphraseException;
|
|
|
-import org.cryptomator.crypto.engine.UnsupportedVaultFormatException;
|
|
|
+import org.cryptomator.cryptolib.api.Cryptor;
|
|
|
+import org.cryptomator.cryptolib.api.CryptorProvider;
|
|
|
+import org.cryptomator.cryptolib.api.InvalidPassphraseException;
|
|
|
+import org.cryptomator.cryptolib.api.KeyFile;
|
|
|
+import org.cryptomator.cryptolib.api.UnsupportedVaultFormatException;
|
|
|
import org.cryptomator.filesystem.crypto.Constants;
|
|
|
import org.cryptomator.ui.settings.Localization;
|
|
|
import org.slf4j.Logger;
|
|
@@ -20,12 +20,16 @@ public abstract class UpgradeStrategy {
|
|
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(UpgradeStrategy.class);
|
|
|
|
|
|
- protected final Provider<Cryptor> cryptorProvider;
|
|
|
+ protected final CryptorProvider cryptorProvider;
|
|
|
protected final Localization localization;
|
|
|
+ protected final int vaultVersionBeforeUpgrade;
|
|
|
+ protected final int vaultVersionAfterUpgrade;
|
|
|
|
|
|
- UpgradeStrategy(Provider<Cryptor> cryptorProvider, Localization localization) {
|
|
|
+ UpgradeStrategy(CryptorProvider cryptorProvider, Localization localization, int vaultVersionBeforeUpgrade, int vaultVersionAfterUpgrade) {
|
|
|
this.cryptorProvider = cryptorProvider;
|
|
|
this.localization = localization;
|
|
|
+ this.vaultVersionBeforeUpgrade = vaultVersionBeforeUpgrade;
|
|
|
+ this.vaultVersionAfterUpgrade = vaultVersionAfterUpgrade;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -37,27 +41,29 @@ public abstract class UpgradeStrategy {
|
|
|
* Upgrades a vault. Might take a moment, should be run in a background thread.
|
|
|
*/
|
|
|
public void upgrade(Vault vault, CharSequence passphrase) throws UpgradeFailedException {
|
|
|
- final Cryptor cryptor = cryptorProvider.get();
|
|
|
+ Cryptor cryptor = null;
|
|
|
try {
|
|
|
final Path masterkeyFile = vault.path().getValue().resolve(Constants.MASTERKEY_FILENAME);
|
|
|
final byte[] masterkeyFileContents = Files.readAllBytes(masterkeyFile);
|
|
|
- cryptor.readKeysFromMasterkeyFile(masterkeyFileContents, passphrase);
|
|
|
+ cryptor = cryptorProvider.createFromKeyFile(KeyFile.parse(masterkeyFileContents), passphrase, vaultVersionBeforeUpgrade);
|
|
|
// create backup, as soon as we know the password was correct:
|
|
|
final Path masterkeyBackupFile = vault.path().getValue().resolve(Constants.MASTERKEY_BACKUP_FILENAME);
|
|
|
Files.copy(masterkeyFile, masterkeyBackupFile, StandardCopyOption.REPLACE_EXISTING);
|
|
|
// do stuff:
|
|
|
upgrade(vault, cryptor);
|
|
|
// write updated masterkey file:
|
|
|
- final byte[] upgradedMasterkeyFileContents = cryptor.writeKeysToMasterkeyFile(passphrase);
|
|
|
- final Path masterkeyFileAfterUpgrading = vault.path().getValue().resolve(Constants.MASTERKEY_FILENAME); // path may have changed
|
|
|
- Files.write(masterkeyFileAfterUpgrading, upgradedMasterkeyFileContents, StandardOpenOption.TRUNCATE_EXISTING);
|
|
|
+ final byte[] upgradedMasterkeyFileContents = cryptor.writeKeysToMasterkeyFile(passphrase, vaultVersionAfterUpgrade).serialize();
|
|
|
+ final Path masterkeyFileAfterUpgrade = vault.path().getValue().resolve(Constants.MASTERKEY_FILENAME); // path may have changed
|
|
|
+ Files.write(masterkeyFileAfterUpgrade, upgradedMasterkeyFileContents, StandardOpenOption.TRUNCATE_EXISTING);
|
|
|
} catch (InvalidPassphraseException e) {
|
|
|
throw new UpgradeFailedException(localization.getString("unlock.errorMessage.wrongPassword"));
|
|
|
} catch (IOException | UnsupportedVaultFormatException e) {
|
|
|
LOG.warn("Upgrade failed.", e);
|
|
|
throw new UpgradeFailedException("Upgrade failed. Details in log message.");
|
|
|
} finally {
|
|
|
- cryptor.destroy();
|
|
|
+ if (cryptor != null) {
|
|
|
+ cryptor.destroy();
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -68,7 +74,21 @@ public abstract class UpgradeStrategy {
|
|
|
*
|
|
|
* @return <code>true</code> if and only if the vault can be migrated to a newer version without the risk of data losses.
|
|
|
*/
|
|
|
- public abstract boolean isApplicable(Vault vault);
|
|
|
+ public boolean isApplicable(Vault vault) {
|
|
|
+ final Path masterkeyFile = vault.path().getValue().resolve(Constants.MASTERKEY_FILENAME);
|
|
|
+ try {
|
|
|
+ if (Files.isRegularFile(masterkeyFile)) {
|
|
|
+ byte[] masterkeyFileContents = Files.readAllBytes(masterkeyFile);
|
|
|
+ return KeyFile.parse(masterkeyFileContents).getVersion() == vaultVersionBeforeUpgrade;
|
|
|
+ } else {
|
|
|
+ LOG.warn("Not a file: {}", masterkeyFile);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ LOG.warn("Could not determine, whether upgrade is applicable.", e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* Thrown when data migration failed.
|