Skip to content

Commit

Permalink
added test to check authentication errors in file headers
Browse files Browse the repository at this point in the history
  • Loading branch information
overheadhunter committed Feb 22, 2016
1 parent 5df9f35 commit c8df03a
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 7 deletions.
Expand Up @@ -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. * @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. * @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()}. * @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()}.
Expand Down
Expand Up @@ -14,6 +14,7 @@


import javax.crypto.SecretKey; import javax.crypto.SecretKey;


import org.cryptomator.crypto.engine.AuthenticationFailedException;
import org.cryptomator.crypto.engine.FileContentCryptor; import org.cryptomator.crypto.engine.FileContentCryptor;
import org.cryptomator.crypto.engine.FileContentDecryptor; import org.cryptomator.crypto.engine.FileContentDecryptor;
import org.cryptomator.crypto.engine.FileContentEncryptor; import org.cryptomator.crypto.engine.FileContentEncryptor;
Expand Down Expand Up @@ -52,7 +53,7 @@ public long toCiphertextPos(long cleartextPos) {
} }


@Override @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()) { if (header.remaining() != getHeaderSize()) {
throw new IllegalArgumentException("Invalid header."); throw new IllegalArgumentException("Invalid header.");
} }
Expand Down
Expand Up @@ -17,6 +17,8 @@
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.security.auth.Destroyable; import javax.security.auth.Destroyable;


import org.cryptomator.crypto.engine.AuthenticationFailedException;

class FileHeader implements Destroyable { class FileHeader implements Destroyable {


static final int HEADER_SIZE = 88; static final int HEADER_SIZE = 88;
Expand Down Expand Up @@ -77,7 +79,7 @@ public void destroy() {
payload.destroy(); 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) { if (header.remaining() != HEADER_SIZE) {
throw new IllegalArgumentException("Invalid header size."); throw new IllegalArgumentException("Invalid header size.");
} }
Expand All @@ -97,7 +99,7 @@ public static FileHeader decrypt(SecretKey headerKey, Supplier<Mac> hmacSha256Fa
return new FileHeader(iv, payload); 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; assert mac.getMacLength() == MAC_LEN;
ByteBuffer headerData = header.asReadOnlyBuffer(); ByteBuffer headerData = header.asReadOnlyBuffer();
headerData.position(0).limit(MAC_POS); headerData.position(0).limit(MAC_POS);
Expand All @@ -108,7 +110,7 @@ private static void checkHeaderMac(ByteBuffer header, Mac mac) throws IllegalArg
headerMac.get(expectedMac); headerMac.get(expectedMac);


if (!MessageDigest.isEqual(expectedMac, mac.doFinal())) { if (!MessageDigest.isEqual(expectedMac, mac.doFinal())) {
throw new IllegalArgumentException("Corrupt header."); throw new AuthenticationFailedException("Corrupt header.");
} }
} }


Expand Down
Expand Up @@ -64,7 +64,19 @@ public void testDecryption() throws InterruptedException {
} }


@Test(expected = AuthenticationFailedException.class) @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 byte[] keyBytes = new byte[32];
final SecretKey headerKey = new SecretKeySpec(keyBytes, "AES"); final SecretKey headerKey = new SecretKeySpec(keyBytes, "AES");
final SecretKey macKey = new SecretKeySpec(keyBytes, "HmacSHA256"); final SecretKey macKey = new SecretKeySpec(keyBytes, "HmacSHA256");
Expand Down
Expand Up @@ -5,7 +5,7 @@


import org.apache.jackrabbit.webdav.io.InputContext; import org.apache.jackrabbit.webdav.io.InputContext;


public class NullInputContext implements InputContext { class NullInputContext implements InputContext {


@Override @Override
public boolean hasStream() { public boolean hasStream() {
Expand Down

0 comments on commit c8df03a

Please sign in to comment.