/// <summary> /// Initialize the <see cref="EncryptionManager"/>. This will initialize the CryptoServiceProvider /// used to perform encryption, as well as to verify that the certificate is suitable for the /// desired mode. /// </summary> private void Initialize() { // Create the CSP. By default, this will generate a new Key and IV, so we need to ensure that we // initialize for each file that is being encrypted. Each file should have a unique key and IV. this.aes = new AesCryptoServiceProvider { // Ensure that we are using the correct key size and block size KeySize = DefaultCspKeySize, BlockSize = DefaultCspBlockSize, // Ensure that we are using Cipher Block Chaining (CBC) Mode = CipherMode.CBC }; if (this.Mode == EncryptionMode.Encrypt) { // We are encrypting the stream, so use the certificate public key as the CSP this.rsa = this.encryptionCertificate.PublicKey.Key as RSACryptoServiceProvider; Pre.Assert(this.rsa != null, "this.rsa != null"); } else { // Initialize the CSP from the private key of the certificate. this.rsa = this.encryptionCertificate.PrivateKey as RSACryptoServiceProvider; Pre.Assert(this.rsa != null, "this.rsa != null"); } }
/// <summary> /// Create a new instance of the <see cref="EncryptionManager"/> class /// </summary> /// <param name="encryptionCertificate"> /// The certificate that contains the secrets used for encryption. Note that /// the private key must be present in this certificate in order for decryption /// to be performed. /// </param> /// <param name="mode">The mode (encryption/decryption) of the encryption manager</param> /// <param name="outputStream">The stream where the transformed content will be written</param> /// <param name="sourceFileSize"></param> public EncryptionManager( X509Certificate2 encryptionCertificate, EncryptionMode mode, Stream outputStream, long sourceFileSize) { Pre.ThrowIfArgumentNull(encryptionCertificate, nameof(encryptionCertificate)); Pre.ThrowIfArgumentNull(outputStream, nameof(outputStream)); Pre.ThrowIfTrue(mode == EncryptionMode.None, "Encryption mode cannot be None"); this.encryptionCertificate = encryptionCertificate; this.Mode = mode; this.sourceFileSize = sourceFileSize; this.outputStream = outputStream; this.sha1 = new SHA1Cng(); this.md5 = new MD5Cng(); // Any valid encrypted file will have a minimum size (to include the header and minimal // encrypted content). Ensure that the source file is at least this size. if (mode == EncryptionMode.Decrypt) { Pre.Assert(sourceFileSize >= MinimumEncryptedFileSize, "sourceFileSize >= minimumEncryptedFileSize"); } this.Initialize(); }
/// <summary> /// Transform a block by encrypting/decrypting the file. /// </summary> /// <param name="buffer">The data to transform</param> /// <param name="offset">The offset within the buffer to begin reading</param> /// <param name="count">The number of bytes from the buffer to read</param> /// <returns>The number of bytes transformed</returns> public int TransformBlock(byte[] buffer, int offset, int count) { Pre.Assert(count >= EncryptedFileHeader.HeaderSize + 16); // Create a new memory stream that will hold the transformed content, as well as allow // for hashes to be calculated as the data is streamed. using (MemoryStream bufferedOutputStream = new MemoryStream()) { // Call the appropriate method to encrypt/decrypt the data if (this.Mode == EncryptionMode.Encrypt) { this.WriteEncrypted(bufferedOutputStream, buffer, offset, count); } else { this.ReadEncrypted(bufferedOutputStream, buffer, offset, count); } // Read the tranformed data as a byte array for each hash calculation. byte[] transformedBuffer = bufferedOutputStream.ToArray(); // Compute the ongoing hash value this.sha1.TransformBlock(transformedBuffer, 0, transformedBuffer.Length, null, 0); this.md5.TransformBlock(transformedBuffer, 0, transformedBuffer.Length, null, 0); // Write the transformed data to the output stream. this.outputStream.Write(transformedBuffer, 0, transformedBuffer.Length); return(transformedBuffer.Length); } }
private static Dictionary <string, string> GetAuthenticationHeaderError(HttpResponseMessage response) { IEnumerable <string> values; if (response.Headers.TryGetValues("Www-Authenticate", out values)) { // Should return a value simiar to the following: // Bearer realm="OneDriveAPI", error="expired_token", error_description="Auth token expired. Try refreshing." // First is to split the 'Bearer' portion string[] headerValue = values.First().Split(new[] { ' ' }, 2); Pre.Assert(headerValue[0] == "Bearer", "headerValue[0] == Bearer"); if (headerValue.Length == 2) { // Next split into response components. There should be a max of 3. string[] responseParts = headerValue[1].Split(new[] { ',' }, 3); return(responseParts .Select(responsePart => responsePart.Trim()) .Select(str => str.Split(new[] { '=' }, 2)) .Where(elements => elements.Length == 2) .ToDictionary(elements => elements[0], elements => elements[1].Trim('\"'))); } } return(new Dictionary <string, string>()); }
public override void UpdateItem(EntryUpdateInfo updateInfo, SyncEntryChangedFlags changeFlags) { if (updateInfo.Entry.Type == SyncEntryType.Directory) { Logger.Debug("Suppressing UpdateItem() call for Directory in BackblazeB2 adapter"); return; } // The changeFlags parameter is passed by value, so we will modify it as we go to unset // the properties that we change. If we are left with a changeFlags that is non-zero, // then we missed a case. if ((changeFlags & SyncEntryChangedFlags.ModifiedTimestamp) != 0) { Pre.Assert(updateInfo.ModifiedDateTimeUtcNew != null, "updateInfo.ModifiedDateTimeUtcNew != null"); // No action needed at the remote end. Updating the blob will update the Last-Modified // property. However, we do need to update the Entry. updateInfo.Entry.ModifiedDateTimeUtc = updateInfo.ModifiedDateTimeUtcNew.Value; changeFlags &= ~SyncEntryChangedFlags.ModifiedTimestamp; } if (changeFlags != SyncEntryChangedFlags.None) { throw new NotImplementedException("changeFlags = " + changeFlags); } }
public static void ClassInitialize(TestContext testContext) { if (!GlobalTestSettings.RunNetworkTests) { return; } string tokenFilePath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "SyncProTesting", "OneDriveTestingToken.json"); if (!File.Exists(tokenFilePath)) { string tokenHelperPath = "OneDriveTokenHelper.exe"; Process p = Process.Start(tokenHelperPath, "/getToken /path \"" + tokenFilePath + "\""); Pre.Assert(p != null, "p != null"); p.WaitForExit(); if (p.ExitCode != 1) { throw new Exception("Failed to get token using OneDriveTokenHelper"); } //throw new FileNotFoundException("Token file was not present at path " + tokenFilePath); } string tokenContent = File.ReadAllText(tokenFilePath); var token = JsonConvert.DeserializeObject <TokenResponse>(tokenContent); if (!token.IsEncrypted) { // The token file is NOT encrypted. Immediately encrypt and save the file back to disk // for security before using it. token.Protect(); tokenContent = JsonConvert.SerializeObject(token, Formatting.Indented); File.WriteAllText(tokenFilePath, tokenContent); } // The token file on disk is encrypted. Decrypt the values for in-memory use. token.Unprotect(); using (OneDriveClient client = new OneDriveClient(token)) { client.TokenRefreshed += (sender, args) => { // The token was refreshed, so save a protected copy of the token to the token file. token = args.NewToken; token.SaveProtectedToken(tokenFilePath); }; client.GetUserProfileAsync().Wait(); } classCurrentToken = token; }
public override SyncEntry CreateSyncEntryForAdapterItem(IAdapterItem item, SyncEntry parentEntry) { GoogleDriveAdapterItem adapterItem = item as GoogleDriveAdapterItem; Pre.Assert(adapterItem != null, "adapterItem != null"); Pre.Assert(adapterItem.Item != null, "adapterItem.Item != null"); return(this.CreateEntry(adapterItem.Item, parentEntry)); }
public static void Start() { string databasePath = CounterDatabase.GetDatabaseFilePath(); string folderPath = Path.GetDirectoryName(databasePath); // Create the directory containing the counters database (if it does not exist). Pre.Assert(folderPath != null, "folderPath != null"); Directory.CreateDirectory(folderPath); processingTask = Task.Run(() => { ProcessCounterEmitsMain(); }); }
public override SyncEntry CreateSyncEntryForAdapterItem(IAdapterItem item, SyncEntry parentEntry) { OneDriveAdapterItem oneDriveAdapterItem = item as OneDriveAdapterItem; Pre.Assert(oneDriveAdapterItem != null, "oneDriveAdapterItem != null"); Pre.Assert(oneDriveAdapterItem.Item != null, "oneDriveAdapterItem.Item != null"); // Is this always true? Pre.Assert(parentEntry != null, "parentEntry != null"); return(this.CreateEntry(oneDriveAdapterItem.Item, parentEntry)); }
public void WriteToStream(MemoryStream bufferedOutputStream) { Pre.Assert(this.EncryptedKey != null, "this.EncryptedKey != null"); Pre.Assert(this.EncryptedKey.Length > 0, "this.EncryptedKey.Length > 0"); Pre.Assert( this.EncryptedKey.Length < EncryptedKeyMaxLength, "this.EncryptedKey.Length < EncryptedKeyMaxLength"); Pre.Assert(this.IV != null, "this.IV != null"); Pre.Assert(this.IV.Length == IVStorageSize, "this.IV.Length == IVStorageSize"); Pre.Assert(this.EncryptedFileLength > 0, "this.EncryptedFileLength > 0"); byte[] headerBytes; // Create a temporary stream for writing the header using (MemoryStream stream = new MemoryStream()) { // Write the encrypted key length and key stream.WriteInt32(this.EncryptedKey.Length); stream.Write(this.EncryptedKey, 0, this.EncryptedKey.Length); // Write the initialization vector and length stream.WriteInt32(this.IV.Length); stream.Write(this.IV, 0, this.IV.Length); // Write the original file file, encrypted file size, and thumbprint stream.WriteInt64(this.OriginalFileLength); stream.WriteInt64(this.EncryptedFileLength); stream.Write(this.CertificateThumbprint, 0, this.CertificateThumbprint.Length); // Write the padding length and the reserved bytes stream.WriteInt16(this.PaddingLength); headerBytes = stream.ToArray(); } // Allocate the 1k buffer for the header. This will be written to the output stream after // populating the fields. byte[] buffer = new byte[HeaderSize]; Buffer.BlockCopy(headerBytes, 0, buffer, 0, headerBytes.Length); using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) { byte[] hash = sha1.ComputeHash(buffer, 0, HeaderSize - ChecksumSize); Buffer.BlockCopy(hash, 0, buffer, buffer.Length - ChecksumSize, ChecksumSize); } Buffer.BlockCopy(headerBytes, 0, buffer, 0, headerBytes.Length); bufferedOutputStream.Write(buffer, 0, buffer.Length); }
/// <summary> /// Read the encrypted file header information from a stream /// </summary> /// <param name="stream">The stream to read</param> /// <returns>The encrypted header object</returns> public static EncryptedFileHeader ReadFromStream(Stream stream) { Pre.ThrowIfArgumentNull(stream, nameof(stream)); // Read the entire header from the stream byte[] buffer = stream.ReadByteArray(HeaderSize); // Verify the header's checksum using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) { byte[] computedHash = sha1.ComputeHash(buffer, 0, HeaderSize - ChecksumSize); byte[] headerHash = BufferUtil.CopyBytes(buffer, buffer.Length - ChecksumSize, ChecksumSize); if (!NativeMethods.ByteArrayEquals(computedHash, headerHash)) { // TODO: Replace with a better exception throw new Exception("The header checksum failed"); } } // Create a new stream for reading the header data. This will make it easier to process the // fields in the header and will avoid having to reposition the original stream. using (MemoryStream headerStream = new MemoryStream(buffer)) { EncryptedFileHeader header = new EncryptedFileHeader(); int encryptedKeyLength = headerStream.ReadInt32(); // Ensure the key is not longer than the buffer Pre.Assert(encryptedKeyLength < HeaderSize, "encryptedKeyLength < HeaderSize"); // Read the encrypted key field. header.EncryptedKey = headerStream.ReadByteArray(encryptedKeyLength); // Read the IV length. This should be 16 bytes (asserted below). int ivLength = headerStream.ReadInt32(); Pre.Assert(ivLength == IVStorageSize, "ivLength == ivStorageSize"); // Read the initialization vector header.IV = headerStream.ReadByteArray(ivLength); // Read the file sizes, thumbprint, and padding header.OriginalFileLength = headerStream.ReadInt64(); header.EncryptedFileLength = headerStream.ReadInt64(); header.CertificateThumbprint = headerStream.ReadByteArray(CertificateThumbprintSize); header.PaddingLength = headerStream.ReadInt16(); return(header); } }
/// <summary> /// Calculate the length of the decrypted data given the encrypted size. /// </summary> /// <param name="encryptedSize">The size of the plaintext data</param> /// <param name="padding"></param> /// <returns>The length of the encrypted data</returns> public static long CalculateDecryptedFileSize(long encryptedSize, out short padding) { Pre.Assert(encryptedSize >= MinimumEncryptedFileSize, "encryptedSize >= minimumEncryptedFileSize"); const int BlockSizeInBytes = DefaultCspBlockSize / 8; // The encrypted data always has a length according to the following formula: // encryptedSize = plainTextSize + blockSize - (plainText % blocksize) padding = (short)((encryptedSize - EncryptedFileHeader.HeaderSize) % BlockSizeInBytes); Pre.Assert(padding >= 0, "padding >= 0"); return(encryptedSize - (EncryptedFileHeader.HeaderSize + BlockSizeInBytes)); }
public void ResizeWindow(object sender) { Rectangle clickedRectangle = sender as Rectangle; Pre.Assert(clickedRectangle != null, "clickedRectangle != null"); switch (clickedRectangle.Name) { case "PART_ResizeTop": this.activeWindow.Cursor = Cursors.SizeNS; this.InternalResizeWindow(ResizeDirection.Top); break; case "PART_ResizeBottom": this.activeWindow.Cursor = Cursors.SizeNS; this.InternalResizeWindow(ResizeDirection.Bottom); break; case "PART_ResizeLeft": this.activeWindow.Cursor = Cursors.SizeWE; this.InternalResizeWindow(ResizeDirection.Left); break; case "PART_ResizeRight": this.activeWindow.Cursor = Cursors.SizeWE; this.InternalResizeWindow(ResizeDirection.Right); break; case "PART_ResizeTopLeft": this.activeWindow.Cursor = Cursors.SizeNWSE; this.InternalResizeWindow(ResizeDirection.TopLeft); break; case "PART_ResizeTopRight": this.activeWindow.Cursor = Cursors.SizeNESW; this.InternalResizeWindow(ResizeDirection.TopRight); break; case "PART_ResizeBottomLeft": this.activeWindow.Cursor = Cursors.SizeNESW; this.InternalResizeWindow(ResizeDirection.BottomLeft); break; case "PART_ResizeBottomRight": this.activeWindow.Cursor = Cursors.SizeNWSE; this.InternalResizeWindow(ResizeDirection.BottomRight); break; } }
public override int Read(byte[] buffer, int offset, int count) { for (int i = 0; i < count; i++) { // Check if we need to download a fragment if (this.currentBufferOffset >= this.currentBuffer.Length) { if (this.isFinalBuffer) { return(i); } HttpResponseMessage response = this.client.DownloadFileFragment( this.downloadUri, this.currentFragmentOffset, fragmentLength).Result; using (response) { this.currentBuffer = response.Content.ReadAsByteArrayAsync().Result; this.currentFragmentOffset++; this.currentBufferOffset = 0; var rangeHeader = response.Content.Headers.ContentRange; Pre.Assert(rangeHeader.To != null, "rangeHeader.To != null"); Pre.Assert(rangeHeader.Length != null, "rangeHeader.Length != null"); if (rangeHeader.To.Value == rangeHeader.Length - 1) { this.isFinalBuffer = true; } } } buffer[i + offset] = this.currentBuffer[this.currentBufferOffset]; this.currentBufferOffset++; } return(count); }
public override IEnumerable <IAdapterItem> GetAdapterItems(IAdapterItem folder) { if (folder == null) { Item root = this.googleDriveClient.GetItemById("root").Result; return(new List <IAdapterItem>() { new GoogleDriveAdapterItem(root, null, this) }); } GoogleDriveAdapterItem adapterItem = folder as GoogleDriveAdapterItem; Pre.Assert(adapterItem != null, "adapterItem != null"); var items = this.googleDriveClient.GetChildItems(adapterItem).Result; IEnumerable <GoogleDriveAdapterItem> adapterItems = items.Select(i => new GoogleDriveAdapterItem(i, folder, this)); return(adapterItems); }
public override IEnumerable <IAdapterItem> GetAdapterItems(IAdapterItem folder) { if (folder == null) { Drive defaultDrive = this.oneDriveClient.GetDefaultDrive().Result; return(new List <OneDriveAdapterItem> { new OneDriveAdapterItem(defaultDrive, this) }); } OneDriveAdapterItem adapterItem = folder as OneDriveAdapterItem; Pre.Assert(adapterItem != null, "adapterItem != null"); IEnumerable <Item> items = this.oneDriveClient.GetChildItems(adapterItem).Result; IEnumerable <OneDriveAdapterItem> adapterItems = items.Select(i => new OneDriveAdapterItem(i, folder, this)); return(adapterItems); }
public void DisplayResizeCursor(object sender) { Rectangle clickedRectangle = sender as Rectangle; Pre.Assert(clickedRectangle != null, "clickedRectangle != null"); switch (clickedRectangle.Name) { case "PART_ResizeTop": this.activeWindow.Cursor = Cursors.SizeNS; break; case "PART_ResizeBottom": this.activeWindow.Cursor = Cursors.SizeNS; break; case "PART_ResizeLeft": this.activeWindow.Cursor = Cursors.SizeWE; break; case "PART_ResizeRight": this.activeWindow.Cursor = Cursors.SizeWE; break; case "PART_ResizeTopLeft": this.activeWindow.Cursor = Cursors.SizeNWSE; break; case "PART_ResizeTopRight": this.activeWindow.Cursor = Cursors.SizeNESW; break; case "PART_ResizeBottomLeft": this.activeWindow.Cursor = Cursors.SizeNESW; break; case "PART_ResizeBottomRight": this.activeWindow.Cursor = Cursors.SizeNWSE; break; } }