Browse Source

Using pattern based filename filtering
This is a preparation for finding valid encrypted names inside filenames that include additional characters

Sebastian Stenzel 9 years ago
parent
commit
0d9f8eefc0

+ 4 - 5
main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FilenameCryptor.java

@@ -8,6 +8,8 @@
  *******************************************************************************/
 package org.cryptomator.crypto.engine;
 
+import java.util.regex.Pattern;
+
 /**
  * Provides deterministic encryption capabilities as filenames must not change on subsequent encryption attempts,
  * otherwise each change results in major directory structure changes which would be a terrible idea for cloud storage encryption.
@@ -22,12 +24,9 @@ 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
+	 * @return A Pattern that can be used to test, if a name is a well-formed ciphertext.
 	 */
-	boolean isEncryptedFilename(String ciphertextName);
+	Pattern encryptedNamePattern();
 
 	/**
 	 * @param cleartextName original filename including cleartext file extension

+ 4 - 2
main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FilenameCryptorImpl.java

@@ -12,6 +12,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.util.regex.Pattern;
 
 import javax.crypto.AEADBadTagException;
 import javax.crypto.SecretKey;
@@ -25,6 +26,7 @@ import org.cryptomator.siv.SivMode;
 class FilenameCryptorImpl implements FilenameCryptor {
 
 	private static final BaseNCodec BASE32 = new Base32();
+	private static final Pattern BASE32_PATTERN = Pattern.compile("([A-Z0-9]{8})*[A-Z0-9=]{8}");
 	private static final ThreadLocal<MessageDigest> SHA1 = new ThreadLocalSha1();
 	private static final ThreadLocal<SivMode> AES_SIV = new ThreadLocal<SivMode>() {
 		@Override
@@ -50,8 +52,8 @@ class FilenameCryptorImpl implements FilenameCryptor {
 	}
 
 	@Override
-	public boolean isEncryptedFilename(String ciphertextName) {
-		return BASE32.isInAlphabet(ciphertextName);
+	public Pattern encryptedNamePattern() {
+		return BASE32_PATTERN;
 	}
 
 	@Override

+ 14 - 3
main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java

@@ -18,6 +18,7 @@ import java.util.Optional;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Predicate;
+import java.util.regex.Matcher;
 import java.util.stream.Stream;
 
 import org.apache.commons.lang3.StringUtils;
@@ -85,7 +86,10 @@ class CryptoFolder extends CryptoNode implements Folder {
 	}
 
 	private Predicate<String> isEncryptedFileName() {
-		return (String name) -> !name.endsWith(DIR_SUFFIX) && cryptor.getFilenameCryptor().isEncryptedFilename(name);
+		return (String name) -> {
+			final Matcher m = cryptor.getFilenameCryptor().encryptedNamePattern().matcher(name);
+			return m.matches();
+		};
 	}
 
 	private String decryptChildFileName(String encryptedFileName) {
@@ -109,7 +113,14 @@ class CryptoFolder extends CryptoNode implements Folder {
 	}
 
 	private Predicate<String> isEncryptedDirectoryName() {
-		return (String name) -> name.endsWith(DIR_SUFFIX) && cryptor.getFilenameCryptor().isEncryptedFilename(StringUtils.removeEnd(name, DIR_SUFFIX));
+		return (String name) -> {
+			if (name.endsWith(DIR_SUFFIX)) {
+				final Matcher m = cryptor.getFilenameCryptor().encryptedNamePattern().matcher(StringUtils.removeEnd(name, DIR_SUFFIX));
+				return m.matches();
+			} else {
+				return false;
+			}
+		};
 	}
 
 	private String decryptChildFolderName(String encryptedFolderName) {
@@ -176,7 +187,7 @@ class CryptoFolder extends CryptoNode implements Folder {
 		// cut all ties:
 		this.invalidateDirectoryIdsRecursively();
 
-		assert!exists();
+		assert !exists();
 		assert target.exists();
 	}
 

+ 4 - 2
main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/NoFilenameCryptor.java

@@ -12,6 +12,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.util.regex.Pattern;
 
 import org.apache.commons.codec.binary.Base32;
 import org.apache.commons.codec.binary.BaseNCodec;
@@ -19,6 +20,7 @@ import org.apache.commons.codec.binary.BaseNCodec;
 class NoFilenameCryptor implements FilenameCryptor {
 
 	private static final BaseNCodec BASE32 = new Base32();
+	private static final Pattern WILDCARD_PATTERN = Pattern.compile(".*");
 	private static final ThreadLocal<MessageDigest> SHA1 = new ThreadLocalSha1();
 
 	@Override
@@ -29,8 +31,8 @@ class NoFilenameCryptor implements FilenameCryptor {
 	}
 
 	@Override
-	public boolean isEncryptedFilename(String ciphertextName) {
-		return true;
+	public Pattern encryptedNamePattern() {
+		return WILDCARD_PATTERN;
 	}
 
 	@Override