Contracts refactored

master
Inga 🏳‍🌈 7 years ago
parent 9f26b7241a
commit e942fdbd0c
  1. 11
      Source/Contracts/ContentTransformations/IContentEncryptor.cs
  2. 2
      Source/Contracts/ContentTransformations/IContentHasher.cs
  3. 11
      Source/Contracts/ContentTransformations/IContentTransformer.cs
  4. 13
      Source/Contracts/ReportStorage/IFileInfo.cs
  5. 21
      Source/Contracts/ReportStorage/IReportInfo.cs
  6. 18
      Source/Contracts/ReportStorage/IReportStorage.cs
  7. 13
      Source/Contracts/TargetBinaryStorage/IBlobInfo.cs
  8. 13
      Source/Contracts/TargetBinaryStorage/ITargetBinaryStorage.cs
  9. 13
      Source/Contracts/TargetMetadataStorage/ITargetDirectory.cs
  10. 10
      Source/Contracts/TargetMetadataStorage/ITargetFile.cs
  11. 15
      Source/Contracts/TargetMetadataStorage/ITargetFileVersion.cs
  12. 9
      Source/Contracts/TargetMetadataStorage/ITargetMetadataStorage.cs
  13. 13
      Source/Contracts/TargetMetadataStorage/ITargetMetadataStorageForRecovery.cs
  14. 13
      Source/Contracts/TargetStorage/ITargetDirectory.cs
  15. 18
      Source/Contracts/TargetStorage/ITargetFile.cs
  16. 9
      Source/Contracts/TargetStorage/ITargetStorage.cs
  17. 10
      Source/Contracts/TargetStorage/ITargetStorageForRecovery.cs
  18. 25
      Source/Encryptor.ClearText/ClearTextContentEncryptor.cs
  19. 3
      Source/Hasher.SHA1/SHA1ContentHasher.cs
  20. 8
      Tests/Encryptor.ClearText/EncryptorAndHasherTests.cs
  21. 24
      Tests/Hasher.SHA1/HasherTests.cs

@ -1,11 +0,0 @@
namespace EternalArrowBackup.Contracts.ContentTransformations
{
using System.Threading.Tasks;
public interface IContentEncryptor
{
Task<byte[]> Encrypt(byte[] originalData);
Task<IDecryptionResult> Decrypt(byte[] encryptedData);
}
}

@ -5,6 +5,6 @@
public interface IContentHasher
{
Task<string> ComputeHash(byte[] content);
Task<string> ComputeHash(Stream content);
}
}

@ -0,0 +1,11 @@
namespace EternalArrowBackup.Contracts.ContentTransformations
{
using System.Threading.Tasks;
public interface IContentTransformer
{
Task<byte[]> TransformData(byte[] originalData);
Task<IDecryptionResult> GetOriginalData(byte[] transformedData);
}
}

@ -0,0 +1,13 @@
namespace EternalArrowBackup.Contracts.ReportStorage
{
public interface IFileInfo
{
string DirectoryPath { get; }
string Filename { get; }
string Hash { get; }
long Size { get; }
}
}

@ -0,0 +1,21 @@
namespace EternalArrowBackup.Contracts.ReportStorage
{
using System;
public interface IReportInfo
{
string ReportId { get; }
DateTime DateTime { get; }
bool IsCompleted { get; }
bool IsEmpty { get; }
bool HasErrors { get; }
IObservable<string> GetAllErrors();
IObservable<IFileInfo> GetAllFiles();
}
}

@ -0,0 +1,18 @@
namespace EternalArrowBackup.Contracts.ReportStorage
{
using System;
using System.Threading.Tasks;
public interface IReportStorage
{
Task InitReport(string reportId);
Task CompleteReport(string reportId, bool isEmpty, bool hasErrors);
Task AddError(string reportId, string errorMessage);
Task AddFileInfo(string reportId, string directoryPath, string fileName, string hash, long size);
IObservable<IReportInfo> GetAllReports(bool includeEmpty);
}
}

@ -0,0 +1,13 @@
namespace EternalArrowBackup.Contracts.TargetBinaryStorage
{
using System;
public interface IBlobInfo
{
DateTime UploadDate { get; }
long OriginalSize { get; }
string[] BlockKeys { get; }
}
}

@ -0,0 +1,13 @@
namespace EternalArrowBackup.Contracts.TargetBinaryStorage
{
using System.Threading.Tasks;
public interface ITargetBinaryStorage
{
Task WriteBlock(byte[] block, string blobId, int partNumber, string blockKey);
Task WriteBlob(string blobId, long originalSize, string[] blockKeys);
Task<IBlobInfo> GetBlobIfExists(string blobId);
}
}

@ -0,0 +1,13 @@
namespace EternalArrowBackup.Contracts.TargetMetadataStorage
{
using System;
using System.Threading;
using System.Threading.Tasks;
public interface ITargetDirectory
{
Task UploadFile(string filename, string originalHash, long originalSize);
IObservable<ITargetFileVersion> GetAllLatestFileVersions(CancellationToken ct);
}
}

@ -0,0 +1,10 @@
namespace EternalArrowBackup.Contracts.TargetMetadataStorage
{
using System;
using System.Threading;
public interface ITargetFile
{
IObservable<ITargetFileVersion> GetAllVersions(CancellationToken ct);
}
}

@ -0,0 +1,15 @@
namespace EternalArrowBackup.Contracts.TargetMetadataStorage
{
using System;
public interface ITargetFileVersion
{
string Filename { get; }
string Hash { get; }
DateTime UploadDate { get; }
long Size { get; }
}
}

@ -0,0 +1,9 @@
namespace EternalArrowBackup.Contracts.TargetMetadataStorage
{
using System.Threading.Tasks;
public interface ITargetMetadataStorage
{
Task<ITargetDirectory> GetDirectory(string normalizedRelativeDirectoryPath);
}
}

@ -0,0 +1,13 @@
namespace EternalArrowBackup.Contracts.TargetMetadataStorage
{
using System;
using System.Threading;
using System.Threading.Tasks;
public interface ITargetMetadataStorageForRecovery
{
IObservable<ITargetDirectory> GetAllDirectories(CancellationToken ct);
Task<ITargetFile> GetFile(string normalizedRelativeDirectoryPath, string filename);
}
}

@ -1,13 +0,0 @@
namespace EternalArrowBackup.Contracts.TargetStorage
{
using System;
using System.Threading;
using System.Threading.Tasks;
public interface ITargetDirectory
{
Task UploadFile(string filename, byte[] data, string originalHash, long originalSize);
IObservable<ITargetFile> GetAllFiles(CancellationToken ct);
}
}

@ -1,18 +0,0 @@
namespace EternalArrowBackup.Contracts.TargetStorage
{
using System;
using System.Threading.Tasks;
public interface ITargetFile
{
string Filename { get; }
string Hash { get; }
DateTime UploadDate { get; }
long Size { get; }
Task<byte[]> RetrieveContents();
}
}

@ -1,9 +0,0 @@
namespace EternalArrowBackup.Contracts.TargetStorage
{
using System.Threading.Tasks;
public interface ITargetStorage
{
Task<ITargetDirectory> GetDirectory(string normalizedRelativePath);
}
}

@ -1,10 +0,0 @@
namespace EternalArrowBackup.Contracts.TargetStorage
{
using System;
using System.Threading;
public interface ITargetStorageForRecovery
{
IObservable<ITargetDirectory> GetAllDirectories(CancellationToken ct);
}
}

@ -1,11 +1,12 @@
namespace EternalArrowBackup.Encryptor.ClearText
{
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Contracts.ContentTransformations;
public class ClearTextContentEncryptor : IContentEncryptor
public class ClearTextContentEncryptor : IContentTransformer
{
public ClearTextContentEncryptor(IContentHasher hasher)
{
@ -14,7 +15,7 @@
private IContentHasher Hasher { get; }
public async Task<IDecryptionResult> Decrypt(byte[] encryptedData)
public async Task<IDecryptionResult> GetOriginalData(byte[] encryptedData)
{
var hashLength = encryptedData[encryptedData.Length - 1];
@ -25,19 +26,27 @@
Buffer.BlockCopy(encryptedData, originalData.Length, hashBytes, 0, hashBytes.Length);
var expectedHash = Encoding.UTF8.GetString(hashBytes);
var actualHash = await this.Hasher.ComputeHash(originalData);
if (expectedHash != actualHash)
using (var stream = new MemoryStream(originalData))
{
return new FailedDecryptionResult();
var actualHash = await this.Hasher.ComputeHash(stream);
if (expectedHash != actualHash)
{
return new FailedDecryptionResult();
}
}
return new SuccessfulDecryptionResult(originalData);
}
public async Task<byte[]> Encrypt(byte[] originalData)
public async Task<byte[]> TransformData(byte[] originalData)
{
var hash = await this.Hasher.ComputeHash(originalData);
string hash;
using (var stream = new MemoryStream(originalData))
{
hash = await this.Hasher.ComputeHash(stream);
}
var hashBytes = Encoding.UTF8.GetBytes(hash);
if (hashBytes.Length >= 256)
{

@ -1,12 +1,13 @@
namespace EternalArrowBackup.Hasher.SHA1
{
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Contracts.ContentTransformations;
public class SHA1ContentHasher : IContentHasher
{
public Task<string> ComputeHash(byte[] content)
public Task<string> ComputeHash(Stream content)
{
return Task.Run(() =>
{

@ -16,19 +16,19 @@
var messageBytes = Encoding.ASCII.GetBytes(message);
var hasher = new SHA1ContentHasher();
var encryptor = new ClearTextContentEncryptor(hasher);
var encrypted = await encryptor.Encrypt(messageBytes);
var encrypted = await encryptor.TransformData(messageBytes);
var decryptionResult = await encryptor.Decrypt(encrypted);
var decryptionResult = await encryptor.GetOriginalData(encrypted);
Assert.True(decryptionResult.IsSuccessful);
Assert.Equal(messageBytes, decryptionResult.Data);
encrypted[0]++;
decryptionResult = await encryptor.Decrypt(encrypted);
decryptionResult = await encryptor.GetOriginalData(encrypted);
Assert.False(decryptionResult.IsSuccessful);
encrypted[0]--;
encrypted[encrypted.Length - 1]--;
decryptionResult = await encryptor.Decrypt(encrypted);
decryptionResult = await encryptor.GetOriginalData(encrypted);
Assert.False(decryptionResult.IsSuccessful);
}
}

@ -2,6 +2,7 @@
{
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Xunit;
@ -21,8 +22,11 @@
var expectedHashFormatted = expectedHash.Replace(" ", string.Empty).ToLowerInvariant();
var hasher = new SHA1ContentHasher();
var messageBytes = Encoding.ASCII.GetBytes(inputMessage);
var actualHash = await hasher.ComputeHash(messageBytes);
Assert.Equal(expectedHashFormatted, actualHash);
using (var stream = new MemoryStream(messageBytes))
{
var actualHash = await hasher.ComputeHash(stream);
Assert.Equal(expectedHashFormatted, actualHash);
}
}
// Single-threaded SHA1 performance on i5-6500 is around 500MB/s
@ -46,12 +50,16 @@
var expectedTimeHigh = 1 + length / (MegabytesPerSecondLowSpeed * 1000);
var hasher = new SHA1ContentHasher();
var stopwatch = new Stopwatch();
stopwatch.Start();
await hasher.ComputeHash(messageBytes);
stopwatch.Stop();
Assert.InRange(stopwatch.ElapsedMilliseconds, expectedTimeLow, expectedTimeHigh);
using (var stream = new MemoryStream(messageBytes))
{
await hasher.ComputeHash(stream);
stream.Seek(0, SeekOrigin.Begin);
var stopwatch = new Stopwatch();
stopwatch.Start();
await hasher.ComputeHash(stream);
stopwatch.Stop();
Assert.InRange(stopwatch.ElapsedMilliseconds, expectedTimeLow, expectedTimeHigh);
}
}
}
}

Loading…
Cancel
Save