Example #1
0
        /// <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");
            }
        }
Example #2
0
        /// <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();
        }
Example #3
0
        /// <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);
            }
        }
Example #4
0
        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>());
        }
Example #5
0
        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);
            }
        }
Example #6
0
        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;
        }
Example #7
0
        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));
        }
Example #8
0
        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(); });
        }
Example #9
0
        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));
        }
Example #10
0
        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);
        }
Example #11
0
        /// <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);
            }
        }
Example #12
0
        /// <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));
        }
Example #13
0
        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);
        }
Example #15
0
        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);
        }
Example #16
0
        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);
        }
Example #17
0
        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;
            }
        }