diff --git a/README.md b/README.md
index 53e70212..6ed04e88 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@
### Security Architecture
-For more information on the security details, visit [cryptomator.org](https://cryptomator.org/architecture/).
+For more information on the security details, visit [docs.cryptomator.org](https://docs.cryptomator.org/en/latest/security/architecture/).
## Audits
@@ -33,9 +33,14 @@ For more information on the security details, visit [cryptomator.org](https://cr
```java
Path storageLocation = Paths.get("/home/cryptobot/vault");
Files.createDirectories(storageLocation);
-CryptoFileSystemProvider.initialize(storageLocation, "masterkey.cryptomator", "password");
+Masterkey masterkey = Masterkey.generate(csprng));
+MasterkeyLoader loader = ignoredUri -> masterkey.copy(); //create a copy because the key handed over to init() method will be destroyed
+CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties().withKeyLoader(loader).build();
+CryptoFileSystemProvider.initialize(storageLocation, fsProps, "myKeyId");
```
+The key material used for initialization and later de- & encryption is given by the [org.cryptomator.cryptolib.api.Masterkeyloader](https://github.com/cryptomator/cryptolib/blob/2.1.2/src/main/java/org/cryptomator/cryptolib/api/MasterkeyLoader.java) interface.
+
### Obtaining a FileSystem Instance
You have the option to use the convenience method `CryptoFileSystemProvider#newFileSystem` as follows:
@@ -44,7 +49,7 @@ You have the option to use the convenience method `CryptoFileSystemProvider#newF
FileSystem fileSystem = CryptoFileSystemProvider.newFileSystem(
storageLocation,
CryptoFileSystemProperties.cryptoFileSystemProperties()
- .withPassphrase("password")
+ .withKeyLoader(ignoredUri -> masterkey.copy())
.withFlags(FileSystemFlags.READONLY) // readonly flag is optional of course
.build());
```
@@ -56,7 +61,7 @@ URI uri = CryptoFileSystemUri.create(storageLocation);
FileSystem fileSystem = FileSystems.newFileSystem(
uri,
CryptoFileSystemProperties.cryptoFileSystemProperties()
- .withPassphrase("password")
+ .withKeyLoader(ignoredUri -> masterkey.copy())
.withFlags(FileSystemFlags.READONLY) // readonly flag is optional of course
.build());
```
diff --git a/pom.xml b/pom.xml
index c708f3dd..0083ba02 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
4.0.0
org.cryptomator
cryptofs
- 2.6.5
+ 2.6.6
Cryptomator Crypto Filesystem
This library provides the Java filesystem provider used by Cryptomator.
https://github.com/cryptomator/cryptofs
@@ -19,7 +19,7 @@
2.1.2
- 4.3.0
+ 4.4.0
2.44.2
32.0.0-jre
3.1.4
diff --git a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java
index bd10dc34..8bd83d2d 100644
--- a/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java
+++ b/src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java
@@ -599,7 +599,7 @@ private void moveFile(CryptoPath cleartextSource, CryptoPath cleartextTarget, Co
CiphertextFilePath ciphertextTarget = cryptoPathMapper.getCiphertextFilePath(cleartextTarget);
try (OpenCryptoFiles.TwoPhaseMove twoPhaseMove = openCryptoFiles.prepareMove(ciphertextSource.getRawPath(), ciphertextTarget.getRawPath())) {
if (ciphertextTarget.isShortened()) {
- Files.createDirectory(ciphertextTarget.getRawPath());
+ Files.createDirectories(ciphertextTarget.getRawPath());
ciphertextTarget.persistLongFileName();
}
Files.move(ciphertextSource.getFilePath(), ciphertextTarget.getFilePath(), options);
diff --git a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java
index 487d683c..c9f0b4bd 100644
--- a/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java
+++ b/src/test/java/org/cryptomator/cryptofs/CryptoFileSystemProviderIntegrationTest.java
@@ -62,7 +62,9 @@
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.DosFileAttributeView;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.EnumSet;
+import java.util.Set;
import static java.nio.file.Files.readAllBytes;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
@@ -170,7 +172,7 @@ public void testCopyExceedingPathLengthLimit(String path) {
@Nested
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
- public class InMemory {
+ public class InMemoryOrdered {
private FileSystem tmpFs;
private MasterkeyLoader keyLoader1;
@@ -587,6 +589,68 @@ public void testMoveFileFromOneCryptoFileSystemToAnother() throws IOException {
}
+
+ @Nested
+ public class InMemory {
+
+ private static FileSystem tmpFs;
+ private static Path pathToVault;
+
+ @BeforeAll
+ public static void beforeAll() {
+ tmpFs = Jimfs.newFileSystem(Configuration.unix());
+ pathToVault = tmpFs.getPath("/vault");
+ }
+
+ @BeforeEach
+ public void beforeEach() throws IOException {
+ Files.createDirectory(pathToVault);
+ }
+
+ @AfterEach
+ public void afterEach() throws IOException {
+ try (var paths = Files.walk(pathToVault)) {
+ var nodes = paths.sorted(Comparator.reverseOrder()).toList();
+ for (var node : nodes) {
+ Files.delete(node);
+ }
+ }
+ }
+
+ @AfterAll
+ public static void afterAll() throws IOException {
+ tmpFs.close();
+ }
+
+ @Test
+ @DisplayName("Replace an existing, shortened file")
+ public void testReplaceExistingShortenedFile() throws IOException {
+ try (var fs = setupCryptoFs(50, 100, false)) {
+ var fiftyCharName2 = "/50char2_50char2_50char2_50char2_50char2_50char.txt"; //since filename encryption increases filename length, 50 cleartext chars are sufficient
+ var source = fs.getPath("/source.txt");
+ var target = fs.getPath(fiftyCharName2);
+ Files.createFile(source);
+ Files.createFile(target);
+
+ Assertions.assertDoesNotThrow(() -> Files.move(source, target, REPLACE_EXISTING));
+ Assertions.assertTrue(Files.notExists(source));
+ Assertions.assertTrue(Files.exists(target));
+ }
+ }
+
+ private FileSystem setupCryptoFs(int ciphertextShorteningThreshold, int maxCleartextFilename, boolean readonly) throws IOException {
+ byte[] key = new byte[64];
+ Arrays.fill(key, (byte) 0x55);
+ var keyLoader = Mockito.mock(MasterkeyLoader.class);
+ Mockito.when(keyLoader.loadKey(Mockito.any())).thenAnswer(ignored -> new Masterkey(key));
+ var properties = CryptoFileSystemProperties.cryptoFileSystemProperties().withKeyLoader(keyLoader).withShorteningThreshold(ciphertextShorteningThreshold).withMaxCleartextNameLength(maxCleartextFilename).withFlags(readonly ? Set.of(CryptoFileSystemProperties.FileSystemFlags.READONLY) : Set.of()).build();
+ CryptoFileSystemProvider.initialize(pathToVault, properties, URI.create("test:key"));
+ URI fsUri = CryptoFileSystemUri.create(pathToVault);
+ return FileSystems.newFileSystem(fsUri, cryptoFileSystemProperties().withKeyLoader(keyLoader).build());
+ }
+
+ }
+
@Nested
@EnabledOnOs({OS.MAC, OS.LINUX})
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
diff --git a/suppression.xml b/suppression.xml
index ebb877b8..4c274d96 100644
--- a/suppression.xml
+++ b/suppression.xml
@@ -9,4 +9,13 @@
cpe:/a:cryptomator:cryptomator
CVE-2022-25366
+
+
+
+
+ ^pkg:maven/com\.fasterxml\.jackson\.core/jackson\-databind@.*$
+ CVE-2023-35116
+
\ No newline at end of file