public int StoreSnapshot( IReadOnlyCollection <Blob> blobs, Fuzzy scanFuzzy, DateTime creationTimeUtc, Func <string, Stream> openRead) { var newSnapshot = new Snapshot( _currentSnapshotId == null ? 0 : _currentSnapshotId.Value + 1, creationTimeUtc, WriteBlobs(blobs, scanFuzzy, openRead)); using var memoryStream = new MemoryStream( DataConvert.ObjectToBytes(newSnapshot)); var newSnapshotReference = new SnapshotReference( _salt, _iterations, WriteContent(AesGcmCrypto.GenerateNonce(), memoryStream)); _intRepository.StoreValue( newSnapshot.SnapshotId, DataConvert.ObjectToBytes(newSnapshotReference)); _currentSnapshotId = newSnapshot.SnapshotId; _probe.StoredSnapshot(newSnapshot.SnapshotId); return(newSnapshot.SnapshotId); }
public void RetrieveContent( IEnumerable <Uri> contentUris, Stream outputStream) { contentUris.EnsureNotNull(nameof(contentUris)); outputStream.EnsureNotNull(nameof(outputStream)); foreach (var contentUri in contentUris) { try { var decrypted = AesGcmCrypto.Decrypt( _uriRepository.RetrieveValue(contentUri), _key.Value); outputStream.Write(decrypted); } catch (CryptographicException e) { throw new ChunkyardException( $"Could not decrypt content: {contentUri}", e); } } }
public SnapshotStore( IRepository <Uri> uriRepository, IRepository <int> intRepository, FastCdc fastCdc, string hashAlgorithmName, IPrompt prompt, IProbe probe, int parallelizeChunkThreshold) { _uriRepository = uriRepository; _intRepository = intRepository; _fastCdc = fastCdc; _hashAlgorithmName = hashAlgorithmName; _probe = probe; _parallelizeChunkThreshold = parallelizeChunkThreshold; if (parallelizeChunkThreshold <= 0) { throw new ArgumentException( "Value must be larger than zero", nameof(parallelizeChunkThreshold)); } _currentSnapshotId = FetchCurrentSnapshotId(); if (_currentSnapshotId == null) { _salt = AesGcmCrypto.GenerateSalt(); _iterations = AesGcmCrypto.Iterations; } else { var snapshotReference = GetSnapshotReference( _currentSnapshotId.Value); _salt = snapshotReference.Salt; _iterations = snapshotReference.Iterations; } _key = new Lazy <byte[]>(() => { var password = _currentSnapshotId == null ? prompt.NewPassword() : prompt.ExistingPassword(); return(AesGcmCrypto.PasswordToKey(password, _salt, _iterations)); }); }
public static void Encrypt_And_Decrypt_Return_Input() { var expectedText = "Hello!"; var key = AesGcmCrypto.PasswordToKey( "secret", AesGcmCrypto.GenerateSalt(), AesGcmCrypto.Iterations); var cipherText = AesGcmCrypto.Encrypt( AesGcmCrypto.GenerateNonce(), Encoding.UTF8.GetBytes(expectedText), key); var actualText = Encoding.UTF8.GetString( AesGcmCrypto.Decrypt(cipherText, key)); Assert.Equal(expectedText, actualText); }
private BlobReference[] WriteBlobs( IReadOnlyCollection <Blob> blobs, Fuzzy scanFuzzy, Func <string, Stream> openRead) { var currentBlobReferences = _currentSnapshotId == null ? new Dictionary <string, BlobReference>() : GetSnapshot(_currentSnapshotId.Value).BlobReferences .ToDictionary(br => br.Name, br => br); return(blobs .AsParallel() .Select(blob => { currentBlobReferences.TryGetValue( blob.Name, out var current); if (!scanFuzzy.IsMatch(blob.Name) && current != null && current.ToBlob().Equals(blob)) { return current; } // Known blobs should be encrypted using the same nonce var nonce = current?.Nonce ?? AesGcmCrypto.GenerateNonce(); using var stream = openRead(blob.Name); var blobReference = new BlobReference( blob.Name, blob.LastWriteTimeUtc, nonce, WriteContent(nonce, stream)); _probe.StoredBlob(blobReference); return blobReference; }) .OrderBy(blobReference => blobReference.Name) .ToArray()); }
private IReadOnlyCollection <Uri> WriteContent( byte[] nonce, Stream stream) { Uri WriteChunk(byte[] chunk) { var encryptedData = AesGcmCrypto.Encrypt( nonce, chunk, _key.Value); var contentUri = Id.ComputeContentUri( _hashAlgorithmName, encryptedData); _uriRepository.StoreValue(contentUri, encryptedData); return(contentUri); } var expectedChunks = stream.Length / _fastCdc.AvgSize; if (expectedChunks < _parallelizeChunkThreshold) { return(_fastCdc.SplitIntoChunks(stream) .Select(WriteChunk) .ToArray()); } else { return(_fastCdc.SplitIntoChunks(stream) .AsParallel() .AsOrdered() .Select(WriteChunk) .ToArray()); } }