From 0d9f8eefc020fcab9a35e5d0d1cd146d5858f681 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 12 May 2016 11:51:14 +0200 Subject: [PATCH] Using pattern based filename filtering This is a preparation for finding valid encrypted names inside filenames that include additional characters --- .../crypto/engine/FilenameCryptor.java | 9 ++++----- .../crypto/engine/impl/FilenameCryptorImpl.java | 6 ++++-- .../filesystem/crypto/CryptoFolder.java | 17 ++++++++++++++--- .../crypto/engine/NoFilenameCryptor.java | 6 ++++-- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FilenameCryptor.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FilenameCryptor.java index cb94a12fa..1226da4ed 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FilenameCryptor.java +++ b/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 true 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 diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FilenameCryptorImpl.java b/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FilenameCryptorImpl.java index 5db611548..4b977d44d 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FilenameCryptorImpl.java +++ b/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 SHA1 = new ThreadLocalSha1(); private static final ThreadLocal AES_SIV = new ThreadLocal() { @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 diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java index c8228535c..3c2040ea3 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/CryptoFolder.java +++ b/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 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 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(); } diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/NoFilenameCryptor.java b/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/NoFilenameCryptor.java index 9f3901f7e..590582ba8 100644 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/NoFilenameCryptor.java +++ b/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 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