Skip to content

Commit

Permalink
Merge branch 'release/1.8.7'
Browse files Browse the repository at this point in the history
  • Loading branch information
overheadhunter committed Aug 18, 2019
2 parents fa335fa + af65bc9 commit 1ec3005
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 9 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>cryptofs</artifactId>
<version>1.8.6</version>
<version>1.8.7</version>
<name>Cryptomator Crypto Filesystem</name>
<description>This library provides the Java filesystem provider used by Cryptomator.</description>
<url>https://github.com/cryptomator/cryptofs</url>
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/org/cryptomator/cryptofs/BackupUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.cryptomator.cryptofs;

import com.google.common.io.BaseEncoding;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
* Utility class for generating a suffix for the backup file to make it unique to its original master key file.
*/
public class BackupUtil {

/**
* Computes the SHA-256 digest of the given byte array and returns a file suffix containing the first 4 bytes in hex string format.
*
* @param fileBytes the input byte for which the digest is computed
* @return "." + first 4 bytes of SHA-256 digest in hex string format
*/
public static String generateFileIdSuffix(byte[] fileBytes) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(fileBytes);
return "." + BaseEncoding.base16().encode(digest, 0, 4);
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("Every Java Platform must support the Message Digest algorithm SHA-256", e);
}
}
}
6 changes: 3 additions & 3 deletions src/main/java/org/cryptomator/cryptofs/ConflictResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,18 +103,18 @@ private Path resolveConflict(Path conflictingPath, String ciphertextFileName, St
* @param conflictingPath The path to the potentially conflicting file.
* @param ciphertext The (previously inflated) ciphertext name of the file without any preceeding directory prefix.
* @param dirId The directory id of the file's parent directory.
* @param dirPrefix The directory prefix (if the conflicting file is a directory file) or an empty string.
* @param typePrefix The prefix (if the conflicting file is a directory file or a symlink) or an empty string.
* @return The new path after renaming the conflicting file.
* @throws IOException
*/
private Path renameConflictingFile(Path canonicalPath, Path conflictingPath, String ciphertext, String dirId, String dirPrefix) throws IOException {
private Path renameConflictingFile(Path canonicalPath, Path conflictingPath, String ciphertext, String dirId, String typePrefix) throws IOException {
try {
String cleartext = cryptor.fileNameCryptor().decryptFilename(ciphertext, dirId.getBytes(StandardCharsets.UTF_8));
Path alternativePath = canonicalPath;
for (int i = 1; Files.exists(alternativePath); i++) {
String alternativeCleartext = cleartext + " (Conflict " + i + ")";
String alternativeCiphertext = cryptor.fileNameCryptor().encryptFilename(alternativeCleartext, dirId.getBytes(StandardCharsets.UTF_8));
String alternativeCiphertextFileName = dirPrefix + alternativeCiphertext;
String alternativeCiphertextFileName = typePrefix + alternativeCiphertext;
if (alternativeCiphertextFileName.length() > SHORT_NAMES_MAX_LENGTH) {
alternativeCiphertextFileName = longFileNameProvider.deflate(alternativeCiphertextFileName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ class CryptoFileSystemModule {
public Cryptor provideCryptor(CryptorProvider cryptorProvider, @PathToVault Path pathToVault, CryptoFileSystemProperties properties, ReadonlyFlag readonlyFlag) {
try {
Path masterKeyPath = pathToVault.resolve(properties.masterkeyFilename());
Path backupKeyPath = pathToVault.resolve(properties.masterkeyFilename() + Constants.MASTERKEY_BACKUP_SUFFIX);
assert Files.exists(masterKeyPath); // since 1.3.0 a file system can only be created for existing vaults. initialization is done before.
byte[] keyFileContents = Files.readAllBytes(masterKeyPath);
Path backupKeyPath = pathToVault.resolve(properties.masterkeyFilename() + BackupUtil.generateFileIdSuffix(keyFileContents) + Constants.MASTERKEY_BACKUP_SUFFIX);
Cryptor cryptor = cryptorProvider.createFromKeyFile(KeyFile.parse(keyFileContents), properties.passphrase(), properties.pepper(), Constants.VAULT_VERSION);
backupMasterkeyFileIfRequired(masterKeyPath, backupKeyPath, readonlyFlag);
return cryptor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,9 @@ public static void changePassphrase(Path pathToVault, String masterkeyFilename,
String normalizedOldPassphrase = Normalizer.normalize(oldPassphrase, Form.NFC);
String normalizedNewPassphrase = Normalizer.normalize(newPassphrase, Form.NFC);
Path masterKeyPath = pathToVault.resolve(masterkeyFilename);
Path backupKeyPath = pathToVault.resolve(masterkeyFilename + Constants.MASTERKEY_BACKUP_SUFFIX);
byte[] oldMasterkeyBytes = Files.readAllBytes(masterKeyPath);
byte[] newMasterkeyBytes = Cryptors.changePassphrase(CRYPTOR_PROVIDER, oldMasterkeyBytes, pepper, normalizedOldPassphrase, normalizedNewPassphrase);
Path backupKeyPath = pathToVault.resolve(masterkeyFilename + BackupUtil.generateFileIdSuffix(oldMasterkeyBytes) + Constants.MASTERKEY_BACKUP_SUFFIX);
Files.move(masterKeyPath, backupKeyPath, REPLACE_EXISTING, ATOMIC_MOVE);
Files.write(masterKeyPath, newMasterkeyBytes, CREATE_NEW, WRITE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import javax.inject.Inject;

import org.cryptomator.cryptofs.BackupUtil;
import org.cryptomator.cryptofs.Constants;
import org.cryptomator.cryptofs.migration.api.Migrator;
import org.cryptomator.cryptolib.api.Cryptor;
Expand Down Expand Up @@ -44,7 +45,7 @@ public void migrate(Path vaultRoot, String masterkeyFilename, CharSequence passp
KeyFile keyFile = KeyFile.parse(fileContentsBeforeUpgrade);
try (Cryptor cryptor = cryptorProvider.createFromKeyFile(keyFile, passphrase, 5)) {
// create backup, as soon as we know the password was correct:
Path masterkeyBackupFile = vaultRoot.resolve(masterkeyFilename + Constants.MASTERKEY_BACKUP_SUFFIX);
Path masterkeyBackupFile = vaultRoot.resolve(masterkeyFilename + BackupUtil.generateFileIdSuffix(fileContentsBeforeUpgrade) + Constants.MASTERKEY_BACKUP_SUFFIX);
Files.copy(masterkeyFile, masterkeyBackupFile, StandardCopyOption.REPLACE_EXISTING);
LOG.info("Backed up masterkey from {} to {}.", masterkeyFile.getFileName(), masterkeyBackupFile.getFileName());
// rewrite masterkey file with normalized passphrase:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import org.cryptomator.cryptofs.BackupUtil;
import org.cryptomator.cryptofs.Constants;
import org.cryptomator.cryptofs.migration.api.Migrator;
import org.cryptomator.cryptofs.mocks.NullSecureRandom;
import org.cryptomator.cryptolib.Cryptors;
Expand All @@ -25,7 +27,6 @@ public class Version6MigratorTest {
private FileSystem fs;
private Path pathToVault;
private Path masterkeyFile;
private Path masterkeyBackupFile;
private CryptorProvider cryptorProvider;

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

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

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

0 comments on commit 1ec3005

Please sign in to comment.