new vault-internal file extensions (no extension at all for files, "_" suffix for directories)

This commit is contained in:
Sebastian Stenzel
2016-02-08 15:17:50 +01:00
parent bb185c3170
commit 4d2a786504
6 changed files with 35 additions and 11 deletions

View File

@@ -21,6 +21,14 @@ public interface FilenameCryptor {
*/
String hashDirectoryId(String cleartextDirectoryId);
/**
* Tests without an actual decryption attempt, if a name is a well-formed ciphertext.
*
* @param ciphertextName Filename in question
* @return <code>true</code> if the given name is likely to be a valid ciphertext
*/
boolean isEncryptedFilename(String ciphertextName);
/**
* @param cleartextName original filename including cleartext file extension
* @param associatedData optional associated data, that will not get encrypted but needs to be provided during decryption

View File

@@ -49,6 +49,11 @@ class FilenameCryptorImpl implements FilenameCryptor {
return BASE32.encodeAsString(hashedBytes);
}
@Override
public boolean isEncryptedFilename(String ciphertextName) {
return BASE32.isInAlphabet(ciphertextName);
}
@Override
public String encryptFilename(String cleartextName, byte[]... associatedData) {
final byte[] cleartextBytes = cleartextName.getBytes(UTF_8);

View File

@@ -21,8 +21,6 @@ import org.cryptomator.filesystem.WritableFile;
public class CryptoFile extends CryptoNode implements File {
static final String FILE_EXT = ".file";
public CryptoFile(CryptoFolder parent, String name, Cryptor cryptor) {
super(parent, name, cryptor);
}
@@ -30,7 +28,7 @@ public class CryptoFile extends CryptoNode implements File {
@Override
protected String encryptedName() {
final byte[] parentDirId = parent.getDirectoryId().getBytes(UTF_8);
return cryptor.getFilenameCryptor().encryptFilename(name(), parentDirId) + FILE_EXT;
return cryptor.getFilenameCryptor().encryptFilename(name(), parentDirId);
}
@Override

View File

@@ -19,6 +19,7 @@ import java.time.Instant;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.apache.commons.io.IOUtils;
@@ -33,7 +34,7 @@ import org.cryptomator.filesystem.WritableFile;
class CryptoFolder extends CryptoNode implements Folder {
static final String DIR_EXT = ".dir";
static final String DIR_SUFFIX = "_";
private final WeakValuedCache<String, CryptoFolder> folders = WeakValuedCache.usingLoader(this::newFolder);
private final WeakValuedCache<String, CryptoFile> files = WeakValuedCache.usingLoader(this::newFile);
@@ -46,7 +47,7 @@ class CryptoFolder extends CryptoNode implements Folder {
@Override
protected String encryptedName() {
final byte[] parentDirId = parent().map(CryptoFolder::getDirectoryId).map(s -> s.getBytes(UTF_8)).orElse(null);
return cryptor.getFilenameCryptor().encryptFilename(name(), parentDirId) + DIR_EXT;
return cryptor.getFilenameCryptor().encryptFilename(name(), parentDirId) + DIR_SUFFIX;
}
Folder physicalFolder() {
@@ -82,13 +83,16 @@ class CryptoFolder extends CryptoNode implements Folder {
@Override
public Stream<CryptoFile> files() {
return physicalFolder().files().map(File::name).filter(s -> s.endsWith(CryptoFile.FILE_EXT)).map(this::decryptChildFileName).map(this::file);
return physicalFolder().files().map(File::name).filter(isEncryptedFileName()).map(this::decryptChildFileName).map(this::file);
}
private Predicate<String> isEncryptedFileName() {
return (String name) -> cryptor.getFilenameCryptor().isEncryptedFilename(name);
}
private String decryptChildFileName(String encryptedFileName) {
final byte[] dirId = getDirectoryId().getBytes(UTF_8);
final String ciphertext = StringUtils.removeEnd(encryptedFileName, CryptoFile.FILE_EXT);
return cryptor.getFilenameCryptor().decryptFilename(ciphertext, dirId);
return cryptor.getFilenameCryptor().decryptFilename(encryptedFileName, dirId);
}
@Override
@@ -102,12 +106,16 @@ class CryptoFolder extends CryptoNode implements Folder {
@Override
public Stream<CryptoFolder> folders() {
return physicalFolder().files().map(File::name).filter(s -> s.endsWith(CryptoFolder.DIR_EXT)).map(this::decryptChildFolderName).map(this::folder);
return physicalFolder().files().map(File::name).filter(isEncryptedDirectoryName()).map(this::decryptChildFolderName).map(this::folder);
}
private Predicate<String> isEncryptedDirectoryName() {
return (String name) -> name.endsWith(DIR_SUFFIX) && isEncryptedFileName().test(StringUtils.removeEnd(name, DIR_SUFFIX));
}
private String decryptChildFolderName(String encryptedFolderName) {
final byte[] dirId = getDirectoryId().getBytes(UTF_8);
final String ciphertext = StringUtils.removeEnd(encryptedFolderName, CryptoFolder.DIR_EXT);
final String ciphertext = StringUtils.removeEnd(encryptedFolderName, CryptoFolder.DIR_SUFFIX);
return cryptor.getFilenameCryptor().decryptFilename(ciphertext, dirId);
}

View File

@@ -28,6 +28,11 @@ class NoFilenameCryptor implements FilenameCryptor {
return BASE32.encodeAsString(hashedBytes);
}
@Override
public boolean isEncryptedFilename(String ciphertextName) {
return true;
}
@Override
public String encryptFilename(String cleartextName, byte[]... associatedData) {
return cleartextName;

View File

@@ -19,7 +19,7 @@ import org.cryptomator.filesystem.blacklisting.SamePathPredicate;
@Singleton
public class ShorteningFileSystemFactory {
private static final int SHORTENING_THRESHOLD = 140;
private static final int SHORTENING_THRESHOLD = 129; // 128 + "_"
private static final String METADATA_FOLDER_NAME = "m";
private final BlacklistingFileSystemFactory blacklistingFileSystemFactory;