Skip to content

Commit

Permalink
Encrypt large files with temporary file. NC PR: nextcloud#11777
Browse files Browse the repository at this point in the history
  • Loading branch information
surinder-tsys committed Aug 28, 2023
1 parent 6fa52c6 commit a270987
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,15 @@ protected static File getDummyFile(String name) throws IOException {
}

public static File createFile(String name, int iteration) throws IOException {
File file = new File(FileStorageUtils.getTemporalPath(account.name) + File.separator + name);
File file = new File(FileStorageUtils.getInternalTemporalPath(account.name, targetContext) + File.separator + name);
if (!file.getParentFile().exists()) {
assertTrue(file.getParentFile().mkdirs());
}

if (file.exists()) {
file.delete();
}

file.createNewFile();

FileWriter writer = new FileWriter(file);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.owncloud.android.datamodel.EncryptedFolderMetadata;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.utils.CsrHelper;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.EncryptionUtils;

import org.apache.commons.codec.binary.Hex;
Expand All @@ -44,7 +45,6 @@

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyPair;
Expand All @@ -65,7 +65,6 @@

import androidx.test.runner.AndroidJUnit4;

import static com.owncloud.android.utils.EncryptionUtils.EncryptedFile;
import static com.owncloud.android.utils.EncryptionUtils.decodeStringToBase64Bytes;
import static com.owncloud.android.utils.EncryptionUtils.decryptFile;
import static com.owncloud.android.utils.EncryptionUtils.decryptFolderMetaData;
Expand All @@ -91,6 +90,7 @@
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

@RunWith(AndroidJUnit4.class)
Expand Down Expand Up @@ -401,6 +401,19 @@ public void testCryptFileWithoutMetadata() throws Exception {
assertTrue(cryptFile("ia7OEEEyXMoRa1QWQk8r", "78f42172166f9dc8fd1a7156b1753353", key, iv, authTag));
}

@Test
public void testLargeFile() throws Exception {
byte[] key = decodeStringToBase64Bytes("WANM0gRv+DhaexIsI0T3Lg==");
byte[] iv = decodeStringToBase64Bytes("gKm3n+mJzeY26q4OfuZEqg==");

createFile("large1", 5000000);
File file = getDummyFile("large1");
String md5 = getMD5Sum(file);
Log_OC.d("Large file", "Size: " + DisplayUtils.bytesToHumanReadable(file.length()));

assertTrue(cryptFile(file, md5, key, iv, null));
}

@Test
public void cryptFileWithMetadata() throws Exception {
DecryptedFolderMetadata metadata = generateFolderMetadata();
Expand Down Expand Up @@ -751,28 +764,34 @@ private DecryptedFolderMetadata generateFolderMetadata() throws Exception {
private boolean cryptFile(String fileName, String md5, byte[] key, byte[] iv, byte[] expectedAuthTag)
throws Exception {
File file = getFile(fileName);
assertEquals(md5, getMD5Sum(file));

EncryptedFile encryptedFile = encryptFile(file, key, iv);
return cryptFile(file, md5, key, iv, expectedAuthTag);
}

File encryptedTempFile = File.createTempFile("file", "tmp");
FileOutputStream fileOutputStream = new FileOutputStream(encryptedTempFile);
fileOutputStream.write(encryptedFile.encryptedBytes);
fileOutputStream.close();
private boolean cryptFile(File file, String md5, byte[] key, byte[] iv, byte[] expectedAuthTag)
throws Exception {
assertEquals(md5, getMD5Sum(file));

byte[] authenticationTag = decodeStringToBase64Bytes(encryptedFile.authenticationTag);
File encryptedLargeTempFile = File.createTempFile("largeEncrypted", "tmp");
byte[] authenticationTag = encryptFile(file, encryptedLargeTempFile, key, iv);

// verify authentication tag
assertTrue(Arrays.equals(expectedAuthTag, authenticationTag));
assertNotNull(authenticationTag);

byte[] decryptedBytes = decryptFile(encryptedTempFile, key, iv, authenticationTag);
// verify authentication tag
if (expectedAuthTag != null) {
assertEquals(expectedAuthTag, authenticationTag);
}

File decryptedFile = File.createTempFile("file", "dec");
FileOutputStream fileOutputStream1 = new FileOutputStream(decryptedFile);
fileOutputStream1.write(decryptedBytes);
fileOutputStream1.close();
File decryptedLargeTempFile = File.createTempFile("largeDecrypted", "tmp");
assertTrue(decryptFile(encryptedLargeTempFile,
decryptedLargeTempFile,
key,
iv,
authenticationTag
)
);

return md5.compareTo(getMD5Sum(decryptedFile)) == 0;
return md5.compareTo(getMD5Sum(decryptedLargeTempFile)) == 0;
}

private String getMD5Sum(File file) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import com.owncloud.android.utils.FileStorageUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
Expand Down Expand Up @@ -213,11 +212,18 @@ protected RemoteOperationResult run(OwnCloudClient client) {
.get(file.getEncryptedFileName()).getAuthenticationTag());

try {
byte[] decryptedBytes = EncryptionUtils.decryptFile(tmpFile, key, iv, authenticationTag);
File decryptedFile = new File(getTmpPath() + "_dec");
boolean success = EncryptionUtils.decryptFile(tmpFile, decryptedFile, key, iv, authenticationTag);

try (FileOutputStream fileOutputStream = new FileOutputStream(tmpFile)) {
fileOutputStream.write(decryptedBytes);
if (!success) {
return new RemoteOperationResult(new IllegalStateException("Decryption went wrong!"));
}

decryptedFile.renameTo(tmpFile);
if (decryptedFile.exists()) {
decryptedFile.delete();
}

} catch (Exception e) {
return new RemoteOperationResult(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -509,8 +509,6 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare
// IV, always generate new one
byte[] iv = EncryptionUtils.randomBytes(EncryptionUtils.ivLength);

EncryptionUtils.EncryptedFile encryptedFile = EncryptionUtils.encryptFile(mFile, key, iv);

// new random file name, check if it exists in metadata
String encryptedFileName = UUID.randomUUID().toString().replaceAll("-", "");

Expand All @@ -519,9 +517,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare
}

File encryptedTempFile = File.createTempFile("encFile", encryptedFileName);
FileOutputStream fileOutputStream = new FileOutputStream(encryptedTempFile);
fileOutputStream.write(encryptedFile.encryptedBytes);
fileOutputStream.close();
byte[] authenticationTag = EncryptionUtils.encryptFile(mFile, encryptedTempFile, key, iv);

/***** E2E *****/

Expand Down Expand Up @@ -614,7 +610,7 @@ private RemoteOperationResult encryptedUpload(OwnCloudClient client, OCFile pare

decryptedFile.setEncrypted(data);
decryptedFile.setInitializationVector(EncryptionUtils.encodeBytesToBase64String(iv));
decryptedFile.setAuthenticationTag(encryptedFile.authenticationTag);
decryptedFile.setAuthenticationTag(EncryptionUtils.encodeBytesToBase64String(authenticationTag));

metadata.getFiles().put(encryptedFileName, decryptedFile);

Expand Down
Loading

0 comments on commit a270987

Please sign in to comment.