Skip to content

Commit 51bdba5

Browse files
committed
Merge branch 'release/2.2.0'
2 parents 9759128 + 5f23672 commit 51bdba5

File tree

8 files changed

+46
-52
lines changed

8 files changed

+46
-52
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<modelVersion>4.0.0</modelVersion>
33
<groupId>org.cryptomator</groupId>
44
<artifactId>cryptofs</artifactId>
5-
<version>2.1.1</version>
5+
<version>2.2.0</version>
66
<name>Cryptomator Crypto Filesystem</name>
77
<description>This library provides the Java filesystem provider used by Cryptomator.</description>
88
<url>https://github.com/cryptomator/cryptofs</url>

src/main/java/org/cryptomator/cryptofs/common/MasterkeyBackupHelper.java renamed to src/main/java/org/cryptomator/cryptofs/common/BackupHelper.java

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717
import java.security.NoSuchAlgorithmException;
1818

1919
/**
20-
* Utility class for generating a suffix for the backup file to make it unique to its original master key file.
20+
* Utility class for generating a suffix for the backup file to make it unique to its original file.
2121
*/
22-
public final class MasterkeyBackupHelper {
22+
public final class BackupHelper {
2323

24-
private static final Logger LOG = LoggerFactory.getLogger(MasterkeyBackupHelper.class);
24+
private final static long NO_MISMATCH = -1L;
25+
private static final Logger LOG = LoggerFactory.getLogger(BackupHelper.class);
2526

2627
/**
2728
* Computes the SHA-256 digest of the given byte array and returns a file suffix containing the first 4 bytes in hex string format.
@@ -40,42 +41,36 @@ public static String generateFileIdSuffix(byte[] fileBytes) {
4041
}
4142

4243
/**
43-
* Do a best-effort attempt to backup the masterkey at the given path.
44+
* Do a best-effort attempt to back up the file at the given path.
4445
* Fails silently if a _valid_ backup already exists and fails with a log entry, if any IO error occurs while creating or reading the backup file.
4546
*
46-
* @param masterKeyPath The masterkey file to backup
47-
* @throws IOException If the masterkey cannot be read.
47+
* @param path The file to back up
48+
* @throws IOException If the path cannot be read.
4849
*/
49-
public static Path attemptMasterKeyBackup(Path masterKeyPath) throws IOException {
50-
byte[] keyFileContents = Files.readAllBytes(masterKeyPath);
51-
String backupFileName = masterKeyPath.getFileName().toString() + generateFileIdSuffix(keyFileContents) + Constants.MASTERKEY_BACKUP_SUFFIX;
52-
Path backupFilePath = masterKeyPath.resolveSibling(backupFileName);
50+
public static Path attemptBackup(Path path) throws IOException {
51+
byte[] fileContents = Files.readAllBytes(path);
52+
final String fileToBackup = path.getFileName().toString();
53+
String backupFileName = fileToBackup + generateFileIdSuffix(fileContents) + Constants.BACKUP_SUFFIX;
54+
Path backupFilePath = path.resolveSibling(backupFileName);
5355
try (WritableByteChannel ch = Files.newByteChannel(backupFilePath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)) {
54-
ch.write(ByteBuffer.wrap(keyFileContents));
56+
ch.write(ByteBuffer.wrap(fileContents));
5557
} catch (AccessDeniedException | FileAlreadyExistsException e) {
56-
assertExistingBackupMatchesContent(backupFilePath, ByteBuffer.wrap(keyFileContents));
58+
assertSameContent(backupFilePath, path);
5759
} catch (IOException e) {
58-
LOG.warn("Failed to backup valid masterkey file.");
60+
LOG.warn("Failed to backup valid {} file.", fileToBackup);
5961
}
6062
return backupFilePath;
6163
}
6264

63-
private static void assertExistingBackupMatchesContent(Path backupFilePath, ByteBuffer expectedContent) {
64-
if (Files.exists(backupFilePath)) {
65-
// TODO replace by Files.mismatch() when using JDK > 12
66-
ByteBuffer buf = ByteBuffer.allocateDirect(expectedContent.remaining() + 1);
67-
try (ReadableByteChannel ch = Files.newByteChannel(backupFilePath, StandardOpenOption.READ)) {
68-
ch.read(buf);
69-
buf.flip();
70-
if (buf.compareTo(expectedContent) != 0) {
71-
LOG.warn("Corrupt masterkey backup {}. Please replace it manually or unlock the vault on a writable storage device.", backupFilePath);
72-
} else {
73-
LOG.debug("Verified backup file: {}", backupFilePath);
74-
}
75-
} catch (IOException e) {
76-
LOG.warn("Failed to compare valid masterkey with backup file.", e);
65+
private static void assertSameContent(final Path backupFile, final Path originalFile) {
66+
try {
67+
if (Files.mismatch(backupFile, originalFile) == NO_MISMATCH) {
68+
LOG.debug("Verified backup file: {}", backupFile);
69+
} else {
70+
LOG.warn("Corrupt {} backup for: {}. Please replace it manually or unlock the vault on a writable storage device.", backupFile.getFileName(), backupFile);
7771
}
72+
} catch (IOException e) {
73+
LOG.warn("Failed to compare valid %s with backup file.".formatted(backupFile), e);
7874
}
7975
}
80-
8176
}

src/main/java/org/cryptomator/cryptofs/common/Constants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ private Constants() {
1414
}
1515

1616
public static final int VAULT_VERSION = 8;
17-
public static final String MASTERKEY_BACKUP_SUFFIX = ".bkup";
17+
public static final String BACKUP_SUFFIX = ".bkup";
1818
public static final String DATA_DIR_NAME = "d";
1919
public static final String ROOT_DIR_ID = "";
2020
public static final String RECOVERY_DIR_ID = "recovery";

src/main/java/org/cryptomator/cryptofs/migration/v6/Version6Migrator.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*******************************************************************************/
66
package org.cryptomator.cryptofs.migration.v6;
77

8-
import org.cryptomator.cryptofs.common.MasterkeyBackupHelper;
8+
import org.cryptomator.cryptofs.common.BackupHelper;
99
import org.cryptomator.cryptofs.migration.api.MigrationContinuationListener;
1010
import org.cryptomator.cryptofs.migration.api.MigrationProgressListener;
1111
import org.cryptomator.cryptofs.migration.api.Migrator;
@@ -48,11 +48,11 @@ public void migrate(Path vaultRoot, String vaultConfigFilename, String masterkey
4848
MasterkeyFileAccess masterkeyFileAccess = new MasterkeyFileAccess(new byte[0], csprng);
4949
try (Masterkey masterkey = masterkeyFileAccess.load(masterkeyFile, passphrase)) {
5050
// create backup, as soon as we know the password was correct:
51-
Path masterkeyBackupFile = MasterkeyBackupHelper.attemptMasterKeyBackup(masterkeyFile);
51+
Path masterkeyBackupFile = BackupHelper.attemptBackup(masterkeyFile);
5252
LOG.info("Backed up masterkey from {} to {}.", masterkeyFile.getFileName(), masterkeyBackupFile.getFileName());
5353

5454
progressListener.update(MigrationProgressListener.ProgressState.FINALIZING, 0.0);
55-
55+
5656
// rewrite masterkey file with normalized passphrase:
5757
masterkeyFileAccess.persist(masterkey, masterkeyFile, Normalizer.normalize(passphrase, Form.NFC), 6);
5858
LOG.info("Updated masterkey.");

src/main/java/org/cryptomator/cryptofs/migration/v7/Version7Migrator.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
import org.cryptomator.cryptofs.FileNameTooLongException;
99
import org.cryptomator.cryptofs.common.DeletingFileVisitor;
1010
import org.cryptomator.cryptofs.common.FileSystemCapabilityChecker;
11-
import org.cryptomator.cryptofs.common.MasterkeyBackupHelper;
11+
import org.cryptomator.cryptofs.common.BackupHelper;
12+
import org.cryptomator.cryptofs.migration.Migrators;
1213
import org.cryptomator.cryptofs.migration.api.MigrationContinuationListener;
1314
import org.cryptomator.cryptofs.migration.api.MigrationContinuationListener.ContinuationEvent;
1415
import org.cryptomator.cryptofs.migration.api.MigrationContinuationListener.ContinuationResult;
@@ -58,11 +59,11 @@ public Version7Migrator(SecureRandom csprng) {
5859
public void migrate(Path vaultRoot, String vaultConfigFilename, String masterkeyFilename, CharSequence passphrase, MigrationProgressListener progressListener, MigrationContinuationListener continuationListener) throws CryptoException, IOException {
5960
LOG.info("Upgrading {} from version 6 to version 7.", vaultRoot);
6061
progressListener.update(MigrationProgressListener.ProgressState.INITIALIZING, 0.0);
61-
Path masterkeyFile = vaultRoot.resolve(masterkeyFilename);
62+
final Path masterkeyFile = vaultRoot.resolve(masterkeyFilename);
6263
MasterkeyFileAccess masterkeyFileAccess = new MasterkeyFileAccess(new byte[0], csprng);
6364
try (Masterkey masterkey = masterkeyFileAccess.load(masterkeyFile, passphrase)) {
6465
// create backup, as soon as we know the password was correct:
65-
Path masterkeyBackupFile = MasterkeyBackupHelper.attemptMasterKeyBackup(masterkeyFile);
66+
Path masterkeyBackupFile = BackupHelper.attemptBackup(masterkeyFile);
6667
LOG.info("Backed up masterkey from {} to {}.", masterkeyFile.getFileName(), masterkeyBackupFile.getFileName());
6768

6869
// check file system capabilities:
@@ -76,14 +77,12 @@ public void migrate(Path vaultRoot, String vaultConfigFilename, String masterkey
7677
LOG.warn("Underlying file system only supports names with up to {} chars (required: 220). Asking for user feedback...", filenameLengthLimit);
7778
ContinuationResult result = continuationListener.continueMigrationOnEvent(ContinuationEvent.REQUIRES_FULL_VAULT_DIR_SCAN);
7879
switch (result) {
79-
case PROCEED:
80-
preMigrationVisitor = new PreMigrationVisitor(vaultRoot, true);
81-
break;
82-
case CANCEL:
80+
case PROCEED -> preMigrationVisitor = new PreMigrationVisitor(vaultRoot, true);
81+
case CANCEL -> {
8382
LOG.info("Migration canceled by user.");
8483
return;
85-
default:
86-
throw new IllegalStateException("Unexpected result " + result);
84+
}
85+
default -> throw new IllegalStateException("Unexpected result " + result);
8786
}
8887
}
8988

src/main/java/org/cryptomator/cryptofs/migration/v8/Version8Migrator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import com.auth0.jwt.JWT;
99
import com.auth0.jwt.algorithms.Algorithm;
10-
import org.cryptomator.cryptofs.common.MasterkeyBackupHelper;
10+
import org.cryptomator.cryptofs.common.BackupHelper;
1111
import org.cryptomator.cryptofs.migration.api.MigrationContinuationListener;
1212
import org.cryptomator.cryptofs.migration.api.MigrationProgressListener;
1313
import org.cryptomator.cryptofs.migration.api.Migrator;
@@ -56,7 +56,7 @@ public void migrate(Path vaultRoot, String vaultConfigFilename, String masterkey
5656
MasterkeyFileAccess masterkeyFileAccess = new MasterkeyFileAccess(new byte[0], csprng);
5757
try (Masterkey masterkey = masterkeyFileAccess.load(masterkeyFile, passphrase)) {
5858
// create backup, as soon as we know the password was correct:
59-
Path masterkeyBackupFile = MasterkeyBackupHelper.attemptMasterKeyBackup(masterkeyFile);
59+
Path masterkeyBackupFile = BackupHelper.attemptBackup(masterkeyFile);
6060
LOG.info("Backed up masterkey from {} to {}.", masterkeyFile.getFileName(), masterkeyBackupFile.getFileName());
6161

6262
// create vaultconfig.cryptomator

src/test/java/org/cryptomator/cryptofs/common/MasterkeyBackupHelperTest.java renamed to src/test/java/org/cryptomator/cryptofs/common/BackupHelperTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import java.util.Random;
1616
import java.util.stream.Stream;
1717

18-
public class MasterkeyBackupHelperTest {
18+
public class BackupHelperTest {
1919

2020
@EnabledOnOs({OS.LINUX, OS.MAC})
2121
@ParameterizedTest
@@ -24,11 +24,11 @@ public void testBackupFilePosix(byte[] contents, @TempDir Path tmp) throws IOExc
2424
Path originalFile = tmp.resolve("original");
2525
Files.write(originalFile, contents);
2626

27-
Path backupFile = MasterkeyBackupHelper.attemptMasterKeyBackup(originalFile);
27+
Path backupFile = BackupHelper.attemptBackup(originalFile);
2828
Assertions.assertArrayEquals(contents, Files.readAllBytes(backupFile));
2929

3030
Files.setPosixFilePermissions(backupFile, PosixFilePermissions.fromString("r--r--r--"));
31-
Path backupFile2 = MasterkeyBackupHelper.attemptMasterKeyBackup(originalFile);
31+
Path backupFile2 = BackupHelper.attemptBackup(originalFile);
3232
Assertions.assertEquals(backupFile, backupFile2);
3333
}
3434

@@ -39,16 +39,16 @@ public void testBackupFileWin(byte[] contents, @TempDir Path tmp) throws IOExcep
3939
Path originalFile = tmp.resolve("original");
4040
Files.write(originalFile, contents);
4141

42-
Path backupFile = MasterkeyBackupHelper.attemptMasterKeyBackup(originalFile);
42+
Path backupFile = BackupHelper.attemptBackup(originalFile);
4343
Assertions.assertArrayEquals(contents, Files.readAllBytes(backupFile));
4444

4545
Files.getFileAttributeView(backupFile, DosFileAttributeView.class).setReadOnly(true);
46-
Path backupFile2 = MasterkeyBackupHelper.attemptMasterKeyBackup(originalFile);
46+
Path backupFile2 = BackupHelper.attemptBackup(originalFile);
4747
Assertions.assertEquals(backupFile, backupFile2);
4848
}
4949

5050
public static Stream<byte[]> createRandomBytes() {
51-
Random rnd = new Random(42l);
51+
Random rnd = new Random(42L);
5252
return Stream.generate(() -> {
5353
byte[] bytes = new byte[100];
5454
rnd.nextBytes(bytes);

src/test/java/org/cryptomator/cryptofs/migration/v6/Version6MigratorTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import com.google.common.jimfs.Configuration;
44
import com.google.common.jimfs.Jimfs;
55
import org.cryptomator.cryptofs.common.Constants;
6-
import org.cryptomator.cryptofs.common.MasterkeyBackupHelper;
6+
import org.cryptomator.cryptofs.common.BackupHelper;
77
import org.cryptomator.cryptofs.migration.api.Migrator;
88
import org.cryptomator.cryptofs.mocks.NullSecureRandom;
99
import org.cryptomator.cryptolib.api.CryptoException;
@@ -58,7 +58,7 @@ public void testMigrate() throws IOException, CryptoException {
5858
byte[] beforeMigration = Files.readAllBytes(masterkeyFile);
5959

6060
Files.write(masterkeyFile, beforeMigration);
61-
Path masterkeyBackupFile = pathToVault.resolve("masterkey.cryptomator" + MasterkeyBackupHelper.generateFileIdSuffix(beforeMigration) + Constants.MASTERKEY_BACKUP_SUFFIX);
61+
Path masterkeyBackupFile = pathToVault.resolve("masterkey.cryptomator" + BackupHelper.generateFileIdSuffix(beforeMigration) + Constants.BACKUP_SUFFIX);
6262

6363
Migrator migrator = new Version6Migrator(csprng);
6464
migrator.migrate(pathToVault, null, "masterkey.cryptomator", oldPassword);

0 commit comments

Comments
 (0)