diff --git a/src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java b/src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java index 5a89250672..b73924f811 100644 --- a/src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java +++ b/src/androidTest/java/com/owncloud/android/util/EncryptionTestIT.java @@ -53,10 +53,6 @@ import java.util.HashSet; import java.util.Set; import static android.support.test.InstrumentationRegistry.getInstrumentation; -import static com.owncloud.android.utils.EncryptionUtils.decodeStringToBase64Bytes; -import static com.owncloud.android.utils.EncryptionUtils.encodeBytesToBase64String; -import static com.owncloud.android.utils.EncryptionUtils.generateIV; -import static com.owncloud.android.utils.EncryptionUtils.generateKey; import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; @@ -117,7 +113,7 @@ public class EncryptionTestIT { @Test public void encryptStringAsymmetric() throws Exception { byte[] key1 = EncryptionUtils.generateKey(); - String base64encodedKey = encodeBytesToBase64String(key1); + String base64encodedKey = EncryptionUtils.encodeBytesToBase64String(key1); String encryptedString = EncryptionUtils.encryptStringAsymmetric(base64encodedKey, cert); String decryptedString = EncryptionUtils.decryptStringAsymmetric(encryptedString, privateKey); @@ -129,7 +125,7 @@ public class EncryptionTestIT { @Test public void encryptStringSymmetric() throws Exception { - byte[] key = generateKey(); + byte[] key = EncryptionUtils.generateKey(); String encryptedString = EncryptionUtils.encryptStringSymmetric(privateKey, key); String decryptedString = EncryptionUtils.decryptStringSymmetric(encryptedString, key); @@ -146,7 +142,7 @@ public class EncryptionTestIT { KeyPair keyPair = keyGen.generateKeyPair(); PrivateKey privateKey = keyPair.getPrivate(); byte[] privateKeyBytes = privateKey.getEncoded(); - String privateKeyString = encodeBytesToBase64String(privateKeyBytes); + String privateKeyString = EncryptionUtils.encodeBytesToBase64String(privateKeyBytes); String encryptedString = EncryptionUtils.encryptPrivateKey(privateKeyString, keyPhrase); String decryptedString = EncryptionUtils.decryptPrivateKey(encryptedString, keyPhrase); @@ -164,7 +160,7 @@ public class EncryptionTestIT { String urlEncoded = URLEncoder.encode("-----BEGIN CERTIFICATE REQUEST-----\n" + string + "\n-----END CERTIFICATE REQUEST-----", "UTF-8"); - Log_OC.d(TAG, "public: " + encodeBytesToBase64String(keyPair.getPublic().getEncoded())); + Log_OC.d(TAG, "public: " + EncryptionUtils.encodeBytesToBase64String(keyPair.getPublic().getEncoded())); Log_OC.d(TAG, "csrPEM: " + string); Log_OC.d(TAG, "csrPEM: " + urlEncoded); } @@ -234,7 +230,7 @@ public class EncryptionTestIT { Set keys = new HashSet<>(); for (int i = 0; i < 50; i++) { - assertTrue(keys.add(encodeBytesToBase64String(generateKey()))); + assertTrue(keys.add(EncryptionUtils.encodeBytesToBase64String(EncryptionUtils.generateKey()))); } } @@ -246,7 +242,7 @@ public class EncryptionTestIT { Set ivs = new HashSet<>(); for (int i = 0; i < 50; i++) { - assertTrue(ivs.add(encodeBytesToBase64String(generateIV()))); + assertTrue(ivs.add(EncryptionUtils.encodeBytesToBase64String(EncryptionUtils.generateIV()))); } } @@ -267,9 +263,9 @@ public class EncryptionTestIT { } private DecryptedFolderMetadata generateFolderMetadata() throws Exception { - String metadataKey0 = encodeBytesToBase64String(EncryptionUtils.generateKey()); - String metadataKey1 = encodeBytesToBase64String(EncryptionUtils.generateKey()); - String metadataKey2 = encodeBytesToBase64String(EncryptionUtils.generateKey()); + String metadataKey0 = EncryptionUtils.encodeBytesToBase64String(EncryptionUtils.generateKey()); + String metadataKey1 = EncryptionUtils.encodeBytesToBase64String(EncryptionUtils.generateKey()); + String metadataKey2 = EncryptionUtils.encodeBytesToBase64String(EncryptionUtils.generateKey()); HashMap metadataKeys = new HashMap<>(); metadataKeys.put(0, EncryptionUtils.encryptStringAsymmetric(metadataKey0, cert)); metadataKeys.put(1, EncryptionUtils.encryptStringAsymmetric(metadataKey1, cert)); @@ -332,7 +328,7 @@ public class EncryptionTestIT { fileOutputStream.write(encryptedFile.encryptedBytes); fileOutputStream.close(); - byte[] authenticationTag = decodeStringToBase64Bytes(encryptedFile.authenticationTag); + byte[] authenticationTag = EncryptionUtils.decodeStringToBase64Bytes(encryptedFile.authenticationTag); // verify authentication tag assertTrue(Arrays.equals(expectedAuthTag, authenticationTag)); diff --git a/src/main/java/com/owncloud/android/MainApp.java b/src/main/java/com/owncloud/android/MainApp.java index d4f72a5d58..e97d9ec694 100644 --- a/src/main/java/com/owncloud/android/MainApp.java +++ b/src/main/java/com/owncloud/android/MainApp.java @@ -64,7 +64,6 @@ import com.owncloud.android.utils.AnalyticsUtils; import com.owncloud.android.utils.FilesSyncHelper; import com.owncloud.android.utils.PermissionUtil; import com.owncloud.android.utils.ReceiversHelper; -import com.owncloud.android.utils.EncryptionUtils; import java.lang.reflect.Method; import java.util.ArrayList; @@ -72,8 +71,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.crypto.Cipher; - import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; diff --git a/src/main/java/com/owncloud/android/files/services/FileUploader.java b/src/main/java/com/owncloud/android/files/services/FileUploader.java index bbec886765..53e4b80423 100644 --- a/src/main/java/com/owncloud/android/files/services/FileUploader.java +++ b/src/main/java/com/owncloud/android/files/services/FileUploader.java @@ -1055,19 +1055,8 @@ public class FileUploader extends Service mUploadClient = OwnCloudClientManagerFactory.getDefaultSingleton(). getClientFor(ocAccount, this); - -// // If parent folder is encrypted, upload file encrypted -// OCFile parent = mStorageManager.getFileByPath(mCurrentUpload.getFile().getParentRemotePath()); - -// if (parent.isEncrypted()) { -// UploadEncryptedFileOperation uploadEncryptedFileOperation = -// new UploadEncryptedFileOperation(parent, mCurrentUpload); -// -// uploadResult = uploadEncryptedFileOperation.execute(mUploadClient, mStorageManager); -// } else { - /// perform the regular upload - uploadResult = mCurrentUpload.execute(mUploadClient, mStorageManager); -// } + /// perform the upload + uploadResult = mCurrentUpload.execute(mUploadClient, mStorageManager); } catch (Exception e) { diff --git a/src/main/java/com/owncloud/android/operations/RemoveRemoteEncryptedFileOperation.java b/src/main/java/com/owncloud/android/operations/RemoveRemoteEncryptedFileOperation.java index c00a795f2c..2a95f75b6a 100644 --- a/src/main/java/com/owncloud/android/operations/RemoveRemoteEncryptedFileOperation.java +++ b/src/main/java/com/owncloud/android/operations/RemoveRemoteEncryptedFileOperation.java @@ -88,7 +88,6 @@ public class RemoveRemoteEncryptedFileOperation extends RemoteOperation { DecryptedFolderMetadata metadata; String privateKey = arbitraryDataProvider.getValue(account.name, EncryptionUtils.PRIVATE_KEY); - String publicKey = arbitraryDataProvider.getValue(account.name, EncryptionUtils.PUBLIC_KEY); // unlock @@ -100,9 +99,9 @@ public class RemoveRemoteEncryptedFileOperation extends RemoteOperation { if (lockFileOperationResult.isSuccess()) { token = (String) lockFileOperationResult.getData().get(0); } else if (lockFileOperationResult.getHttpCode() == HttpStatus.SC_FORBIDDEN) { - throw new Exception("Forbidden! Please try again later.)"); + throw new RuntimeException("Forbidden! Please try again later.)"); } else { - throw new Exception("Unknown error!"); + throw new RuntimeException("Unknown error!"); } // refresh metadata @@ -119,7 +118,7 @@ public class RemoveRemoteEncryptedFileOperation extends RemoteOperation { metadata = EncryptionUtils.decryptFolderMetaData(encryptedFolderMetadata, privateKey); } else { - throw new Exception("No Metadata found!"); + throw new RuntimeException("No Metadata found!"); } // delete file remote @@ -143,7 +142,7 @@ public class RemoveRemoteEncryptedFileOperation extends RemoteOperation { RemoteOperationResult uploadMetadataOperationResult = storeMetadataOperation.execute(client); if (!uploadMetadataOperationResult.isSuccess()) { - throw new Exception(); + throw new RuntimeException(); } // return success diff --git a/src/main/java/com/owncloud/android/operations/UploadEncryptedFileOperation.java b/src/main/java/com/owncloud/android/operations/UploadEncryptedFileOperation.java deleted file mode 100644 index f3dd80bbad..0000000000 --- a/src/main/java/com/owncloud/android/operations/UploadEncryptedFileOperation.java +++ /dev/null @@ -1,880 +0,0 @@ -/* - * Nextcloud Android client application - * - * @author Tobias Kaminsky - * Copyright (C) 2017 Tobias Kaminsky - * Copyright (C) 2017 Nextcloud GmbH. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package com.owncloud.android.operations; - -import android.accounts.Account; -import android.content.Context; -import android.os.Build; -import android.support.annotation.RequiresApi; - -import com.google.gson.reflect.TypeToken; -import com.owncloud.android.datamodel.ArbitraryDataProvider; -import com.owncloud.android.datamodel.DecryptedFolderMetadata; -import com.owncloud.android.datamodel.EncryptedFolderMetadata; -import com.owncloud.android.datamodel.FileDataStorageManager; -import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.files.services.FileUploader; -import com.owncloud.android.lib.common.OwnCloudClient; -import com.owncloud.android.lib.common.network.OnDatatransferProgressListener; -import com.owncloud.android.lib.common.network.ProgressiveDataTransferer; -import com.owncloud.android.lib.common.operations.OperationCancelledException; -import com.owncloud.android.lib.common.operations.RemoteOperation; -import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; -import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.lib.resources.files.ChunkedUploadRemoteFileOperation; -import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation; -import com.owncloud.android.lib.resources.files.GetMetadataOperation; -import com.owncloud.android.lib.resources.files.LockFileOperation; -import com.owncloud.android.lib.resources.files.ReadRemoteFileOperation; -import com.owncloud.android.lib.resources.files.RemoteFile; -import com.owncloud.android.lib.resources.files.StoreMetadataOperation; -import com.owncloud.android.lib.resources.files.UnlockFileOperation; -import com.owncloud.android.lib.resources.files.UpdateMetadataOperation; -import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation; -import com.owncloud.android.operations.common.SyncOperation; -import com.owncloud.android.utils.EncryptionUtils; -import com.owncloud.android.utils.FileStorageUtils; -import com.owncloud.android.utils.MimeType; - -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.methods.RequestEntity; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; -import java.nio.channels.OverlappingFileLockException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; - -import static com.owncloud.android.utils.EncryptionUtils.encodeStringToBase64Bytes; - - -/** - * Operation performing the update in the ownCloud server - * of a file that was modified locally. - */ -@RequiresApi(api = Build.VERSION_CODES.KITKAT) -public class UploadEncryptedFileOperation extends SyncOperation { - - private static final String TAG = UploadEncryptedFileOperation.class.getSimpleName(); - - public static final int CREATED_BY_USER = 0; - public static final int CREATED_AS_INSTANT_PICTURE = 1; - public static final int CREATED_AS_INSTANT_VIDEO = 2; - private OCFile parentFile; - - /** - * OCFile which is to be uploaded. - */ - private OCFile ocFile; - private int localBehaviour = FileUploader.LOCAL_BEHAVIOUR_COPY; - private final String originalStoragePath; - private boolean chunked = false; - private boolean mRemoteFolderToBeCreated = false; - private int mCreatedBy = CREATED_BY_USER; - - private long mOCUploadId = -1; - /** - * Local path to file which is to be uploaded (before any possible renaming or moving). - */ - private Set mDataTransferListeners = new HashSet(); - - private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); - private final AtomicBoolean mUploadStarted = new AtomicBoolean(false); - - private Context context; - - private UploadRemoteFileOperation mUploadOperation; - - protected RequestEntity mEntity = null; - - private Account account; - private ArbitraryDataProvider arbitraryDataProvider; - - public UploadEncryptedFileOperation(OCFile parent, UploadFileOperation uploadFileOperation) { - parentFile = parent; - ocFile = uploadFileOperation.getFile(); - account = uploadFileOperation.getAccount(); - chunked = uploadFileOperation.isChunkedUploadSupported(); - context = uploadFileOperation.getContext(); - localBehaviour = uploadFileOperation.getLocalBehaviour(); - originalStoragePath = uploadFileOperation.getStoragePath(); - - arbitraryDataProvider = new ArbitraryDataProvider(context.getContentResolver()); - } - - public Account getAccount() { - return account; - } - - public String getFileName() { - return (ocFile != null) ? ocFile.getFileName() : null; - } - - public OCFile getFile() { - return ocFile; - } - - public String getStoragePath() { - return ocFile.getStoragePath(); - } - - public String getRemotePath() { - return ocFile.getParentRemotePath() + ocFile.getEncryptedFileName(); - } - - public String getMimeType() { - return ocFile.getMimetype(); - } - - public void setRemoteFolderToBeCreated() { - mRemoteFolderToBeCreated = true; - } - - public void setCreatedBy(int createdBy) { - mCreatedBy = createdBy; - if (createdBy < CREATED_BY_USER || CREATED_AS_INSTANT_VIDEO < createdBy) { - mCreatedBy = CREATED_BY_USER; - } - } - - public int getCreatedBy() { - return mCreatedBy; - } - - public boolean isInstantPicture() { - return mCreatedBy == CREATED_AS_INSTANT_PICTURE; - } - - public boolean isInstantVideo() { - return mCreatedBy == CREATED_AS_INSTANT_VIDEO; - } - - public void setOCUploadId(long id) { - mOCUploadId = id; - } - - public long getOCUploadId() { - return mOCUploadId; - } - - public Set getDataTransferListeners() { - return mDataTransferListeners; - } - - public void addDatatransferProgressListener(OnDatatransferProgressListener listener) { - synchronized (mDataTransferListeners) { - mDataTransferListeners.add(listener); - } - if (mEntity != null) { - ((ProgressiveDataTransferer) mEntity).addDatatransferProgressListener(listener); - } - if (mUploadOperation != null) { - mUploadOperation.addDatatransferProgressListener(listener); - } - } - - public void removeDatatransferProgressListener(OnDatatransferProgressListener listener) { - synchronized (mDataTransferListeners) { - mDataTransferListeners.remove(listener); - } - if (mEntity != null) { - ((ProgressiveDataTransferer) mEntity).removeDatatransferProgressListener(listener); - } - if (mUploadOperation != null) { - mUploadOperation.removeDatatransferProgressListener(listener); - } - } - - @Override - protected RemoteOperationResult run(OwnCloudClient client) { - RemoteOperationResult result = null; - boolean metadataExists = false; - String token = null; - mCancellationRequested.set(false); - mUploadStarted.set(true); - - File temporalFile = null; - File originalFile = new File(ocFile.getStoragePath()); - File expectedFile = null; - FileLock fileLock = null; - - String privateKey = arbitraryDataProvider.getValue(account.name, EncryptionUtils.PRIVATE_KEY); - String publicKey = arbitraryDataProvider.getValue(account.name, EncryptionUtils.PUBLIC_KEY); - - try { - - /// check if the file continues existing before schedule the operation - if (!originalFile.exists()) { - Log_OC.d(TAG, ocFile.getStoragePath() + " not exists anymore"); - throw new FileNotFoundException(); - } - - /// check the existence of the parent folder for the file to upload - String remoteParentPath = new File(getRemotePath()).getParent(); - remoteParentPath = remoteParentPath.endsWith(OCFile.PATH_SEPARATOR) ? - remoteParentPath : remoteParentPath + OCFile.PATH_SEPARATOR; - result = grantFolderExistence(remoteParentPath, client); - - if (!result.isSuccess()) { - return result; - } - - // TODO automatic rename? UploadFileOperation:365 - - /// set parent local id in uploading file -// OCFile parent = getStorageManager().getFileByPath(remoteParentPath); -// ocFile.setParentId(parent.getFileId()); - - -// if (mCancellationRequested.get()) { -// throw new OperationCancelledException(); -// } - - // Get the last modification date of the file from the file system - Long timeStampLong = originalFile.lastModified() / 1000; - String timeStamp = timeStampLong.toString(); - - // Lock folder - LockFileOperation lockFileOperation = new LockFileOperation(parentFile.getLocalId()); - RemoteOperationResult lockFileOperationResult = lockFileOperation.execute(client); - - - if (lockFileOperationResult.isSuccess()) { - token = (String) lockFileOperationResult.getData().get(0); - } else if (lockFileOperationResult.getHttpCode() == HttpStatus.SC_FORBIDDEN) { - throw new Exception("Forbidden! Please try again later.)"); - } else { - throw new Exception("Unknown error!"); - } - - // Update metadata - GetMetadataOperation getMetadataOperation = new GetMetadataOperation(parentFile.getLocalId()); - RemoteOperationResult getMetadataOperationResult = getMetadataOperation.execute(client); - - DecryptedFolderMetadata metadata; - - if (getMetadataOperationResult.isSuccess()) { - metadataExists = true; - - // decrypt metadata - String serializedEncryptedMetadata = (String) getMetadataOperationResult.getData().get(0); - - - EncryptedFolderMetadata encryptedFolderMetadata = EncryptionUtils.deserializeJSON( - serializedEncryptedMetadata, new TypeToken() { - }); - - metadata = EncryptionUtils.decryptFolderMetaData(encryptedFolderMetadata, privateKey); - - } else if (getMetadataOperationResult.getHttpCode() == HttpStatus.SC_NOT_FOUND) { - // new metadata - metadata = new DecryptedFolderMetadata(); - metadata.metadata = new DecryptedFolderMetadata.Metadata(); - metadata.metadata.metadataKeys = new HashMap<>(); - String metadataKey = EncryptionUtils.encodeBytesToBase64String(EncryptionUtils.generateKey()); - String encryptedMetadataKey = EncryptionUtils.encryptStringAsymmetric(metadataKey, publicKey); - metadata.metadata.metadataKeys.put(0, encryptedMetadataKey); - } else { - // TODO error - throw new Exception("something wrong"); - } - - // Key - byte[] key = null; - - try { - // TODO change key if file has changed, e.g. when file is updated - key = encodeStringToBase64Bytes(metadata.files.get(ocFile.getFileName()).encrypted.key); - } catch (Exception e) { - // no key found - } - - if (key == null || key.length == 0) { - key = EncryptionUtils.generateKey(); - } - - // IV - byte[] iv = null; - - try { - iv = encodeStringToBase64Bytes(metadata.files.get(ocFile.getFileName()).initializationVector); - } catch (Exception e) { - // no iv found - } - - if (iv == null || iv.length == 0) { - iv = EncryptionUtils.generateIV(); - } - - - EncryptionUtils.EncryptedFile encryptedFile = EncryptionUtils.encryptFile(ocFile, key, iv); - - // new random file name, check if it exists in metadata - String encryptedFileName = UUID.randomUUID().toString().replaceAll("-", ""); - - while (metadata.files.get(encryptedFileName) != null) { - encryptedFileName = UUID.randomUUID().toString().replaceAll("-", ""); - } - - ocFile.setEncryptedFileName(encryptedFileName); - - File encryptedTempFile = File.createTempFile("encFile", encryptedFileName); - FileOutputStream fileOutputStream = new FileOutputStream(encryptedTempFile); - fileOutputStream.write(encryptedFile.encryptedBytes); - fileOutputStream.close(); - - /// perform the upload - if (chunked && - (new File(ocFile.getStoragePath())).length() > - ChunkedUploadRemoteFileOperation.CHUNK_SIZE) { - mUploadOperation = new ChunkedUploadRemoteFileOperation(context, encryptedTempFile.getAbsolutePath(), - ocFile.getParentRemotePath() + encryptedFileName, ocFile.getMimetype(), - ocFile.getEtagInConflict(), timeStamp); - } else { - mUploadOperation = new UploadRemoteFileOperation(encryptedTempFile.getAbsolutePath(), - ocFile.getParentRemotePath() + encryptedFileName, ocFile.getMimetype(), - ocFile.getEtagInConflict(), timeStamp); - } - - Iterator listener = mDataTransferListeners.iterator(); - while (listener.hasNext()) { - mUploadOperation.addDatatransferProgressListener(listener.next()); - } - - if (mCancellationRequested.get()) { - throw new OperationCancelledException(); - } - -// FileChannel channel = null; -// try { -// channel = new RandomAccessFile(ocFile.getStoragePath(), "rw").getChannel(); -// fileLock = channel.tryLock(); -// } catch (FileNotFoundException e) { -// if (temporalFile == null) { -// String temporalPath = FileStorageUtils.getTemporalPath(account.name) + ocFile.getRemotePath(); -// ocFile.setStoragePath(temporalPath); -// temporalFile = new File(temporalPath); -// -// result = copy(originalFile, temporalFile); -// -// if (result != null) { -// return result; -// } else { -// if (temporalFile.length() == originalFile.length()) { -// channel = new RandomAccessFile(temporalFile.getAbsolutePath(), "rw").getChannel(); -// fileLock = channel.tryLock(); -// } else { -// while (temporalFile.length() != originalFile.length()) { -// Files.deleteIfExists(Paths.get(temporalPath)); -// result = copy(originalFile, temporalFile); -// -// if (result != null) { -// return result; -// } else { -// channel = new RandomAccessFile(temporalFile.getAbsolutePath(), "rw"). -// getChannel(); -// fileLock = channel.tryLock(); -// } -// } -// } -// } -// } else { -// channel = new RandomAccessFile(temporalFile.getAbsolutePath(), "rw").getChannel(); -// fileLock = channel.tryLock(); -// } -// } - - result = mUploadOperation.execute(client); - - /// move local temporal file or original file to its corresponding - // location in the ownCloud local folder - if (!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_PRECONDITION_FAILED) { - result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT); - } - - if (result.isSuccess()) { - // upload metadata - DecryptedFolderMetadata.DecryptedFile decryptedFile = new DecryptedFolderMetadata.DecryptedFile(); - DecryptedFolderMetadata.Data data = new DecryptedFolderMetadata.Data(); - data.filename = ocFile.getFileName(); - data.mimetype = ocFile.getMimetype(); - data.key = EncryptionUtils.encodeBytesToBase64String(key); - - decryptedFile.encrypted = data; - decryptedFile.initializationVector = EncryptionUtils.encodeBytesToBase64String(iv); - decryptedFile.authenticationTag = encryptedFile.authenticationTag; - - metadata.files.put(encryptedFileName, decryptedFile); - - EncryptedFolderMetadata encryptedFolderMetadata = EncryptionUtils.encryptFolderMetadata(metadata, - privateKey); - String serializedFolderMetadata = EncryptionUtils.serializeJSON(encryptedFolderMetadata); - - // upload metadata - RemoteOperationResult uploadMetadataOperationResult; - if (metadataExists) { - // update metadata - UpdateMetadataOperation storeMetadataOperation = new UpdateMetadataOperation(parentFile.getLocalId(), - serializedFolderMetadata, token); - uploadMetadataOperationResult = storeMetadataOperation.execute(client); - } else { - // store metadata - StoreMetadataOperation storeMetadataOperation = new StoreMetadataOperation(parentFile.getLocalId(), - serializedFolderMetadata); - uploadMetadataOperationResult = storeMetadataOperation.execute(client); - } - - if (!uploadMetadataOperationResult.isSuccess()) { - throw new Exception(); - } - } - } catch (FileNotFoundException e) { - Log_OC.d(TAG, ocFile.getStoragePath() + " not exists anymore"); - result = new RemoteOperationResult(ResultCode.LOCAL_FILE_NOT_FOUND); - } catch (OverlappingFileLockException e) { - Log_OC.d(TAG, "Overlapping file lock exception"); - result = new RemoteOperationResult(ResultCode.LOCK_FAILED); - } catch (Exception e) { - result = new RemoteOperationResult(e); - - } finally { - mUploadStarted.set(false); - - // unlock file - if (token != null) { - UnlockFileOperation unlockFileOperation = new UnlockFileOperation(parentFile.getLocalId(), token); - RemoteOperationResult unlockFileOperationResult = unlockFileOperation.execute(client); - - if (!unlockFileOperationResult.isSuccess()) { - Log_OC.e(TAG, "Failed to unlock " + parentFile.getLocalId()); - } - } - - if (fileLock != null) { - try { - fileLock.release(); - } catch (IOException e) { - Log_OC.e(TAG, "Failed to unlock file with path " + ocFile.getStoragePath()); - } - } - - if (temporalFile != null && !originalFile.equals(temporalFile)) { - temporalFile.delete(); - } - if (result == null) { - result = new RemoteOperationResult(ResultCode.UNKNOWN_ERROR); - } - if (result.isSuccess()) { - Log_OC.i(TAG, "Upload of " + ocFile.getStoragePath() + " to " + ocFile.getRemotePath() + ": " + - result.getLogMessage()); - } else { - if (result.getException() != null) { - if (result.isCancelled()) { - Log_OC.w(TAG, "Upload of " + ocFile.getStoragePath() + " to " + ocFile.getRemotePath() + - ": " + result.getLogMessage()); - } else { - Log_OC.e(TAG, "Upload of " + ocFile.getStoragePath() + " to " + ocFile.getRemotePath() + - ": " + result.getLogMessage(), result.getException()); - } - - } else { - Log_OC.e(TAG, "Upload of " + ocFile.getStoragePath() + " to " + ocFile.getRemotePath() + - ": " + result.getLogMessage()); - } - } - } - - switch (localBehaviour) { - case FileUploader.LOCAL_BEHAVIOUR_FORGET: - String temporalPath = FileStorageUtils.getTemporalPath(account.name) + ocFile.getRemotePath(); - if (originalStoragePath.equals(temporalPath)) { - // delete local file is was pre-copied in temporary folder (see .ui.helpers.UriUploader) - temporalFile = new File(temporalPath); - temporalFile.delete(); - } - ocFile.setStoragePath(""); - saveUploadedFile(client); - break; - - case FileUploader.LOCAL_BEHAVIOUR_DELETE: - Log_OC.d(TAG, "Delete source file"); - - originalFile.delete(); - getStorageManager().deleteFileInMediaScan(originalFile.getAbsolutePath()); - saveUploadedFile(client); - break; - - case FileUploader.LOCAL_BEHAVIOUR_COPY: - if (temporalFile != null) { - try { - move(temporalFile, expectedFile); - } catch (IOException e) { - e.printStackTrace(); - } - } - ocFile.setStoragePath(expectedFile.getAbsolutePath()); - saveUploadedFile(client); - FileDataStorageManager.triggerMediaScan(expectedFile.getAbsolutePath()); - break; - - case FileUploader.LOCAL_BEHAVIOUR_MOVE: - - String expectedPath = FileStorageUtils.getDefaultSavePathFor(account.name, ocFile); - expectedFile = new File(expectedPath); - - try { - move(originalFile, expectedFile); - } catch (IOException e) { - e.printStackTrace(); - } - getStorageManager().deleteFileInMediaScan(originalFile.getAbsolutePath()); - ocFile.setStoragePath(expectedFile.getAbsolutePath()); - saveUploadedFile(client); - FileDataStorageManager.triggerMediaScan(expectedFile.getAbsolutePath()); - break; - } - - return result; - } - - /** - * Checks the existence of the folder where the current file will be uploaded both - * in the remote server and in the local database. - *

- * If the upload is set to enforce the creation of the folder, the method tries to - * create it both remote and locally. - * - * @param pathToGrant Full remote path whose existence will be granted. - * @return An {@link OCFile} instance corresponding to the folder where the file - * will be uploaded. - */ - private RemoteOperationResult grantFolderExistence(String pathToGrant, OwnCloudClient client) { - RemoteOperation operation = new ExistenceCheckRemoteOperation(pathToGrant, context, false); - RemoteOperationResult result = operation.execute(client); - if (!result.isSuccess() && result.getCode() == ResultCode.FILE_NOT_FOUND && mRemoteFolderToBeCreated) { - SyncOperation syncOp = new CreateFolderOperation(pathToGrant, true); - result = syncOp.execute(client, getStorageManager()); - } - if (result.isSuccess()) { - OCFile parentDir = getStorageManager().getFileByPath(pathToGrant); - if (parentDir == null) { - parentDir = createLocalFolder(pathToGrant); - } - if (parentDir != null) { - result = new RemoteOperationResult(ResultCode.OK); - } else { - result = new RemoteOperationResult(ResultCode.UNKNOWN_ERROR); - } - } - return result; - } - - private OCFile createLocalFolder(String remotePath) { - String parentPath = new File(remotePath).getParent(); - parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? - parentPath : parentPath + OCFile.PATH_SEPARATOR; - OCFile parent = getStorageManager().getFileByPath(parentPath); - if (parent == null) { - parent = createLocalFolder(parentPath); - } - if (parent != null) { - OCFile createdFolder = new OCFile(remotePath); - createdFolder.setMimetype(MimeType.DIRECTORY); - createdFolder.setParentId(parent.getFileId()); - getStorageManager().saveFile(createdFolder); - return createdFolder; - } - return null; - } - - /** - * Checks if remotePath does not exist in the server and returns it, or adds - * a suffix to it in order to avoid the server file is overwritten. - * - * @param wc - * @param remotePath - * @return - */ - private String getAvailableRemotePath(OwnCloudClient wc, String remotePath) { - boolean check = existsFile(wc, remotePath); - if (!check) { - return remotePath; - } - - int pos = remotePath.lastIndexOf('.'); - String suffix = ""; - String extension = ""; - if (pos >= 0) { - extension = remotePath.substring(pos + 1); - remotePath = remotePath.substring(0, pos); - } - int count = 2; - do { - suffix = " (" + count + ")"; - if (pos >= 0) { - check = existsFile(wc, remotePath + suffix + "." + extension); - } else { - check = existsFile(wc, remotePath + suffix); - } - count++; - } while (check); - - if (pos >= 0) { - return remotePath + suffix + "." + extension; - } else { - return remotePath + suffix; - } - } - - private boolean existsFile(OwnCloudClient client, String remotePath) { - ExistenceCheckRemoteOperation existsOperation = - new ExistenceCheckRemoteOperation(remotePath, context, false); - RemoteOperationResult result = existsOperation.execute(client); - return result.isSuccess(); - } - - /** - * Allows to cancel the actual upload operation. If actual upload operating - * is in progress it is cancelled, if upload preparation is being performed - * upload will not take place. - */ - public void cancel() { - if (mUploadOperation == null) { - if (mUploadStarted.get()) { - Log_OC.d(TAG, "Cancelling upload during upload preparations."); - mCancellationRequested.set(true); - } else { - Log_OC.e(TAG, "No upload in progress. This should not happen."); - } - } else { - Log_OC.d(TAG, "Cancelling upload during actual upload operation."); - mUploadOperation.cancel(); - } - } - - /** - * As soon as this method return true, upload can be cancel via cancel(). - */ - public boolean isUploadInProgress() { - return mUploadStarted.get(); - - } - -// /** -// * TODO rewrite with homogeneous fail handling, remove dependency on {@link RemoteOperationResult}, -// * TODO use Exceptions instead -// * -// * @param sourceFile Source file to copy. -// * @param targetFile Target location to copy the file. -// * @return {@link RemoteOperationResult} -// * @throws IOException -// */ -// private RemoteOperationResult copy(File sourceFile, File targetFile) throws IOException { -// Log_OC.d(TAG, "Copying local file"); -// -// RemoteOperationResult result = null; -// -// if (FileStorageUtils.getUsableSpace(account.name) < sourceFile.length()) { -// result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_FULL); -// return result; // error condition when the file should be copied -// -// } else { -// Log_OC.d(TAG, "Creating temporal folder"); -// File temporalParent = targetFile.getParentFile(); -// temporalParent.mkdirs(); -// if (!temporalParent.isDirectory()) { -// throw new IOException( -// "Unexpected error: parent directory could not be created"); -// } -// Log_OC.d(TAG, "Creating temporal file"); -// targetFile.createNewFile(); -// if (!targetFile.isFile()) { -// throw new IOException( -// "Unexpected error: target file could not be created"); -// } -// -// Log_OC.d(TAG, "Copying file contents"); -// InputStream in = null; -// OutputStream out = null; -// -// try { -// if (!mOriginalStoragePath.equals(targetFile.getAbsolutePath())) { -// // In case document provider schema as 'content://' -// if (mOriginalStoragePath.startsWith(UriUtils.URI_CONTENT_SCHEME)) { -// Uri uri = Uri.parse(mOriginalStoragePath); -// in = context.getContentResolver().openInputStream(uri); -// } else { -// in = new FileInputStream(sourceFile); -// } -// out = new FileOutputStream(targetFile); -// int nRead; -// byte[] buf = new byte[4096]; -// while (!mCancellationRequested.get() && -// (nRead = in.read(buf)) > -1) { -// out.write(buf, 0, nRead); -// } -// out.flush(); -// -// } // else: weird but possible situation, nothing to copy -// -// if (mCancellationRequested.get()) { -// result = new RemoteOperationResult(new OperationCancelledException()); -// return result; -// } -// -// } catch (Exception e) { -// result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_COPIED); -// return result; -// -// } finally { -// try { -// if (in != null) { -// in.close(); -// } -// } catch (Exception e) { -// Log_OC.d(TAG, "Weird exception while closing input stream for " + -// mOriginalStoragePath + " (ignoring)", e); -// } -// try { -// if (out != null) { -// out.close(); -// } -// } catch (Exception e) { -// Log_OC.d(TAG, "Weird exception while closing output stream for " + -// targetFile.getAbsolutePath() + " (ignoring)", e); -// } -// } -// } -// return result; -// } - - - /** - * TODO rewrite with homogeneous fail handling, remove dependency on {@link RemoteOperationResult}, - * TODO use Exceptions instead - *

- * TODO refactor both this and 'copy' in a single method - * - * @param sourceFile Source file to move. - * @param targetFile Target location to move the file. - * @return {@link RemoteOperationResult} - * @throws IOException - */ - private void move(File sourceFile, File targetFile) throws IOException { - - if (!targetFile.equals(sourceFile)) { - File expectedFolder = targetFile.getParentFile(); - expectedFolder.mkdirs(); - - if (expectedFolder.isDirectory()) { - if (!sourceFile.renameTo(targetFile)) { - // try to copy and then delete - targetFile.createNewFile(); - FileChannel inChannel = new FileInputStream(sourceFile).getChannel(); - FileChannel outChannel = new FileOutputStream(targetFile).getChannel(); - try { - inChannel.transferTo(0, inChannel.size(), outChannel); - sourceFile.delete(); - } catch (Exception e) { - ocFile.setStoragePath(""); // forget the local file - // by now, treat this as a success; the file was uploaded - // the best option could be show a warning message - } finally { - if (inChannel != null) { - inChannel.close(); - } - if (outChannel != null) { - outChannel.close(); - } - } - } - - } else { - ocFile.setStoragePath(""); - } - } - } - - /** - * Saves a OC File after a successful upload. - *

- * A PROPFIND is necessary to keep the props in the local database - * synchronized with the server, specially the modification time and Etag - * (where available) - *

- */ - private void saveUploadedFile(OwnCloudClient client) { - OCFile file = ocFile; - if (file.fileExists()) { - file = getStorageManager().getFileById(file.getFileId()); - } - long syncDate = System.currentTimeMillis(); - file.setLastSyncDateForData(syncDate); - - // new PROPFIND to keep data consistent with server - // in theory, should return the same we already have - // TODO from the appropriate OC server version, get data from last PUT response headers, instead - // TODO of a new PROPFIND; the latter may fail, specially for chunked uploads - ReadRemoteFileOperation operation = new ReadRemoteFileOperation(getRemotePath()); - RemoteOperationResult result = operation.execute(client); - if (result.isSuccess()) { - updateOCFile(file, (RemoteFile) result.getData().get(0)); - file.setLastSyncDateForProperties(syncDate); - } else { - Log_OC.e(TAG, "Error reading properties of file after successful upload; this is gonna hurt..."); - } - - file.setEncrypted(true); - file.setStoragePath(""); - file.setParentId(parentFile.getFileId()); - getStorageManager().saveFile(file); - getStorageManager().saveConflict(file, null); - - FileDataStorageManager.triggerMediaScan(file.getStoragePath()); - } - - private void updateOCFile(OCFile file, RemoteFile remoteFile) { - file.setCreationTimestamp(remoteFile.getCreationTimestamp()); - file.setFileLength(remoteFile.getLength()); -// file.setMimetype(file.getMimetype()); - file.setModificationTimestamp(remoteFile.getModifiedTimestamp()); - file.setModificationTimestampAtLastSyncForData(remoteFile.getModifiedTimestamp()); - file.setEtag(remoteFile.getEtag()); - file.setRemoteId(remoteFile.getRemoteId()); - } - - public interface OnRenameListener { - - void onRenameUpload(); - } - -} diff --git a/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java index b2db600025..bcf5185b00 100644 --- a/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -52,7 +52,6 @@ import android.support.v4.view.MenuItemCompat; import android.support.v7.app.AlertDialog; import android.support.v7.widget.SearchView; import android.text.TextUtils; -import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; diff --git a/src/main/java/com/owncloud/android/ui/dialog/SetupEncryptionDialogFragment.java b/src/main/java/com/owncloud/android/ui/dialog/SetupEncryptionDialogFragment.java index c029dafff9..461e6ffd57 100644 --- a/src/main/java/com/owncloud/android/ui/dialog/SetupEncryptionDialogFragment.java +++ b/src/main/java/com/owncloud/android/ui/dialog/SetupEncryptionDialogFragment.java @@ -289,7 +289,7 @@ public class SetupEncryptionDialogFragment extends DialogFragment { publicKey = (String) result.getData().get(0); } else { - throw new Exception("Public key not stored!"); + throw new RuntimeException("Public key not stored!"); } keyWords = EncryptionUtils.getRandomWords(12, getContext()); diff --git a/src/test/java/com/owncloud/android/utils/EncryptionTest.java b/src/test/java/com/owncloud/android/utils/EncryptionTest.java deleted file mode 100644 index eba2f90697..0000000000 --- a/src/test/java/com/owncloud/android/utils/EncryptionTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Nextcloud Android client application - * - * @author Tobias Kaminsky - * Copyright (C) 2017 Tobias Kaminsky - * Copyright (C) 2017 Nextcloud GmbH. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package com.owncloud.android.utils; - -import android.os.Build; -import android.support.annotation.RequiresApi; - -import com.google.gson.reflect.TypeToken; -import com.owncloud.android.datamodel.DecryptedFolderMetadata; - -import org.junit.Test; - -import java.util.HashMap; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -@RequiresApi(api = Build.VERSION_CODES.KITKAT) -public class EncryptionTest { - private String encryptedString = "{\"metadata\":{\"encrypted\":\"np1sIwoAFCb/vRqV/jWOIe1UtyVO02EJhvPoh3VwcZuiSbDjwQO5QHUWtKXpHLyX6wfbkRX6nr8mSG0+HhLRud1t126UMxQK5BNINu99WlzPMa5PaKhTXlpuRUf3tR6PTQ\\u003d\\u003d\",\"initializationVector\":" + - "\"kahzfT4u86Knc+e3\",\"sharing\":{\"recipient\":{\"blah@schiessle.org\":\"PUBLIC KEY\"," + - "\"bjoern@schiessle.org\":\"PUBLIC KEY\"},\"signature\":\"HMACOFRECIPIENTANDNEWESTMETADATAKEY\"}," + - "\"version\":1},\"files\":{\"ia7OEEEyXMoRa1QWQk8r\":{\"encrypted\":\"yl52TIccvo62LezCaFjQFJs7a1Q281pOuj59oNXMX7ti+7+h1SjK1AAk1HuwT+CI7BT64+R0ZLgyR/vBPjWvAQuxi9JWgsCjFMX91Mv2m2zI/bNQCarczOfnmf4FZ3Nv6yPLSjShmfQzemQ99Z3g7UHyrZ6pKT18m17IueJHF3V5kOhd9vcH\",\"metadataKey\":0," + - "\"initializationVector\":\"+mHu52HyZq+pAAIN\"}," + - "\"n9WXAIXO2wRY4R8nXwmo\":{\"encrypted\":\"Z9YTAgY/0YqKQlDwiqENcZRRupjgmJ1f0bTy0hOHP2/mHxFtoHCftT4STvt21OJMx8wF6V3cquQIGJ976WxkhA4SQxaQNpznhm1W9e8y+B5x8QnxSasYnOSFtZ/xVgQq6IZRjvYdPo7rvZk49hnqkwnUyvqtCj14aCE42qoxVZCd9M6XaZEBTA\\u003d\\u003d\",\"metadataKey\":0,\"initializationVector\":" + - "\"sOFd17hCKWIv0gyB\"}}}"; - - private String decryptedString = "{\"metadata\":{\"encrypted\":{\"metadataKeys\":{\"0\":" + - "\"s4k4LPDpxoO53TKwem3Lo1\",\"2\":\"…\",\"3\":\"NEWESTMETADATAKEY\"}},\"initializationVector\":" + - "\"kahzfT4u86Knc+e3\",\"sharing\":{\"recipient\":{\"blah@schiessle.org\":\"PUBLIC KEY\"," + - "\"bjoern@schiessle.org\":\"PUBLIC KEY\"},\"signature\":\"HMACOFRECIPIENTANDNEWESTMETADATAKEY\"}," + - "\"version\":1},\"files\":{\"ia7OEEEyXMoRa1QWQk8r\":{\"encrypted\":{\"key\":" + - "\"jtboLmgGR1OQf2uneqCVHpklQLlIwWL5TXAQ0keK\",\"filename\":\"test.txt\",\"authenticationTag\":" + - "\"HMAC of file\",\"version\":1},\"metadataKey\":0,\"initializationVector\":\"+mHu52HyZq+pAAIN\"}," + - "\"n9WXAIXO2wRY4R8nXwmo\":{\"encrypted\":{\"key\":\"s4k4LPDpxoO53TKwem3Lo1yJnbNUYH2KLrSFT8Ea\"," + - "\"filename\":\"test2.txt\",\"authenticationTag\":\"HMAC of file\",\"version\":1}," + - "\"metadataKey\":0,\"initializationVector\":\"sOFd17hCKWIv0gyB\"}}}"; - - private String privateKey = "TUlJRXZRSUJBREFOQmdrcWhraUc5dzBCQVFFRkFBU0NCS2N3Z2dTakFnRUFBb0lCQVFEV0FKMDNuNlBLVDNJWlZTT1paSzgyd3dqRTVWSW4vclZ5L0VLbmsyMVgzQ1dPbkdsb0ZrUXdiSWFsYjlkVWNRcmQzM250NVFoMmhJeXM5TkdsMjdMUmhreU1qemYzaFdzbnljSVhZQURVSExweGJZbWpJRzRjbWlNQnI4ckhjVFEvM0dUTlBKWG00ZzUwQlZEOXZlRThoMkQrTXdIQXlTSkxZcG5FaDBKWExES0pvVnpQYldxdVZVdHZNMmdmWVFHNFgwbS9kamR5VzJ4ZGN2UkpZeUtpWDZ3UmY3U3ViaWJkR1V1MHgxckhRdGhnM1dtaXdLd09NR2pQQ3oxRDAwMC9vWjZnckRHcW03TG5XMVZaN0VNTWtWWjVjVlc4NlpGQ2lrcXNtcDd1MVg1YjdCTzBiaThyV2Z0Zm8zZnJaOUptdmkvZHpmeXo2RFRFOWIrZU9CNzlBZ01CQUFFQ2dnRUJBSURYYzlCR1k5VnRDWFBwQjNyVjNJdXExcis4bFQ4UklldHRweSsvR2dqWXVSL29XYW5hSmduRmZUZGpZNUFxVXZHTUY1dTcxZUdOSWlrTGFLRmo2WUF1VEM0Z0dBRUZLYU9WM0M0NGxhY2UrTDFMeHA4WTZsSjhGbkZ3aGpTWG1tNk1ZWUFUWnVqUDF3WFJJWmJ6V0FVYU9MSXl3VzV4YWgxYTZ0c2cyRGNrZ2h3YVoxMURiRTVkNEpNNXl0Q1J6YmZzWTA3cElrUmU4WlFLcm1sMXU0THlsWXVHVHBDZGMwSnNXdUx3d1NWbm8vK056RURiVVNKZThIRmpnM1k3L2JkajgzNE9INzBtQWdBVUdEQTJqQ1BqY1hzNHJnN25udkhuQm5WcVFaemFvVWhHYzFOak9pZzMwNitUV25OL1JUNWc0TThucDNuMXZETWF2dVBiM0lFQ2dZRUE2NVpQV243UlYxZVVVS20zcVRUN1BSa3NuLzZDVWdFaFQ1WDloc0c3cXJXMUVlalhuODE2S1A0R3VsaDc1S0dhQ3hUVmdGZDhHdHF1QVU3MGdaKzB5MHVGd2hTdGtWN1A0K2xlUXlYSmxtNDNWNU9zT3Jxb25ocTZyOCthZ3lGbnNuOEhGd3lVcG1VM0FqR2tXVUNzYWFNdWM4SEt0ajU4RkdGRlh6K3ZlcDBDZ1lFQTZJdUZVZmljLytpUXpsVjczTDdWSS9kRjJNcFRPeHVKb1c4MmM1OE1tdEhGMFFQSktlYU5YVGJuYzluUXZ0aFBWM3c1eEZWc3FkN3pKOEM4ZkJ5S21Xc2ZLOU1abGQvY3RZTk9EMTNLWlM2WTNvWXpGVU5ZRzFPSEhpamNZT3RSWUsvY3k0cS9SRnExQ0pZVCtPaEVTOXlmeGFqZlZXdzFPdGxNZGNuNlYrRUNnWUFwNlN5bTBjYldQZnRodWorMU4zcTJyT0xXZDhXaFp4Z1ErNE1GMVROWXRFakpMZDRtVEx5OXpDdFFQV3VWQ2ZiSW4rVTNsdGk2UWtzUWFvWnZCUVY1NFM2amoyQXRhMnVhaFNyQzBWY2lqdXNEaG43dVY4U2xrK1hBWHpPQ3ZvK2ZIcUFaUnFDdlZYUkt6S0FMVE1rZlpldGVwb3cwamJzdk9QckpiaC8rdFFLQmdIQUFpd1R4RmtVWGNXOC9zdm1lSERCSGI2ZTd3eHlyNWIwUVFJeXRwVGVJSTV2SkZBR1BYclR2dGNpUnR6M0VGMnJPbFZBZnlNZUViMTdOTUxzaVVBc1draHZjZiswMHRpdmlneDFaa2hycnQ0c3QzYnEzQmQrYmVtK25SSVdWc1VzOVNMM3NKTFU2Yndra3A1ZngzcnNmRndEdmxpbWhoWDNEblZUNkpBNWhBb0dBZUtSZGRBVFAxZmVDL1pIZWE0VWh1MEVIencrY2xraDBrdjFDQkNHNnhjM002Y245SzFUNlIwMHRZYlFjS1JvZHJ1ZnBZNUNOL3V2Zyt0VWRucTUxRFhwTU5tbDVMdGpRYnV3MktuZ1F1ZG9NQ1NFMHMzT0dnaGJqMzZtbEVsRERjUGxLaE0rb1hyaVRYdXUvWmljclZqcGxTcWxuSlN2aDh6STJGNFBLaDlnPQ=="; - - private String publicKey = "-----BEGIN CERTIFICATE-----\n" + - "MIIDpzCCAo+gAwIBAgIBADANBgkqhkiG9w0BAQUFADBuMRowGAYDVQQDDBF3d3cu\n" + - "bmV4dGNsb3VkLmNvbTESMBAGA1UECgwJTmV4dGNsb3VkMRIwEAYDVQQHDAlTdHV0\n" + - "dGdhcnQxGzAZBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzELMAkGA1UEBhMCREUw\n" + - "HhcNMTcwOTA0MTEwNTQyWhcNMzcwODMwMTEwNTQyWjBuMRowGAYDVQQDDBF3d3cu\n" + - "bmV4dGNsb3VkLmNvbTESMBAGA1UECgwJTmV4dGNsb3VkMRIwEAYDVQQHDAlTdHV0\n" + - "dGdhcnQxGzAZBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzELMAkGA1UEBhMCREUw\n" + - "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWAJ03n6PKT3IZVSOZZK82\n" + - "wwjE5VIn/rVy/EKnk21X3CWOnGloFkQwbIalb9dUcQrd33nt5Qh2hIys9NGl27LR\n" + - "hkyMjzf3hWsnycIXYADUHLpxbYmjIG4cmiMBr8rHcTQ/3GTNPJXm4g50BVD9veE8\n" + - "h2D+MwHAySJLYpnEh0JXLDKJoVzPbWquVUtvM2gfYQG4X0m/djdyW2xdcvRJYyKi\n" + - "X6wRf7SubibdGUu0x1rHQthg3WmiwKwOMGjPCz1D000/oZ6grDGqm7LnW1VZ7EMM\n" + - "kVZ5cVW86ZFCikqsmp7u1X5b7BO0bi8rWftfo3frZ9Jmvi/dzfyz6DTE9b+eOB79\n" + - "AgMBAAGjUDBOMB0GA1UdDgQWBBS3zNF86LEZFT/KDdscr4ZJEisXqDAfBgNVHSME\n" + - "GDAWgBS3zNF86LEZFT/KDdscr4ZJEisXqDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3\n" + - "DQEBBQUAA4IBAQCPMu5AKNlh0gTr/k9Vc7RJ01uF07D+lTPGIErfW7+qXO21kXyw\n" + - "+w8sxw+e1B/gah/bxotfO7ZuOhs49d8QRUzPy/miBFaZXfjfiqs7UXSDQ6oUbX3a\n" + - "X9eTFMHDcsSUbyqhwn2cghmPJEhE10mtH2DJNPqDYvdpekJ6sEUVaqx63CD3nxcl\n" + - "7fXh0IfmvDQOrSBszRqPY8pvnZJIEwqaENPk9Vgbzs8oXVstKl6wCqM0B36tmhBl\n" + - "f6Dz/EhriF3Rq9w5RrWZOpS6XAWwRpyHPN+lKPa321dF6EEsnvhX8G3UbLbr0uEg\n" + - "dR8lPhuKejU/Ds0ARwQGmFXFzidFNZL5ymos\n" + - "-----END CERTIFICATE-----"; - - @Test - public void deserializeJSON() { - String file = "ia7OEEEyXMoRa1QWQk8r"; - DecryptedFolderMetadata metadata = EncryptionUtils.deserializeJSON(decryptedString, - new TypeToken() {}); - - assertEquals("jtboLmgGR1OQf2uneqCVHpklQLlIwWL5TXAQ0keK", metadata.files.get(file).encrypted.key); - assertEquals("+mHu52HyZq+pAAIN", metadata.files.get(file).initializationVector); - } - - @Test - public void serializeJSON() { - try { - HashMap metadataKeys = new HashMap<>(); - metadataKeys.put(0, EncryptionUtils.encryptStringAsymmetric("s4k4LPDpxoO53TKwem3Lo1", publicKey)); - metadataKeys.put(1, EncryptionUtils.encryptStringAsymmetric("Q3ZobVJHbTlkK1VHT0g3ME", publicKey)); - metadataKeys.put(2, EncryptionUtils.encryptStringAsymmetric("lkK1VHT0g3ME3TKwem3Lo1", publicKey)); - DecryptedFolderMetadata.Encrypted encrypted = new DecryptedFolderMetadata.Encrypted(); - encrypted.metadataKeys = metadataKeys; - - DecryptedFolderMetadata.Metadata metadata1 = new DecryptedFolderMetadata.Metadata(); - metadata1.metadataKeys = metadataKeys; - metadata1.version = 1; - - DecryptedFolderMetadata.Sharing sharing = new DecryptedFolderMetadata.Sharing(); - sharing.signature = "HMACOFRECIPIENTANDNEWESTMETADATAKEY"; - HashMap recipient = new HashMap<>(); - recipient.put("blah@schiessle.org", "PUBLIC KEY"); - recipient.put("bjoern@schiessle.org", "PUBLIC KEY"); - sharing.recipient = recipient; - metadata1.sharing = sharing; - - HashMap files = new HashMap<>(); - - DecryptedFolderMetadata.Data data1 = new DecryptedFolderMetadata.Data(); - data1.key = "jtboLmgGR1OQf2uneqCVHpklQLlIwWL5TXAQ0keK"; - data1.filename = "test.txt"; - data1.version = 1; - - DecryptedFolderMetadata.DecryptedFile file1 = new DecryptedFolderMetadata.DecryptedFile(); - file1.initializationVector = "+mHu52HyZq+pAAIN"; - file1.encrypted = data1; - file1.metadataKey = 0; - file1.authenticationTag = "HMAC of file"; - - files.put("ia7OEEEyXMoRa1QWQk8r", file1); - - DecryptedFolderMetadata.Data data2 = new DecryptedFolderMetadata.Data(); - data2.key = "s4k4LPDpxoO53TKwem3Lo1yJnbNUYH2KLrSFT8Ea"; - data2.filename = "test2.txt"; - data2.version = 1; - - DecryptedFolderMetadata.DecryptedFile file2 = new DecryptedFolderMetadata.DecryptedFile(); - file2.initializationVector = "sOFd17hCKWIv0gyB"; - file2.encrypted = data2; - file2.metadataKey = 0; - file2.authenticationTag = "HMAC of file"; - - files.put("n9WXAIXO2wRY4R8nXwmo", file2); - - DecryptedFolderMetadata metadata = new DecryptedFolderMetadata(metadata1, files); - - // serialize - assertEquals(decryptedString, EncryptionUtils.serializeJSON(metadata)); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } - } -} \ No newline at end of file