Skip to content

Commit

Permalink
remove legacy FileNameCryptor.encrypt/decryptFilename methods without…
Browse files Browse the repository at this point in the history
… explicit encoding
  • Loading branch information
overheadhunter committed Jun 14, 2021
1 parent 83eaeb1 commit d32856f
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 68 deletions.
15 changes: 0 additions & 15 deletions src/main/java/org/cryptomator/cryptolib/api/FileNameCryptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,6 @@ public interface FileNameCryptor {
*/
String hashDirectoryId(String cleartextDirectoryId);

/**
* @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
* @return encrypted filename without any file extension, encoded in BASE32
*/
String encryptFilename(String cleartextName, byte[]... associatedData);

/**
* @param encoding Encoding to use to encode the returned ciphertext
* @param cleartextName original filename including cleartext file extension
Expand All @@ -39,14 +32,6 @@ public interface FileNameCryptor {
*/
String encryptFilename(BaseEncoding encoding, String cleartextName, byte[]... associatedData);

/**
* @param ciphertextName Ciphertext only, with any additional strings like file extensions stripped first, encoded in BASE32
* @param associatedData the same associated data used during encryption, otherwise and {@link AuthenticationFailedException} will be thrown
* @return cleartext filename, probably including its cleartext file extension.
* @throws AuthenticationFailedException if the ciphertext is malformed
*/
String decryptFilename(String ciphertextName, byte[]... associatedData) throws AuthenticationFailedException;

/**
* @param encoding Encoding to use to decode <code>ciphertextName</code>
* @param ciphertextName Ciphertext only, with any additional strings like file extensions stripped first.
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/cryptomator/cryptolib/package-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
*
* // Encrypt and decrypt file name:
* String cleartextFileName = "foo.txt";
* String encryptedName = cryptor.{@link org.cryptomator.cryptolib.api.Cryptor#fileNameCryptor() fileNameCryptor()}.{@link org.cryptomator.cryptolib.api.FileNameCryptor#encryptFilename(String, byte[][]) encryptFilename(cleartextFileName, uniqueIdOfDirectory.getBytes())};
* String decryptedName = cryptor.fileNameCryptor().{@link org.cryptomator.cryptolib.api.FileNameCryptor#decryptFilename(String, byte[][]) decryptFilename(encryptedName, uniqueIdOfDirectory.getBytes())};
* String encryptedName = cryptor.{@link org.cryptomator.cryptolib.api.Cryptor#fileNameCryptor() fileNameCryptor()}.{@link org.cryptomator.cryptolib.api.FileNameCryptor#encryptFilename(com.google.common.io.BaseEncoding, String, byte[][]) encryptFilename(base32, cleartextFileName, uniqueIdOfDirectory.getBytes())};
* String decryptedName = cryptor.fileNameCryptor().{@link org.cryptomator.cryptolib.api.FileNameCryptor#decryptFilename(com.google.common.io.BaseEncoding, String, byte[][]) decryptFilename(base32, encryptedName, uniqueIdOfDirectory.getBytes())};
*
* // Encrypt file contents:
* ByteBuffer plaintext = ...;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ public String hashDirectoryId(String cleartextDirectoryId) {
}
}

@Override
public String encryptFilename(String cleartextName, byte[]... associatedData) {
return encryptFilename(BASE32, cleartextName, associatedData);
}

@Override
public String encryptFilename(BaseEncoding encoding, String cleartextName, byte[]... associatedData) {
try (DestroyableSecretKey ek = masterkey.getEncKey(); DestroyableSecretKey mk = masterkey.getMacKey()) {
Expand All @@ -61,11 +56,6 @@ public String encryptFilename(BaseEncoding encoding, String cleartextName, byte[
}
}

@Override
public String decryptFilename(String ciphertextName, byte[]... associatedData) throws AuthenticationFailedException {
return decryptFilename(BASE32, ciphertextName, associatedData);
}

@Override
public String decryptFilename(BaseEncoding encoding, String ciphertextName, byte[]... associatedData) throws AuthenticationFailedException {
try (DestroyableSecretKey ek = masterkey.getEncKey(); DestroyableSecretKey mk = masterkey.getMacKey()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ public String hashDirectoryId(String cleartextDirectoryId) {
}
}

@Override
public String encryptFilename(String cleartextName, byte[]... associatedData) {
return encryptFilename(BASE32, cleartextName, associatedData);
}

@Override
public String encryptFilename(BaseEncoding encoding, String cleartextName, byte[]... associatedData) {
try (DestroyableSecretKey ek = masterkey.getEncKey(); DestroyableSecretKey mk = masterkey.getMacKey()) {
Expand All @@ -61,11 +56,6 @@ public String encryptFilename(BaseEncoding encoding, String cleartextName, byte[
}
}

@Override
public String decryptFilename(String ciphertextName, byte[]... associatedData) throws AuthenticationFailedException {
return decryptFilename(BASE32, ciphertextName, associatedData);
}

@Override
public String decryptFilename(BaseEncoding encoding, String ciphertextName, byte[]... associatedData) throws AuthenticationFailedException {
try (DestroyableSecretKey ek = masterkey.getEncKey(); DestroyableSecretKey mk = masterkey.getMacKey()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import com.google.common.io.BaseEncoding;
import org.cryptomator.cryptolib.api.AuthenticationFailedException;
import org.cryptomator.cryptolib.api.Masterkey;
import org.cryptomator.cryptolib.common.DestroyableSecretKey;
import org.cryptomator.siv.UnauthenticCiphertextException;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
Expand All @@ -28,6 +27,8 @@

public class FileNameCryptorImplTest {

private static final BaseEncoding BASE32 = BaseEncoding.base32();

private final Masterkey masterkey = new Masterkey(new byte[64]);
private final FileNameCryptorImpl filenameCryptor = new FileNameCryptorImpl(masterkey);

Expand All @@ -39,9 +40,9 @@ private static Stream<String> filenameGenerator() {
@ParameterizedTest(name = "decrypt(encrypt({0}))")
@MethodSource("filenameGenerator")
public void testDeterministicEncryptionOfFilenames(String origName) throws AuthenticationFailedException {
String encrypted1 = filenameCryptor.encryptFilename(origName);
String encrypted2 = filenameCryptor.encryptFilename(origName);
String decrypted = filenameCryptor.decryptFilename(encrypted1);
String encrypted1 = filenameCryptor.encryptFilename(BASE32, origName);
String encrypted2 = filenameCryptor.encryptFilename(BASE32, origName);
String decrypted = filenameCryptor.decryptFilename(BASE32, encrypted1);

Assertions.assertEquals(encrypted1, encrypted2);
Assertions.assertEquals(origName, decrypted);
Expand All @@ -65,9 +66,9 @@ public void testDeterministicEncryptionOfFilenamesWithCustomEncodingAndAssociate
public void testDeterministicEncryptionOf128bitFilename() throws AuthenticationFailedException {
// block size length file names
String originalPath3 = "aaaabbbbccccdddd"; // 128 bit ascii
String encryptedPath3a = filenameCryptor.encryptFilename(originalPath3);
String encryptedPath3b = filenameCryptor.encryptFilename(originalPath3);
String decryptedPath3 = filenameCryptor.decryptFilename(encryptedPath3a);
String encryptedPath3a = filenameCryptor.encryptFilename(BASE32, originalPath3);
String encryptedPath3b = filenameCryptor.encryptFilename(BASE32, originalPath3);
String decryptedPath3 = filenameCryptor.decryptFilename(BASE32, encryptedPath3a);

Assertions.assertEquals(encryptedPath3a, encryptedPath3b);
Assertions.assertEquals(originalPath3, decryptedPath3);
Expand All @@ -86,46 +87,46 @@ public void testDeterministicHashingOfDirectoryIds(String originalDirectoryId) {
@DisplayName("decrypt non-ciphertext")
public void testDecryptionOfMalformedFilename() {
AuthenticationFailedException e = Assertions.assertThrows(AuthenticationFailedException.class, () -> {
filenameCryptor.decryptFilename("lol");
filenameCryptor.decryptFilename(BASE32, "lol");
});
MatcherAssert.assertThat(e.getCause(), CoreMatchers.instanceOf(IllegalArgumentException.class));
}

@Test
@DisplayName("decrypt tampered ciphertext")
public void testDecryptionOfManipulatedFilename() {
final byte[] encrypted = filenameCryptor.encryptFilename("test").getBytes(UTF_8);
final byte[] encrypted = filenameCryptor.encryptFilename(BASE32, "test").getBytes(UTF_8);
encrypted[0] ^= (byte) 0x01; // change 1 bit in first byte

AuthenticationFailedException e = Assertions.assertThrows(AuthenticationFailedException.class, () -> {
filenameCryptor.decryptFilename(new String(encrypted, UTF_8));
filenameCryptor.decryptFilename(BASE32, new String(encrypted, UTF_8));
});
MatcherAssert.assertThat(e.getCause(), CoreMatchers.instanceOf(UnauthenticCiphertextException.class));
}

@Test
@DisplayName("encrypt with different AD")
public void testEncryptionOfSameFilenamesWithDifferentAssociatedData() {
final String encrypted1 = filenameCryptor.encryptFilename("test", "ad1".getBytes(UTF_8));
final String encrypted2 = filenameCryptor.encryptFilename("test", "ad2".getBytes(UTF_8));
final String encrypted1 = filenameCryptor.encryptFilename(BASE32, "test", "ad1".getBytes(UTF_8));
final String encrypted2 = filenameCryptor.encryptFilename(BASE32, "test", "ad2".getBytes(UTF_8));
Assertions.assertNotEquals(encrypted1, encrypted2);
}

@Test
@DisplayName("decrypt ciphertext with correct AD")
public void testDeterministicEncryptionOfFilenamesWithAssociatedData() throws AuthenticationFailedException {
final String encrypted = filenameCryptor.encryptFilename("test", "ad".getBytes(UTF_8));
final String decrypted = filenameCryptor.decryptFilename(encrypted, "ad".getBytes(UTF_8));
final String encrypted = filenameCryptor.encryptFilename(BASE32, "test", "ad".getBytes(UTF_8));
final String decrypted = filenameCryptor.decryptFilename(BASE32, encrypted, "ad".getBytes(UTF_8));
Assertions.assertEquals("test", decrypted);
}

@Test
@DisplayName("decrypt ciphertext with incorrect AD")
public void testDeterministicEncryptionOfFilenamesWithWrongAssociatedData() {
final String encrypted = filenameCryptor.encryptFilename("test", "right".getBytes(UTF_8));
final String encrypted = filenameCryptor.encryptFilename(BASE32, "test", "right".getBytes(UTF_8));

Assertions.assertThrows(AuthenticationFailedException.class, () -> {
filenameCryptor.decryptFilename(encrypted, "wrong".getBytes(UTF_8));
filenameCryptor.decryptFilename(BASE32, encrypted, "wrong".getBytes(UTF_8));
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

public class FileNameCryptorImplTest {

private static final BaseEncoding BASE32 = BaseEncoding.base32();

private final Masterkey masterkey = new Masterkey(new byte[64]);
private final FileNameCryptorImpl filenameCryptor = new FileNameCryptorImpl(masterkey);

Expand All @@ -39,9 +41,9 @@ private static Stream<String> filenameGenerator() {
@ParameterizedTest(name = "decrypt(encrypt({0}))")
@MethodSource("filenameGenerator")
public void testDeterministicEncryptionOfFilenames(String origName) throws AuthenticationFailedException {
String encrypted1 = filenameCryptor.encryptFilename(origName);
String encrypted2 = filenameCryptor.encryptFilename(origName);
String decrypted = filenameCryptor.decryptFilename(encrypted1);
String encrypted1 = filenameCryptor.encryptFilename(BASE32, origName);
String encrypted2 = filenameCryptor.encryptFilename(BASE32, origName);
String decrypted = filenameCryptor.decryptFilename(BASE32, encrypted1);

Assertions.assertEquals(encrypted1, encrypted2);
Assertions.assertEquals(origName, decrypted);
Expand All @@ -65,9 +67,9 @@ public void testDeterministicEncryptionOfFilenamesWithCustomEncodingAndAssociate
public void testDeterministicEncryptionOf128bitFilename() throws AuthenticationFailedException {
// block size length file names
String originalPath3 = "aaaabbbbccccdddd"; // 128 bit ascii
String encryptedPath3a = filenameCryptor.encryptFilename(originalPath3);
String encryptedPath3b = filenameCryptor.encryptFilename(originalPath3);
String decryptedPath3 = filenameCryptor.decryptFilename(encryptedPath3a);
String encryptedPath3a = filenameCryptor.encryptFilename(BASE32, originalPath3);
String encryptedPath3b = filenameCryptor.encryptFilename(BASE32, originalPath3);
String decryptedPath3 = filenameCryptor.decryptFilename(BASE32, encryptedPath3a);

Assertions.assertEquals(encryptedPath3a, encryptedPath3b);
Assertions.assertEquals(originalPath3, decryptedPath3);
Expand All @@ -86,46 +88,46 @@ public void testDeterministicHashingOfDirectoryIds(String originalDirectoryId) {
@DisplayName("decrypt non-ciphertext")
public void testDecryptionOfMalformedFilename() {
AuthenticationFailedException e = Assertions.assertThrows(AuthenticationFailedException.class, () -> {
filenameCryptor.decryptFilename("lol");
filenameCryptor.decryptFilename(BASE32, "lol");
});
MatcherAssert.assertThat(e.getCause(), CoreMatchers.instanceOf(IllegalArgumentException.class));
}

@Test
@DisplayName("decrypt tampered ciphertext")
public void testDecryptionOfManipulatedFilename() {
final byte[] encrypted = filenameCryptor.encryptFilename("test").getBytes(UTF_8);
final byte[] encrypted = filenameCryptor.encryptFilename(BASE32, "test").getBytes(UTF_8);
encrypted[0] ^= (byte) 0x01; // change 1 bit in first byte

AuthenticationFailedException e = Assertions.assertThrows(AuthenticationFailedException.class, () -> {
filenameCryptor.decryptFilename(new String(encrypted, UTF_8));
filenameCryptor.decryptFilename(BASE32, new String(encrypted, UTF_8));
});
MatcherAssert.assertThat(e.getCause(), CoreMatchers.instanceOf(UnauthenticCiphertextException.class));
}

@Test
@DisplayName("encrypt with different AD")
public void testEncryptionOfSameFilenamesWithDifferentAssociatedData() {
final String encrypted1 = filenameCryptor.encryptFilename("test", "ad1".getBytes(UTF_8));
final String encrypted2 = filenameCryptor.encryptFilename("test", "ad2".getBytes(UTF_8));
final String encrypted1 = filenameCryptor.encryptFilename(BASE32, "test", "ad1".getBytes(UTF_8));
final String encrypted2 = filenameCryptor.encryptFilename(BASE32, "test", "ad2".getBytes(UTF_8));
Assertions.assertNotEquals(encrypted1, encrypted2);
}

@Test
@DisplayName("decrypt ciphertext with correct AD")
public void testDeterministicEncryptionOfFilenamesWithAssociatedData() throws AuthenticationFailedException {
final String encrypted = filenameCryptor.encryptFilename("test", "ad".getBytes(UTF_8));
final String decrypted = filenameCryptor.decryptFilename(encrypted, "ad".getBytes(UTF_8));
final String encrypted = filenameCryptor.encryptFilename(BASE32, "test", "ad".getBytes(UTF_8));
final String decrypted = filenameCryptor.decryptFilename(BASE32, encrypted, "ad".getBytes(UTF_8));
Assertions.assertEquals("test", decrypted);
}

@Test
@DisplayName("decrypt ciphertext with incorrect AD")
public void testDeterministicEncryptionOfFilenamesWithWrongAssociatedData() {
final String encrypted = filenameCryptor.encryptFilename("test", "right".getBytes(UTF_8));
final String encrypted = filenameCryptor.encryptFilename(BASE32, "test", "right".getBytes(UTF_8));

Assertions.assertThrows(AuthenticationFailedException.class, () -> {
filenameCryptor.decryptFilename(encrypted, "wrong".getBytes(UTF_8));
filenameCryptor.decryptFilename(BASE32, encrypted, "wrong".getBytes(UTF_8));
});
}

Expand Down

0 comments on commit d32856f

Please sign in to comment.