Skip to content

Commit 1ec3005

Browse files
Merge branch 'release/1.8.7'
2 parents fa335fa + af65bc9 commit 1ec3005

File tree

7 files changed

+40
-9
lines changed

7 files changed

+40
-9
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>1.8.6</version>
5+
<version>1.8.7</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>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.cryptomator.cryptofs;
2+
3+
import com.google.common.io.BaseEncoding;
4+
5+
import java.security.MessageDigest;
6+
import java.security.NoSuchAlgorithmException;
7+
8+
/**
9+
* Utility class for generating a suffix for the backup file to make it unique to its original master key file.
10+
*/
11+
public class BackupUtil {
12+
13+
/**
14+
* Computes the SHA-256 digest of the given byte array and returns a file suffix containing the first 4 bytes in hex string format.
15+
*
16+
* @param fileBytes the input byte for which the digest is computed
17+
* @return "." + first 4 bytes of SHA-256 digest in hex string format
18+
*/
19+
public static String generateFileIdSuffix(byte[] fileBytes) {
20+
try {
21+
MessageDigest md = MessageDigest.getInstance("SHA-256");
22+
byte[] digest = md.digest(fileBytes);
23+
return "." + BaseEncoding.base16().encode(digest, 0, 4);
24+
} catch (NoSuchAlgorithmException e) {
25+
throw new IllegalStateException("Every Java Platform must support the Message Digest algorithm SHA-256", e);
26+
}
27+
}
28+
}

src/main/java/org/cryptomator/cryptofs/ConflictResolver.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,18 @@ private Path resolveConflict(Path conflictingPath, String ciphertextFileName, St
103103
* @param conflictingPath The path to the potentially conflicting file.
104104
* @param ciphertext The (previously inflated) ciphertext name of the file without any preceeding directory prefix.
105105
* @param dirId The directory id of the file's parent directory.
106-
* @param dirPrefix The directory prefix (if the conflicting file is a directory file) or an empty string.
106+
* @param typePrefix The prefix (if the conflicting file is a directory file or a symlink) or an empty string.
107107
* @return The new path after renaming the conflicting file.
108108
* @throws IOException
109109
*/
110-
private Path renameConflictingFile(Path canonicalPath, Path conflictingPath, String ciphertext, String dirId, String dirPrefix) throws IOException {
110+
private Path renameConflictingFile(Path canonicalPath, Path conflictingPath, String ciphertext, String dirId, String typePrefix) throws IOException {
111111
try {
112112
String cleartext = cryptor.fileNameCryptor().decryptFilename(ciphertext, dirId.getBytes(StandardCharsets.UTF_8));
113113
Path alternativePath = canonicalPath;
114114
for (int i = 1; Files.exists(alternativePath); i++) {
115115
String alternativeCleartext = cleartext + " (Conflict " + i + ")";
116116
String alternativeCiphertext = cryptor.fileNameCryptor().encryptFilename(alternativeCleartext, dirId.getBytes(StandardCharsets.UTF_8));
117-
String alternativeCiphertextFileName = dirPrefix + alternativeCiphertext;
117+
String alternativeCiphertextFileName = typePrefix + alternativeCiphertext;
118118
if (alternativeCiphertextFileName.length() > SHORT_NAMES_MAX_LENGTH) {
119119
alternativeCiphertextFileName = longFileNameProvider.deflate(alternativeCiphertextFileName);
120120
}

src/main/java/org/cryptomator/cryptofs/CryptoFileSystemModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ class CryptoFileSystemModule {
2626
public Cryptor provideCryptor(CryptorProvider cryptorProvider, @PathToVault Path pathToVault, CryptoFileSystemProperties properties, ReadonlyFlag readonlyFlag) {
2727
try {
2828
Path masterKeyPath = pathToVault.resolve(properties.masterkeyFilename());
29-
Path backupKeyPath = pathToVault.resolve(properties.masterkeyFilename() + Constants.MASTERKEY_BACKUP_SUFFIX);
3029
assert Files.exists(masterKeyPath); // since 1.3.0 a file system can only be created for existing vaults. initialization is done before.
3130
byte[] keyFileContents = Files.readAllBytes(masterKeyPath);
31+
Path backupKeyPath = pathToVault.resolve(properties.masterkeyFilename() + BackupUtil.generateFileIdSuffix(keyFileContents) + Constants.MASTERKEY_BACKUP_SUFFIX);
3232
Cryptor cryptor = cryptorProvider.createFromKeyFile(KeyFile.parse(keyFileContents), properties.passphrase(), properties.pepper(), Constants.VAULT_VERSION);
3333
backupMasterkeyFileIfRequired(masterKeyPath, backupKeyPath, readonlyFlag);
3434
return cryptor;

src/main/java/org/cryptomator/cryptofs/CryptoFileSystemProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,9 @@ public static void changePassphrase(Path pathToVault, String masterkeyFilename,
225225
String normalizedOldPassphrase = Normalizer.normalize(oldPassphrase, Form.NFC);
226226
String normalizedNewPassphrase = Normalizer.normalize(newPassphrase, Form.NFC);
227227
Path masterKeyPath = pathToVault.resolve(masterkeyFilename);
228-
Path backupKeyPath = pathToVault.resolve(masterkeyFilename + Constants.MASTERKEY_BACKUP_SUFFIX);
229228
byte[] oldMasterkeyBytes = Files.readAllBytes(masterKeyPath);
230229
byte[] newMasterkeyBytes = Cryptors.changePassphrase(CRYPTOR_PROVIDER, oldMasterkeyBytes, pepper, normalizedOldPassphrase, normalizedNewPassphrase);
230+
Path backupKeyPath = pathToVault.resolve(masterkeyFilename + BackupUtil.generateFileIdSuffix(oldMasterkeyBytes) + Constants.MASTERKEY_BACKUP_SUFFIX);
231231
Files.move(masterKeyPath, backupKeyPath, REPLACE_EXISTING, ATOMIC_MOVE);
232232
Files.write(masterKeyPath, newMasterkeyBytes, CREATE_NEW, WRITE);
233233
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import javax.inject.Inject;
1717

18+
import org.cryptomator.cryptofs.BackupUtil;
1819
import org.cryptomator.cryptofs.Constants;
1920
import org.cryptomator.cryptofs.migration.api.Migrator;
2021
import org.cryptomator.cryptolib.api.Cryptor;
@@ -44,7 +45,7 @@ public void migrate(Path vaultRoot, String masterkeyFilename, CharSequence passp
4445
KeyFile keyFile = KeyFile.parse(fileContentsBeforeUpgrade);
4546
try (Cryptor cryptor = cryptorProvider.createFromKeyFile(keyFile, passphrase, 5)) {
4647
// create backup, as soon as we know the password was correct:
47-
Path masterkeyBackupFile = vaultRoot.resolve(masterkeyFilename + Constants.MASTERKEY_BACKUP_SUFFIX);
48+
Path masterkeyBackupFile = vaultRoot.resolve(masterkeyFilename + BackupUtil.generateFileIdSuffix(fileContentsBeforeUpgrade) + Constants.MASTERKEY_BACKUP_SUFFIX);
4849
Files.copy(masterkeyFile, masterkeyBackupFile, StandardCopyOption.REPLACE_EXISTING);
4950
LOG.info("Backed up masterkey from {} to {}.", masterkeyFile.getFileName(), masterkeyBackupFile.getFileName());
5051
// rewrite masterkey file with normalized passphrase:

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.google.common.jimfs.Configuration;
44
import com.google.common.jimfs.Jimfs;
5+
import org.cryptomator.cryptofs.BackupUtil;
6+
import org.cryptomator.cryptofs.Constants;
57
import org.cryptomator.cryptofs.migration.api.Migrator;
68
import org.cryptomator.cryptofs.mocks.NullSecureRandom;
79
import org.cryptomator.cryptolib.Cryptors;
@@ -25,7 +27,6 @@ public class Version6MigratorTest {
2527
private FileSystem fs;
2628
private Path pathToVault;
2729
private Path masterkeyFile;
28-
private Path masterkeyBackupFile;
2930
private CryptorProvider cryptorProvider;
3031

3132
@BeforeEach
@@ -34,7 +35,7 @@ public void setup() throws IOException {
3435
fs = Jimfs.newFileSystem(Configuration.unix());
3536
pathToVault = fs.getPath("/vaultDir");
3637
masterkeyFile = pathToVault.resolve("masterkey.cryptomator");
37-
masterkeyBackupFile = pathToVault.resolve("masterkey.cryptomator.bkup");
38+
//masterkeyBackupFile cannot be set here since we cannot compute a digest from a non-existing file
3839
Files.createDirectory(pathToVault);
3940
}
4041

@@ -52,6 +53,7 @@ public void testMigrate() throws IOException {
5253
KeyFile beforeMigration = cryptorProvider.createNew().writeKeysToMasterkeyFile(oldPassword, 5);
5354
Assertions.assertEquals(5, beforeMigration.getVersion());
5455
Files.write(masterkeyFile, beforeMigration.serialize());
56+
Path masterkeyBackupFile = pathToVault.resolve("masterkey.cryptomator" + BackupUtil.generateFileIdSuffix(beforeMigration.serialize()) + Constants.MASTERKEY_BACKUP_SUFFIX);
5557

5658
Migrator migrator = new Version6Migrator(cryptorProvider);
5759
migrator.migrate(pathToVault, "masterkey.cryptomator", oldPassword);

0 commit comments

Comments
 (0)