Exemplo n.º 1
0
        public void TestAesStream()
        {
            var baseStream = new MemoryStream();
            var key = new byte[]
                { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
            var encryptStream = new AesStream(baseStream, key);
            var plaintext = Encoding.UTF8.GetBytes("Hello, world!");
            encryptStream.Write(plaintext, 0, plaintext.Length);

            baseStream.Seek(0, SeekOrigin.Begin);
            var decryptStream = new AesStream(baseStream, key);
            byte[] buffer = new byte[plaintext.Length];
            decryptStream.Read(buffer, 0, buffer.Length);

            Assert.AreEqual("Hello, world!", Encoding.UTF8.GetString(buffer));
        }
Exemplo n.º 2
0
        public void TestAesStream()
        {
            var baseStream = new MemoryStream();
            var key        = new byte[]
            { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
            var encryptStream = new AesStream(baseStream, key);
            var plaintext     = Encoding.UTF8.GetBytes("Hello, world!");

            encryptStream.Write(plaintext, 0, plaintext.Length);

            baseStream.Seek(0, SeekOrigin.Begin);
            var decryptStream = new AesStream(baseStream, key);

            byte[] buffer = new byte[plaintext.Length];
            decryptStream.Read(buffer, 0, buffer.Length);

            Assert.AreEqual("Hello, world!", Encoding.UTF8.GetString(buffer));
        }
Exemplo n.º 3
0
        public void AesStreamWrite()
        {
            var data = Encoding.ASCII.GetBytes("Hello");

            Assert.IsTrue(data.ToArray().SequenceEqual(new byte[] { 72, 101, 108, 108, 111 }));

            var password = SecurityHelper.ToSecureString("MyPassword");

            using (var baseStream = new MemoryStream())
                using (var aesStream = new AesStream(baseStream, password, SecurityHelper.GetSaltKeys(password).GetBytes(16)))
                {
                    aesStream.Write(data, 0, data.Length);
                    aesStream.Position = 0;

                    var cryptedData = new byte[baseStream.Length];
                    baseStream.Read(cryptedData, 0, cryptedData.Length);
                    Assert.IsTrue(cryptedData.ToArray().SequenceEqual(new byte[] { 238, 75, 117, 248, 55 }));
                }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Read a specified clipboard data, encrypt and save it into a file.
        /// </summary>
        /// <param name="clipboardReader">The <see cref="ClipboardReader"/> used to read the data.</param>
        /// <param name="identifier">The data identifier.</param>
        /// <param name="clipboardDataPath">The full path to the clipboard data folder.</param>
        private void WriteClipboardDataToFile(ClipboardReader clipboardReader, DataIdentifier identifier, string
                                              clipboardDataPath)
        {
            Requires.NotNull(clipboardReader, nameof(clipboardReader));
            Requires.NotNull(identifier, nameof(identifier));
            Requires.NotNullOrWhiteSpace(clipboardDataPath, nameof(clipboardDataPath));
            var dataFilePath = Path.Combine(clipboardDataPath, $"{identifier.Identifier}.dat");

            if (File.Exists(dataFilePath))
            {
                Logger.Instance.Fatal(new FileLoadException($"The file {dataFilePath} already exists."));
            }

            var dataPassword =
                SecurityHelper.ToSecureString(SecurityHelper.EncryptString(SecurityHelper.ToSecureString(
                                                                               identifier.Identifier.ToString(
                                                                                   ))));

            Requires.NotNull(dataPassword, nameof(dataPassword));
            clipboardReader.BeginRead(identifier.FormatName);
            Requires.IsTrue(clipboardReader.IsReadable);
            Requires.IsTrue(clipboardReader.CanReadNextBlock());
            using (var fileStream = File.OpenWrite(dataFilePath))
                using (var aesStream = new AesStream(fileStream, dataPassword,
                                                     SecurityHelper.GetSaltKeys(dataPassword).GetBytes(16)))
                {
                    aesStream.AutoDisposeBaseStream = false;
                    while (clipboardReader.CanReadNextBlock())
                    {
                        var buffer = clipboardReader.ReadNextBlock();
                        aesStream.Write(buffer, 0, buffer.Length);
                    }

                    aesStream.Position = 0;
                }

            clipboardReader.EndRead();
        }
Exemplo n.º 5
0
        /// <summary>
        /// Force to synchronize that data with the cloud.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        internal async Task SynchronizeAsync()
        {
            if (IsSynchronizing)
            {
                return;
            }

            Logger.Instance.Information("Synchronization with the cloud started.");
            IsSynchronizing = true;

            if (CurrentCloudStorageProvider == null)
            {
                Logger.Instance.Warning("The user is not logged to any cloud storage provider. The synchronization stopped.");
                IsSynchronizing = false;
                return;
            }

            if (!CoreHelper.IsUnitTesting() && !SystemInfoHelper.CheckForInternetConnection())
            {
                Logger.Instance.Warning("There is no internet connection. The synchronization stopped.");
                IsSynchronizing = false;
                return;
            }

            SynchronizationStarted?.Invoke(this, new EventArgs());

            try
            {
                if (!await CurrentCloudStorageProvider.TryAuthenticateAsync())
                {
                    Logger.Instance.Warning("The user is not authenticated correctly. Consider unlink the app and connect again. The synchronization stopped.");
                    IsSynchronizing = false;
                    SynchronizationEnded?.Invoke(this, new EventArgs());
                    return;
                }

                var userId = SecurityHelper.ToSecureString(await CurrentCloudStorageProvider.GetUserIdAsync());

                if (string.IsNullOrWhiteSpace(SecurityHelper.ToUnsecureString(userId)))
                {
                    Logger.Instance.Warning("The user's id from the cloud storage provider has not been found. The synchronization stopped.");
                    IsSynchronizing = false;
                    SynchronizationEnded?.Invoke(this, new EventArgs());
                    SynchronizationFailed?.Invoke(this, new EventArgs());
                    return;
                }

                Logger.Instance.Information("Freezing the data before synchronize.");
                var dataService = ServiceLocator.GetService <DataService>();
                var cloudDataEntryFromServer = new List <CloudDataEntry>();
                var cloudAppFolder           = await CurrentCloudStorageProvider.GetAppFolderAsync();

                var cloudDataEntryFilePath = Path.Combine(cloudAppFolder.FullPath, Consts.DataEntryFileName);
                var cloudDataPassword      = SecurityHelper.ToSecureString(SecurityHelper.EncryptString(userId, SecurityHelper.ToSecureString(await CurrentCloudStorageProvider.GetUserNameAsync())));
                var localFrozenDataEntries = DataHelper.FromByteArray <AsyncObservableCollection <DataEntry> >(DataHelper.ToByteArray(dataService.DataEntries));
                var localFrozenCache       = DataHelper.FromByteArray <List <DataEntryCache> >(DataHelper.ToByteArray(dataService.Cache));

                // Download data from server.
                if (cloudAppFolder.Files.Any(file => file.FullPath == cloudDataEntryFilePath))
                {
                    Logger.Instance.Information("Downloading the data entry file from the server.");
                    try
                    {
                        using (var memoryStream = new MemoryStream())
                        {
                            await CurrentCloudStorageProvider.DownloadFileAsync(cloudDataEntryFilePath, memoryStream);

                            memoryStream.Position = 0;
                            using (var aesStream = new AesStream(memoryStream, cloudDataPassword, SecurityHelper.GetSaltKeys(cloudDataPassword).GetBytes(16)))
                            {
                                var data = new byte[aesStream.Length];
                                aesStream.Read(data, 0, data.Length);
                                cloudDataEntryFromServer = JsonConvert.DeserializeObject <List <CloudDataEntry> >(Encoding.UTF8.GetString(data));
                            }
                        }
                    }
                    catch (Exception exception)
                    {
                        Logger.Instance.Warning($"Unable to download or read the data file entry from the cloud for the following reason : {exception.Message}");
                        IsSynchronizing = false;
                        SynchronizationEnded?.Invoke(this, new EventArgs());
                        SynchronizationFailed?.Invoke(this, new EventArgs());
                        return;
                    }
                }
                else
                {
                    Logger.Instance.Information("There is no data entry file on the server yet.");
                }

                // Synchronize locally the data. The result must corresponds to what we will have locally and on the server at the end of the synchronization process.
                var cloudDataEntryToServer = dataService.DifferenceLocalAndCloudDataEntries(cloudDataEntryFromServer);

                // Download the needed data from the server to the local machine.
                Logger.Instance.Information("Downloading the needed data from the server to the local machine.");
                var dataToDownload = cloudDataEntryFromServer.Cast <DataEntryBase>().Except(localFrozenDataEntries, (item1, item2) => item1.Identifier == item2.Identifier).ToList();
                var taskList       = new List <Task>();
                foreach (var cloudDataEntry in dataToDownload)
                {
                    if (dataToDownload.Any(data => localFrozenCache.Any(item => data.Identifier == item.Identifier && item.Status == DataEntryStatus.Deleted)))
                    {
                        continue;
                    }

                    foreach (var dataEntryDataIdentifier in cloudDataEntry.DataIdentifiers)
                    {
                        var task = DownloadDataFileAsync(dataService.ClipboardDataPath, cloudAppFolder, cloudDataPassword, dataEntryDataIdentifier);
                        taskList.Add(task);
                    }
                }
                await Task.WhenAll(taskList);

                // Delete the needed data from the server
                Logger.Instance.Information("Deleting the needed data from the server.");
                taskList = new List <Task>();
                foreach (var dataServiceDataEntry in localFrozenDataEntries.Where(item => !item.CanSynchronize))
                {
                    foreach (var dataEntryDataIdentifier in dataServiceDataEntry.DataIdentifiers)
                    {
                        var task = DeleteFileAsync(cloudAppFolder, dataEntryDataIdentifier);
                        taskList.Add(task);
                    }
                }
                await Task.WhenAll(taskList);

                taskList = new List <Task>();
                foreach (var cacheEntry in localFrozenCache.Where(item => item.Status == DataEntryStatus.Deleted))
                {
                    var dataEntry = cloudDataEntryFromServer.SingleOrDefault(item => item.Identifier == cacheEntry.Identifier);
                    if (dataEntry != null)
                    {
                        foreach (var dataEntryDataIdentifier in dataEntry.DataIdentifiers)
                        {
                            var task = DeleteFileAsync(cloudAppFolder, dataEntryDataIdentifier);
                            taskList.Add(task);
                        }
                    }
                }
                await Task.WhenAll(taskList);

                await dataService.MakeCacheSynchronized(cloudDataEntryToServer, true, localFrozenCache);

                localFrozenDataEntries = DataHelper.FromByteArray <AsyncObservableCollection <DataEntry> >(DataHelper.ToByteArray(dataService.DataEntries));
                localFrozenCache       = DataHelper.FromByteArray <List <DataEntryCache> >(DataHelper.ToByteArray(dataService.Cache));

                // Upload the needed data from the server to the local machine
                Logger.Instance.Information("Uploading the needed data from the server to the local machine.");
                var dataToUpload = localFrozenDataEntries.Cast <DataEntryBase>().Except(cloudDataEntryFromServer, (item1, item2) => item1.Identifier == item2.Identifier);
                taskList = new List <Task>();
                foreach (var dataEntry in dataToUpload)
                {
                    var localDataEntry = localFrozenDataEntries.Single(item => item.Identifier == dataEntry.Identifier);
                    if (!localDataEntry.CanSynchronize || localDataEntry.Thumbnail.Type == ThumbnailDataType.Files)
                    {
                        continue;
                    }

                    foreach (var dataEntryDataIdentifier in dataEntry.DataIdentifiers)
                    {
                        var task = UploadDataFileAsync(dataService.ClipboardDataPath, cloudAppFolder, cloudDataPassword, dataEntryDataIdentifier);
                        taskList.Add(task);
                    }
                }
                await Task.WhenAll(taskList);

                // Upload the new data to the server.
                Logger.Instance.Information("Uploading the data entry file to the server.");

                using (var memoryStream = new MemoryStream())
                    using (var aesStream = new AesStream(memoryStream, cloudDataPassword, SecurityHelper.GetSaltKeys(cloudDataPassword).GetBytes(16)))
                    {
                        var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(cloudDataEntryToServer));
                        aesStream.Write(data, 0, data.Length);
                        aesStream.Position = 0;
                        await CurrentCloudStorageProvider.UploadFileAsync(memoryStream, cloudDataEntryFilePath);
                    }

                await dataService.MakeCacheSynchronized(cloudDataEntryToServer, false, localFrozenCache);
            }
            catch (Exception exception)
            {
                Logger.Instance.Warning($"Unable to synchronize for the following reason : {exception.Message}. {exception.InnerException?.Message}");
                SynchronizationFailed?.Invoke(this, new EventArgs());
            }

            _synchronizeTimer.Stop();
            _synchronizeTimer.Start();

            IsSynchronizing = false;
            SynchronizationEnded?.Invoke(this, new EventArgs());
        }