Browse Source

non-interchangable chunks by adding additional data to MACs

Sebastian Stenzel 9 years ago
parent
commit
8c4d5a9614

+ 16 - 0
main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java

@@ -423,6 +423,7 @@ public class Aes256Cryptor implements Cryptor, AesCryptographicConfiguration {
 		final InputStream in = new SeekableByteChannelInputStream(encryptedFile);
 		byte[] buffer = new byte[CONTENT_MAC_BLOCK + 32];
 		int n = 0;
+		long blockNum = 0;
 		while ((n = IOUtils.read(in, buffer)) > 0) {
 			if (n < 32) {
 				throw new DecryptFailedException("Invalid file content, missing MAC.");
@@ -430,6 +431,8 @@ public class Aes256Cryptor implements Cryptor, AesCryptographicConfiguration {
 
 			// check MAC of current block:
 			if (authenticate) {
+				contentMac.update(iv);
+				contentMac.update(longToByteArray(blockNum));
 				contentMac.update(buffer, 0, n - 32);
 				final byte[] calculatedMac = contentMac.doFinal();
 				final byte[] storedMac = new byte[32];
@@ -444,6 +447,7 @@ public class Aes256Cryptor implements Cryptor, AesCryptographicConfiguration {
 			final int plaintextLengthWithoutPadding = (int) Math.min(plaintext.length, fileSize - bytesDecrypted); // plaintext.length is known to be a 32 bit int
 			plaintextFile.write(plaintext, 0, plaintextLengthWithoutPadding);
 			bytesDecrypted += plaintextLengthWithoutPadding;
+			blockNum++;
 		}
 		destroyQuietly(fileKey);
 
@@ -521,6 +525,7 @@ public class Aes256Cryptor implements Cryptor, AesCryptographicConfiguration {
 			final InputStream in = new SeekableByteChannelInputStream(encryptedFile);
 			byte[] buffer = new byte[CONTENT_MAC_BLOCK + 32];
 			int n = 0;
+			long blockNum = startBlock;
 			while ((n = IOUtils.read(in, buffer)) > 0 && bytesWritten < length) {
 				if (n < 32) {
 					throw new DecryptFailedException("Invalid file content, missing MAC.");
@@ -528,6 +533,8 @@ public class Aes256Cryptor implements Cryptor, AesCryptographicConfiguration {
 
 				// check MAC of current block:
 				if (authenticate) {
+					contentMac.update(iv);
+					contentMac.update(longToByteArray(blockNum));
 					contentMac.update(buffer, 0, n - 32);
 					final byte[] calculatedMac = contentMac.doFinal();
 					final byte[] storedMac = new byte[32];
@@ -546,6 +553,7 @@ public class Aes256Cryptor implements Cryptor, AesCryptographicConfiguration {
 
 				plaintextFile.write(plaintext, offset, currentBatch);
 				bytesWritten += currentBatch;
+				blockNum++;
 			}
 			return bytesWritten;
 		} finally {
@@ -593,12 +601,16 @@ public class Aes256Cryptor implements Cryptor, AesCryptographicConfiguration {
 		// writing ciphered output and MACs interleaved:
 		final byte[] buffer = new byte[CONTENT_MAC_BLOCK];
 		int n = 0;
+		long blockNum = 0;
 		while ((n = IOUtils.read(in, buffer)) > 0) {
 			final byte[] ciphertext = cipher.update(buffer, 0, n);
 			out.write(ciphertext);
+			contentMac.update(iv);
+			contentMac.update(longToByteArray(blockNum));
 			contentMac.update(ciphertext);
 			final byte[] mac = contentMac.doFinal();
 			out.write(mac);
+			blockNum++;
 		}
 		destroyQuietly(fileKey);
 
@@ -623,4 +635,8 @@ public class Aes256Cryptor implements Cryptor, AesCryptographicConfiguration {
 		return plaintextSize;
 	}
 
+	private byte[] longToByteArray(long lng) {
+		return ByteBuffer.allocate(Long.SIZE).putLong(lng).array();
+	}
+
 }