mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-10-01 12:15:32 +00:00
supporting change password again - now via CryptoFileSystemFactory
This commit is contained in:
@@ -21,8 +21,11 @@ public interface Cryptor extends Destroyable {
|
||||
|
||||
void randomizeMasterkey();
|
||||
|
||||
boolean readKeysFromMasterkeyFile(byte[] masterkeyFileContents, CharSequence passphrase);
|
||||
void readKeysFromMasterkeyFile(byte[] masterkeyFileContents, CharSequence passphrase) throws InvalidPassphraseException;
|
||||
|
||||
byte[] writeKeysToMasterkeyFile(CharSequence passphrase);
|
||||
|
||||
@Override
|
||||
void destroy();
|
||||
|
||||
}
|
||||
|
||||
+8
-5
@@ -24,6 +24,7 @@ import org.cryptomator.common.LazyInitializer;
|
||||
import org.cryptomator.crypto.engine.Cryptor;
|
||||
import org.cryptomator.crypto.engine.FileContentCryptor;
|
||||
import org.cryptomator.crypto.engine.FilenameCryptor;
|
||||
import org.cryptomator.crypto.engine.InvalidPassphraseException;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -86,7 +87,7 @@ public class CryptorImpl implements Cryptor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readKeysFromMasterkeyFile(byte[] masterkeyFileContents, CharSequence passphrase) {
|
||||
public void readKeysFromMasterkeyFile(byte[] masterkeyFileContents, CharSequence passphrase) {
|
||||
final KeyFile keyFile;
|
||||
try {
|
||||
final ObjectMapper om = new ObjectMapper();
|
||||
@@ -107,9 +108,8 @@ public class CryptorImpl implements Cryptor {
|
||||
final SecretKey kek = new SecretKeySpec(kekBytes, ENCRYPTION_ALG);
|
||||
this.encryptionKey = AesKeyWrap.unwrap(kek, keyFile.getEncryptionMasterKey(), ENCRYPTION_ALG);
|
||||
this.macKey = AesKeyWrap.unwrap(kek, keyFile.getMacMasterKey(), MAC_ALG);
|
||||
return true;
|
||||
} catch (InvalidKeyException e) {
|
||||
return false;
|
||||
throw new InvalidPassphraseException();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("Hard-coded algorithm doesn't exist.", e);
|
||||
} finally {
|
||||
@@ -152,17 +152,20 @@ public class CryptorImpl implements Cryptor {
|
||||
/* ======================= destruction ======================= */
|
||||
|
||||
@Override
|
||||
public void destroy() throws DestroyFailedException {
|
||||
public void destroy() {
|
||||
destroyQuietly(encryptionKey);
|
||||
destroyQuietly(macKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDestroyed() {
|
||||
return encryptionKey.isDestroyed() && macKey.isDestroyed();
|
||||
return (encryptionKey == null || encryptionKey.isDestroyed()) && (macKey == null || macKey.isDestroyed());
|
||||
}
|
||||
|
||||
private void destroyQuietly(Destroyable d) {
|
||||
if (d == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
d.destroy();
|
||||
} catch (DestroyFailedException e) {
|
||||
|
||||
+3
-37
@@ -16,60 +16,26 @@ import org.cryptomator.crypto.engine.InvalidPassphraseException;
|
||||
import org.cryptomator.filesystem.File;
|
||||
import org.cryptomator.filesystem.FileSystem;
|
||||
import org.cryptomator.filesystem.Folder;
|
||||
import org.cryptomator.filesystem.ReadableFile;
|
||||
import org.cryptomator.filesystem.WritableFile;
|
||||
|
||||
public class CryptoFileSystem extends CryptoFolder implements FileSystem {
|
||||
|
||||
private static final String DATA_ROOT_DIR = "d";
|
||||
private static final String ROOT_DIR_FILE = "root";
|
||||
private static final String MASTERKEY_FILENAME = "masterkey.cryptomator";
|
||||
private static final String MASTERKEY_BACKUP_FILENAME = "masterkey.cryptomator.bkup";
|
||||
|
||||
private final Folder physicalRoot;
|
||||
private final CryptoFileSystemDelegate delegate;
|
||||
|
||||
public CryptoFileSystem(Folder physicalRoot, Cryptor cryptor, CryptoFileSystemDelegate delegate, CharSequence passphrase) throws InvalidPassphraseException {
|
||||
super(null, "", cryptor);
|
||||
if (cryptor.isDestroyed()) {
|
||||
throw new IllegalArgumentException("Cryptor's keys must not be destroyed.");
|
||||
}
|
||||
this.physicalRoot = physicalRoot;
|
||||
this.delegate = delegate;
|
||||
final File masterkeyFile = physicalRoot.file(MASTERKEY_FILENAME);
|
||||
if (masterkeyFile.exists()) {
|
||||
final boolean unlocked = decryptMasterKeyFile(cryptor, masterkeyFile, passphrase);
|
||||
if (!unlocked) {
|
||||
throw new InvalidPassphraseException();
|
||||
}
|
||||
} else {
|
||||
cryptor.randomizeMasterkey();
|
||||
encryptMasterKeyFile(cryptor, masterkeyFile, passphrase);
|
||||
}
|
||||
assert masterkeyFile.exists() : "A CryptoFileSystem can not exist without a masterkey file.";
|
||||
final File backupFile = physicalRoot.file(MASTERKEY_BACKUP_FILENAME);
|
||||
masterkeyFile.copyTo(backupFile);
|
||||
create();
|
||||
}
|
||||
|
||||
private static boolean decryptMasterKeyFile(Cryptor cryptor, File masterkeyFile, CharSequence passphrase) {
|
||||
try (ReadableFile file = masterkeyFile.openReadable()) {
|
||||
// TODO we need to read the whole file but can not be sure about the
|
||||
// buffer size:
|
||||
final ByteBuffer bigEnoughBuffer = ByteBuffer.allocate(500);
|
||||
file.read(bigEnoughBuffer);
|
||||
bigEnoughBuffer.flip();
|
||||
assert bigEnoughBuffer.remaining() < bigEnoughBuffer.capacity() : "The buffer wasn't big enough.";
|
||||
final byte[] fileContents = new byte[bigEnoughBuffer.remaining()];
|
||||
bigEnoughBuffer.get(fileContents);
|
||||
return cryptor.readKeysFromMasterkeyFile(fileContents, passphrase);
|
||||
}
|
||||
}
|
||||
|
||||
private static void encryptMasterKeyFile(Cryptor cryptor, File masterkeyFile, CharSequence passphrase) {
|
||||
try (WritableFile file = masterkeyFile.openWritable()) {
|
||||
final byte[] fileContents = cryptor.writeKeysToMasterkeyFile(passphrase);
|
||||
file.write(ByteBuffer.wrap(fileContents));
|
||||
}
|
||||
}
|
||||
|
||||
CryptoFileSystemDelegate delegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
+26
-7
@@ -1,7 +1,8 @@
|
||||
package org.cryptomator.filesystem.crypto;
|
||||
|
||||
import java.io.UncheckedIOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.cryptomator.crypto.engine.Cryptor;
|
||||
@@ -14,20 +15,38 @@ import org.cryptomator.filesystem.shortening.ShorteningFileSystemFactory;
|
||||
@Singleton
|
||||
public class CryptoFileSystemFactory {
|
||||
|
||||
private final Provider<Cryptor> cryptorProvider;
|
||||
private final Masterkeys masterkeys;
|
||||
private final ShorteningFileSystemFactory shorteningFileSystemFactory;
|
||||
private final BlockAlignedFileSystemFactory blockAlignedFileSystemFactory;
|
||||
|
||||
@Inject
|
||||
public CryptoFileSystemFactory(Provider<Cryptor> cryptorProvider, ShorteningFileSystemFactory shorteningFileSystemFactory, BlockAlignedFileSystemFactory blockAlignedFileSystemFactory) {
|
||||
this.cryptorProvider = cryptorProvider;
|
||||
public CryptoFileSystemFactory(Masterkeys masterkeys, ShorteningFileSystemFactory shorteningFileSystemFactory, BlockAlignedFileSystemFactory blockAlignedFileSystemFactory) {
|
||||
this.masterkeys = masterkeys;
|
||||
this.shorteningFileSystemFactory = shorteningFileSystemFactory;
|
||||
this.blockAlignedFileSystemFactory = blockAlignedFileSystemFactory;
|
||||
}
|
||||
|
||||
public FileSystem get(Folder root, CharSequence passphrase, CryptoFileSystemDelegate delegate) throws InvalidPassphraseException {
|
||||
final FileSystem nameShorteningFs = shorteningFileSystemFactory.get(root);
|
||||
final FileSystem cryptoFs = new CryptoFileSystem(nameShorteningFs, cryptorProvider.get(), delegate, passphrase);
|
||||
public void initializeNew(Folder vaultLocation, CharSequence passphrase) {
|
||||
masterkeys.initialize(vaultLocation, passphrase);
|
||||
}
|
||||
|
||||
public FileSystem unlockExisting(Folder vaultLocation, CharSequence passphrase, CryptoFileSystemDelegate delegate) throws InvalidPassphraseException {
|
||||
final Cryptor cryptor = masterkeys.decrypt(vaultLocation, passphrase);
|
||||
masterkeys.backup(vaultLocation);
|
||||
final FileSystem nameShorteningFs = shorteningFileSystemFactory.get(vaultLocation);
|
||||
final FileSystem cryptoFs = new CryptoFileSystem(nameShorteningFs, cryptor, delegate, passphrase);
|
||||
return blockAlignedFileSystemFactory.get(cryptoFs);
|
||||
}
|
||||
|
||||
public void changePassphrase(Folder vaultLocation, CharSequence oldPassphrase, CharSequence newPassphrase) throws InvalidPassphraseException {
|
||||
masterkeys.backup(vaultLocation);
|
||||
try {
|
||||
masterkeys.changePassphrase(vaultLocation, oldPassphrase, newPassphrase);
|
||||
// At this point the backup is still using the old password.
|
||||
// It will be changed as soon as the user unlocks the vault the next time.
|
||||
// This way he can still restore the old password, if he doesn't remember the new one.
|
||||
} catch (UncheckedIOException e) {
|
||||
masterkeys.restoreBackup(vaultLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
package org.cryptomator.filesystem.crypto;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.cryptomator.crypto.engine.Cryptor;
|
||||
import org.cryptomator.crypto.engine.InvalidPassphraseException;
|
||||
import org.cryptomator.filesystem.File;
|
||||
import org.cryptomator.filesystem.Folder;
|
||||
import org.cryptomator.filesystem.WritableFile;
|
||||
|
||||
@Singleton
|
||||
class Masterkeys {
|
||||
|
||||
private static final String MASTERKEY_FILENAME = "masterkey.cryptomator";
|
||||
private static final String MASTERKEY_BACKUP_FILENAME = "masterkey.cryptomator.bkup";
|
||||
|
||||
private final Provider<Cryptor> cryptorProvider;
|
||||
|
||||
@Inject
|
||||
public Masterkeys(Provider<Cryptor> cryptorProvider) {
|
||||
this.cryptorProvider = cryptorProvider;
|
||||
}
|
||||
|
||||
public void initialize(Folder vaultLocation, CharSequence passphrase) {
|
||||
File masterkeyFile = vaultLocation.file(MASTERKEY_FILENAME);
|
||||
Cryptor cryptor = cryptorProvider.get();
|
||||
try {
|
||||
cryptor.randomizeMasterkey();
|
||||
writeMasterKey(masterkeyFile, cryptor, passphrase);
|
||||
} finally {
|
||||
cryptor.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public Cryptor decrypt(Folder vaultLocation, CharSequence passphrase) throws InvalidPassphraseException {
|
||||
File masterkeyFile = vaultLocation.file(MASTERKEY_FILENAME);
|
||||
Cryptor cryptor = cryptorProvider.get();
|
||||
try {
|
||||
readMasterKey(masterkeyFile, cryptor, passphrase);
|
||||
} catch (UncheckedIOException e) {
|
||||
cryptor.destroy();
|
||||
}
|
||||
return cryptor;
|
||||
}
|
||||
|
||||
public void changePassphrase(Folder vaultLocation, CharSequence oldPassphrase, CharSequence newPassphrase) throws InvalidPassphraseException {
|
||||
File masterkeyFile = vaultLocation.file(MASTERKEY_FILENAME);
|
||||
Cryptor cryptor = cryptorProvider.get();
|
||||
try {
|
||||
readMasterKey(masterkeyFile, cryptor, oldPassphrase);
|
||||
writeMasterKey(masterkeyFile, cryptor, newPassphrase);
|
||||
} finally {
|
||||
cryptor.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public void backup(Folder vaultLocation) {
|
||||
File masterkeyFile = vaultLocation.file(MASTERKEY_FILENAME);
|
||||
File backupFile = vaultLocation.file(MASTERKEY_BACKUP_FILENAME);
|
||||
masterkeyFile.copyTo(backupFile);
|
||||
}
|
||||
|
||||
public void restoreBackup(Folder vaultLocation) {
|
||||
File backupFile = vaultLocation.file(MASTERKEY_BACKUP_FILENAME);
|
||||
File masterkeyFile = vaultLocation.file(MASTERKEY_FILENAME);
|
||||
backupFile.copyTo(masterkeyFile);
|
||||
}
|
||||
|
||||
/* I/O */
|
||||
|
||||
private static void readMasterKey(File file, Cryptor cryptor, CharSequence passphrase) throws UncheckedIOException, InvalidPassphraseException {
|
||||
try (InputStream in = Channels.newInputStream(file.openReadable())) {
|
||||
final byte[] fileContents = IOUtils.toByteArray(in);
|
||||
cryptor.readKeysFromMasterkeyFile(fileContents, passphrase);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeMasterKey(File file, Cryptor cryptor, CharSequence passphrase) throws UncheckedIOException {
|
||||
try (WritableFile writable = file.openWritable()) {
|
||||
final byte[] fileContents = cryptor.writeKeysToMasterkeyFile(passphrase);
|
||||
writable.write(ByteBuffer.wrap(fileContents));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,9 +29,8 @@ public class NoCryptor implements Cryptor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readKeysFromMasterkeyFile(byte[] masterkeyFileContents, CharSequence passphrase) {
|
||||
public void readKeysFromMasterkeyFile(byte[] masterkeyFileContents, CharSequence passphrase) {
|
||||
// thanks, but I don't need a key, if I'm not encryption anything...
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,4 +39,9 @@ public class NoCryptor implements Cryptor {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-3
@@ -11,19 +11,28 @@ package org.cryptomator.crypto.engine.impl;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.cryptomator.crypto.engine.Cryptor;
|
||||
import org.cryptomator.crypto.engine.InvalidPassphraseException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CryptorImplTest {
|
||||
|
||||
@Test
|
||||
public void testMasterkeyDecryption() throws IOException {
|
||||
public void testMasterkeyDecryptionWithCorrectPassphrase() throws IOException {
|
||||
final String testMasterKey = "{\"version\":3,\"scryptSalt\":\"AAAAAAAAAAA=\",\"scryptCostParam\":2,\"scryptBlockSize\":8," //
|
||||
+ "\"primaryMasterKey\":\"mM+qoQ+o0qvPTiDAZYt+flaC3WbpNAx1sTXaUzxwpy0M9Ctj6Tih/Q==\"," //
|
||||
+ "\"hmacMasterKey\":\"mM+qoQ+o0qvPTiDAZYt+flaC3WbpNAx1sTXaUzxwpy0M9Ctj6Tih/Q==\"}";
|
||||
final Cryptor cryptor = TestCryptorImplFactory.insecureCryptorImpl();
|
||||
Assert.assertFalse(cryptor.readKeysFromMasterkeyFile(testMasterKey.getBytes(), "qwe"));
|
||||
Assert.assertTrue(cryptor.readKeysFromMasterkeyFile(testMasterKey.getBytes(), "asd"));
|
||||
cryptor.readKeysFromMasterkeyFile(testMasterKey.getBytes(), "asd");
|
||||
}
|
||||
|
||||
@Test(expected = InvalidPassphraseException.class)
|
||||
public void testMasterkeyDecryptionWithWrongPassphrase() throws IOException {
|
||||
final String testMasterKey = "{\"version\":3,\"scryptSalt\":\"AAAAAAAAAAA=\",\"scryptCostParam\":2,\"scryptBlockSize\":8," //
|
||||
+ "\"primaryMasterKey\":\"mM+qoQ+o0qvPTiDAZYt+flaC3WbpNAx1sTXaUzxwpy0M9Ctj6Tih/Q==\"," //
|
||||
+ "\"hmacMasterKey\":\"mM+qoQ+o0qvPTiDAZYt+flaC3WbpNAx1sTXaUzxwpy0M9Ctj6Tih/Q==\"}";
|
||||
final Cryptor cryptor = TestCryptorImplFactory.insecureCryptorImpl();
|
||||
cryptor.readKeysFromMasterkeyFile(testMasterKey.getBytes(), "qwe");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+27
-1
@@ -1,6 +1,7 @@
|
||||
package org.cryptomator.filesystem.crypto;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -33,10 +34,35 @@ public class CryptoFileSystemComponentIntegrationTest {
|
||||
public void setupFileSystems() {
|
||||
cryptoDelegate = Mockito.mock(CryptoFileSystemDelegate.class);
|
||||
ciphertextFs = new InMemoryFileSystem();
|
||||
cleartextFs = cryptoFsComp.cryptoFileSystemFactory().get(ciphertextFs, "TopSecret", cryptoDelegate);
|
||||
cryptoFsComp.cryptoFileSystemFactory().initializeNew(ciphertextFs, "TopSecret");
|
||||
cleartextFs = cryptoFsComp.cryptoFileSystemFactory().unlockExisting(ciphertextFs, "TopSecret", cryptoDelegate);
|
||||
cleartextFs.create();
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
public void testVaultStructureInitializationAndBackupBehaviour() throws UncheckedIOException, IOException {
|
||||
final FileSystem physicalFs = new InMemoryFileSystem();
|
||||
final File masterkeyFile = physicalFs.file("masterkey.cryptomator");
|
||||
final File masterkeyBkupFile = physicalFs.file("masterkey.cryptomator.bkup");
|
||||
final Folder physicalDataRoot = physicalFs.folder("d");
|
||||
Assert.assertFalse(masterkeyFile.exists());
|
||||
Assert.assertFalse(masterkeyBkupFile.exists());
|
||||
Assert.assertFalse(physicalDataRoot.exists());
|
||||
|
||||
cryptoFsComp.cryptoFileSystemFactory().initializeNew(physicalFs, "asd");
|
||||
Assert.assertTrue(masterkeyFile.exists());
|
||||
Assert.assertFalse(masterkeyBkupFile.exists());
|
||||
Assert.assertFalse(physicalDataRoot.exists());
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
final FileSystem cryptoFs = cryptoFsComp.cryptoFileSystemFactory().unlockExisting(physicalFs, "asd", cryptoDelegate);
|
||||
Assert.assertTrue(masterkeyBkupFile.exists());
|
||||
Assert.assertTrue(physicalDataRoot.exists());
|
||||
Assert.assertEquals(3, physicalFs.children().count()); // d + masterkey.cryptomator + masterkey.cryptomator.bkup
|
||||
Assert.assertEquals(1, physicalDataRoot.files().count()); // ROOT file
|
||||
Assert.assertEquals(1, physicalDataRoot.folders().count()); // ROOT directory
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncryptionOfLongFolderNames() {
|
||||
final String shortName = "normal folder name";
|
||||
|
||||
-54
@@ -13,13 +13,11 @@ import static org.cryptomator.filesystem.FileSystemVisitor.fileSystemVisitor;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.cryptomator.crypto.engine.Cryptor;
|
||||
import org.cryptomator.crypto.engine.NoCryptor;
|
||||
import org.cryptomator.filesystem.File;
|
||||
import org.cryptomator.filesystem.FileSystem;
|
||||
import org.cryptomator.filesystem.Folder;
|
||||
import org.cryptomator.filesystem.ReadableFile;
|
||||
@@ -31,58 +29,6 @@ import org.mockito.Mockito;
|
||||
|
||||
public class CryptoFileSystemTest {
|
||||
|
||||
@Test(timeout = 1000)
|
||||
public void testVaultStructureInitialization() throws UncheckedIOException, IOException {
|
||||
// mock cryptor:
|
||||
final Cryptor cryptor = new NoCryptor();
|
||||
|
||||
// some mock fs:
|
||||
final FileSystem physicalFs = new InMemoryFileSystem();
|
||||
final File masterkeyFile = physicalFs.file("masterkey.cryptomator");
|
||||
final File masterkeyBkupFile = physicalFs.file("masterkey.cryptomator.bkup");
|
||||
final Folder physicalDataRoot = physicalFs.folder("d");
|
||||
Assert.assertFalse(masterkeyFile.exists());
|
||||
Assert.assertFalse(masterkeyBkupFile.exists());
|
||||
Assert.assertFalse(physicalDataRoot.exists());
|
||||
|
||||
// init crypto fs:
|
||||
final FileSystem fs = new CryptoFileSystem(physicalFs, cryptor, Mockito.mock(CryptoFileSystemDelegate.class), "foo");
|
||||
Assert.assertTrue(masterkeyFile.exists());
|
||||
Assert.assertTrue(masterkeyBkupFile.exists());
|
||||
fs.create();
|
||||
Assert.assertTrue(physicalDataRoot.exists());
|
||||
Assert.assertEquals(3, physicalFs.children().count()); // d + masterkey.cryptomator + masterkey.cryptomator.bkup
|
||||
Assert.assertEquals(1, physicalDataRoot.files().count()); // ROOT file
|
||||
Assert.assertEquals(1, physicalDataRoot.folders().count()); // ROOT directory
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
public void testMasterkeyBackupBehaviour() throws InterruptedException {
|
||||
// mock cryptor:
|
||||
final Cryptor cryptor = new NoCryptor();
|
||||
|
||||
// some mock fs:
|
||||
final FileSystem physicalFs = new InMemoryFileSystem();
|
||||
final File masterkeyBkupFile = physicalFs.file("masterkey.cryptomator.bkup");
|
||||
Assert.assertFalse(masterkeyBkupFile.exists());
|
||||
|
||||
// first initialization:
|
||||
new CryptoFileSystem(physicalFs, cryptor, Mockito.mock(CryptoFileSystemDelegate.class), "foo");
|
||||
Assert.assertTrue(masterkeyBkupFile.exists());
|
||||
final Instant bkupDateT0 = masterkeyBkupFile.lastModified();
|
||||
|
||||
// make sure some time passes, as the resolution of last modified date
|
||||
// is not in nanos:
|
||||
Thread.sleep(1);
|
||||
|
||||
// second initialization:
|
||||
new CryptoFileSystem(physicalFs, cryptor, Mockito.mock(CryptoFileSystemDelegate.class), "foo");
|
||||
Assert.assertTrue(masterkeyBkupFile.exists());
|
||||
final Instant bkupDateT1 = masterkeyBkupFile.lastModified();
|
||||
|
||||
Assert.assertTrue(bkupDateT1.isAfter(bkupDateT0));
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
public void testDirectoryCreation() throws UncheckedIOException, IOException {
|
||||
// mock stuff and prepare crypto FS:
|
||||
|
||||
Reference in New Issue
Block a user