Sfoglia il codice sorgente

added test to check authentication errors in file headers

Sebastian Stenzel 9 anni fa
parent
commit
c8df03a085

+ 1 - 1
main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/FileContentCryptor.java

@@ -35,7 +35,7 @@ public interface FileContentCryptor {
 	 * @param authenticate Skip authentication by setting this flag to <code>false</code>. Should be <code>true</code> by default.
 	 * @return A possibly new FileContentDecryptor instance which is capable of decrypting ciphertexts associated with the given file header.
 	 */
-	FileContentDecryptor createFileContentDecryptor(ByteBuffer header, long firstCiphertextByte, boolean authenticate) throws IllegalArgumentException;
+	FileContentDecryptor createFileContentDecryptor(ByteBuffer header, long firstCiphertextByte, boolean authenticate) throws IllegalArgumentException, AuthenticationFailedException;
 
 	/**
 	 * @param header The full fixed-length header of an encrypted file or {@link Optional#empty()}. The caller is required to pass the exact amount of bytes returned by {@link #getHeaderSize()}.

+ 2 - 1
main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FileContentCryptorImpl.java

@@ -14,6 +14,7 @@ import java.util.Optional;
 
 import javax.crypto.SecretKey;
 
+import org.cryptomator.crypto.engine.AuthenticationFailedException;
 import org.cryptomator.crypto.engine.FileContentCryptor;
 import org.cryptomator.crypto.engine.FileContentDecryptor;
 import org.cryptomator.crypto.engine.FileContentEncryptor;
@@ -52,7 +53,7 @@ public class FileContentCryptorImpl implements FileContentCryptor {
 	}
 
 	@Override
-	public FileContentDecryptor createFileContentDecryptor(ByteBuffer header, long firstCiphertextByte, boolean authenticate) {
+	public FileContentDecryptor createFileContentDecryptor(ByteBuffer header, long firstCiphertextByte, boolean authenticate) throws IllegalArgumentException, AuthenticationFailedException {
 		if (header.remaining() != getHeaderSize()) {
 			throw new IllegalArgumentException("Invalid header.");
 		}

+ 5 - 3
main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FileHeader.java

@@ -17,6 +17,8 @@ import javax.crypto.Mac;
 import javax.crypto.SecretKey;
 import javax.security.auth.Destroyable;
 
+import org.cryptomator.crypto.engine.AuthenticationFailedException;
+
 class FileHeader implements Destroyable {
 
 	static final int HEADER_SIZE = 88;
@@ -77,7 +79,7 @@ class FileHeader implements Destroyable {
 		payload.destroy();
 	}
 
-	public static FileHeader decrypt(SecretKey headerKey, Supplier<Mac> hmacSha256Factory, ByteBuffer header) throws IllegalArgumentException {
+	public static FileHeader decrypt(SecretKey headerKey, Supplier<Mac> hmacSha256Factory, ByteBuffer header) throws IllegalArgumentException, AuthenticationFailedException {
 		if (header.remaining() != HEADER_SIZE) {
 			throw new IllegalArgumentException("Invalid header size.");
 		}
@@ -97,7 +99,7 @@ class FileHeader implements Destroyable {
 		return new FileHeader(iv, payload);
 	}
 
-	private static void checkHeaderMac(ByteBuffer header, Mac mac) throws IllegalArgumentException {
+	private static void checkHeaderMac(ByteBuffer header, Mac mac) throws AuthenticationFailedException {
 		assert mac.getMacLength() == MAC_LEN;
 		ByteBuffer headerData = header.asReadOnlyBuffer();
 		headerData.position(0).limit(MAC_POS);
@@ -108,7 +110,7 @@ class FileHeader implements Destroyable {
 		headerMac.get(expectedMac);
 
 		if (!MessageDigest.isEqual(expectedMac, mac.doFinal())) {
-			throw new IllegalArgumentException("Corrupt header.");
+			throw new AuthenticationFailedException("Corrupt header.");
 		}
 	}
 

+ 13 - 1
main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/impl/FileContentDecryptorImplTest.java

@@ -64,7 +64,19 @@ public class FileContentDecryptorImplTest {
 	}
 
 	@Test(expected = AuthenticationFailedException.class)
-	public void testManipulatedDecryption() throws InterruptedException {
+	public void testManipulatedHeaderDecryption() throws InterruptedException {
+		final byte[] keyBytes = new byte[32];
+		final SecretKey headerKey = new SecretKeySpec(keyBytes, "AES");
+		final SecretKey macKey = new SecretKeySpec(keyBytes, "HmacSHA256");
+		final byte[] header = Base64.decode("AAAAAAAAAAAAAAAAAAAAANyVwHiiQImjrUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga26lJzstK9RUv1hj5zDC4wC9FgMfoVE1mD0HnuENuYXkJa==");
+
+		try (FileContentDecryptor decryptor = new FileContentDecryptorImpl(headerKey, macKey, ByteBuffer.wrap(header), 0, true)) {
+
+		}
+	}
+
+	@Test(expected = AuthenticationFailedException.class)
+	public void testManipulatedContentDecryption() throws InterruptedException {
 		final byte[] keyBytes = new byte[32];
 		final SecretKey headerKey = new SecretKeySpec(keyBytes, "AES");
 		final SecretKey macKey = new SecretKeySpec(keyBytes, "HmacSHA256");

+ 1 - 1
main/frontend-webdav/src/main/java/org/cryptomator/frontend/webdav/jackrabbitservlet/NullInputContext.java

@@ -5,7 +5,7 @@ import java.io.InputStream;
 
 import org.apache.jackrabbit.webdav.io.InputContext;
 
-public class NullInputContext implements InputContext {
+class NullInputContext implements InputContext {
 
 	@Override
 	public boolean hasStream() {