Exemple #1
0
        /// <inheritdoc />
        public override void ForwardProcessDataStream(Stream inStream, Stream outStream, Dictionary <string, string> options, out long writtenBytes)
        {
            if (options == null)
            {
                throw new ArgumentException("Options dictionary was null", "options");
            }
            else if (!options.ContainsKey(paddedSizeOptionName) || !options.ContainsKey(padTypeOptionName) || !options.ContainsKey(padExceptionOptionName))
            {
                throw new ArgumentException("Options dictionary did not contain the necessary padding options", "options");
            }

            int             paddingSize;
            DataPaddingType padType;
            bool            padException;

            if (!int.TryParse(options[paddedSizeOptionName], out paddingSize) || !bool.TryParse(options[padExceptionOptionName], out padException))
            {
                throw new ArgumentException("Options dictionary contained invalid options for DataPadder", "options");
            }

            try { padType = (DataPaddingType)Enum.Parse(typeof(DataPaddingType), options[padTypeOptionName]); }
            catch (ArgumentException) { throw new ArgumentException("Options dictionary contained invalid options for DataPadder", "options"); }

            if (padException && inStream.Length > paddingSize - 4)
            {
                throw new ArgumentException("Options dictionary contained invalid options for DataPadder. Not enough data padding was allowed", "options");
            }

            paddingSize = paddingSize - 4 - (int)inStream.Length;
            if (paddingSize < 0)
            {
                paddingSize = 0;
            }

            byte[] padData;

            if (padType == DataPaddingType.Random)
            {
#if NETFX_CORE
                CryptographicBuffer.CopyToByteArray(CryptographicBuffer.GenerateRandom((uint)paddingSize), out padData);
#else
                padData = new byte[paddingSize];
                rand.GetBytes(padData);
#endif
            }
            else
            {
                padData = new byte[paddingSize];
            }

            StreamTools.Write(inStream, 0, inStream.Length, outStream, 8192, double.MaxValue, int.MaxValue);

            if (paddingSize != 0)
            {
                outStream.Write(padData, 0, padData.Length);
            }

            outStream.Write(BitConverter.GetBytes(paddingSize + 4), 0, 4);
            writtenBytes = outStream.Position;
        }
Exemple #2
0
        /// <inheritdoc />
        public override void ReverseProcessDataStream(Stream inStream, Stream outStream, Dictionary <string, string> options, out long writtenBytes)
        {
            inStream.Seek(inStream.Length - 4, SeekOrigin.Begin);
            byte[] buffer = new byte[4];
            inStream.Read(buffer, 0, 4);
            inStream.Seek(0, SeekOrigin.Begin);

            //read the last 4 bytes from the input stream
            int padSize = BitConverter.ToInt32(buffer, 0);

            StreamTools.Write(inStream, 0, inStream.Length - padSize, outStream, 8192, double.MaxValue, int.MaxValue);
            writtenBytes = outStream.Length;
        }
Exemple #3
0
        /// <inheritdoc />
        public override void ForwardProcessDataStream(System.IO.Stream inStream, System.IO.Stream outStream, Dictionary <string, string> options, out long writtenBytes)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
            else if (!options.ContainsKey(PasswordOption))
            {
                throw new ArgumentException("Options must contain encryption key", "options");
            }

            if (outStream == null)
            {
                throw new ArgumentNullException("outStream");
            }

#if NETFX_CORE
            inStream.Seek(0, 0);
            outStream.Seek(0, 0);

            IBuffer pwBuffer   = CryptographicBuffer.ConvertStringToBinary(options[PasswordOption], BinaryStringEncoding.Utf8);
            IBuffer saltBuffer = CryptographicBuffer.CreateFromByteArray(SALT);

            // Derive key material for password size 32 bytes for AES256 algorithm
            KeyDerivationAlgorithmProvider keyDerivationProvider = Windows.Security.Cryptography.Core.KeyDerivationAlgorithmProvider.OpenAlgorithm("PBKDF2_SHA1");
            // using salt and 1000 iterations
            KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(saltBuffer, 1000);

            // create a key based on original key and derivation parmaters
            CryptographicKey keyOriginal  = keyDerivationProvider.CreateKey(pwBuffer);
            IBuffer          keyMaterial  = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, 32);
            CryptographicKey derivedPwKey = keyDerivationProvider.CreateKey(pwBuffer);

            // derive buffer to be used for encryption salt from derived password key
            IBuffer saltMaterial = CryptographicEngine.DeriveKeyMaterial(derivedPwKey, pbkdf2Parms, 16);

            // display the buffers - because KeyDerivationProvider always gets cleared after each use, they are very similar unforunately
            string keyMaterialString  = CryptographicBuffer.EncodeToBase64String(keyMaterial);
            string saltMaterialString = CryptographicBuffer.EncodeToBase64String(saltMaterial);

            SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
            // create symmetric key from derived password key
            CryptographicKey symmKey = symProvider.CreateSymmetricKey(keyMaterial);

            using (MemoryStream ms = new MemoryStream())
            {
                inStream.CopyTo(ms);
                // encrypt data buffer using symmetric key and derived salt material
                IBuffer resultBuffer = CryptographicEngine.Encrypt(symmKey, WindowsRuntimeBufferExtensions.GetWindowsRuntimeBuffer(ms), saltMaterial);
                resultBuffer.AsStream().CopyTo(outStream);
                writtenBytes = outStream.Position;
            }
#else
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(options[PasswordOption], SALT);
            var key = pdb.GetBytes(32);
            pdb.Reset();
            var iv = pdb.GetBytes(16);

            using (var transform = encrypter.CreateEncryptor(key, iv))
            {
                using (MemoryStream internalStream = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(internalStream, transform, CryptoStreamMode.Write))
                    {
                        StreamTools.Write(inStream, csEncrypt);
                        inStream.Flush();
                        csEncrypt.FlushFinalBlock();

                        internalStream.Seek(0, 0);
                        StreamTools.Write(internalStream, outStream);
                        writtenBytes = outStream.Position;
                    }
                }
            }
#endif
        }
        /// <summary>
        /// Sets the item data using the provided data stream. Useful for setting data after deserialisation
        /// </summary>
        /// <param name="itemIdentifier"></param>
        /// <param name="itemDataStream"></param>
        public void SetData(string itemIdentifier, Stream itemDataStream)
        {
            lock (dataLocker)
            {
                if (itemIdentifier == null)
                {
                    throw new ArgumentNullException("itemIdentifier");
                }
                if (itemDataStream == null)
                {
                    throw new ArgumentNullException("itemDataStream");
                }

                #region Build Internal Data Structure
                if (DataBuildMode == DataBuildMode.Disk_Single ||
                    //ItemBuildMode == ItemBuildMode.Both_Single ||
                    DataBuildMode == DataBuildMode.Memory_Single)
                {
                    CompleteDataStream = new StreamTools.ThreadSafeStream(itemDataStream);
                }
                else
                {
                    //Break the itemDataStream into blocks
                    ChunkDataStreams = new StreamTools.ThreadSafeStream[ChunkPositionLengthDict.Count];

                    //If the itemDataStream is a memory stream we can try to access the buffer as it makes creating the streams more efficient
                    byte[] itemDataStreamBuffer = null;
                    if (itemDataStream is MemoryStream)
                    {
                        try
                        {
                            itemDataStreamBuffer = ((MemoryStream)itemDataStream).GetBuffer();
                        }
                        catch (UnauthorizedAccessException) { /* Ignore */ }
                    }

                    for (int i = 0; i < ChunkPositionLengthDict.Count; i++)
                    {
                        if (itemDataStreamBuffer != null)
                        {
                            //This is the fastest way to create a block of data streams
                            ChunkDataStreams[i] = new StreamTools.ThreadSafeStream(new MemoryStream(itemDataStreamBuffer, ChunkPositionLengthDict[i].Position, ChunkPositionLengthDict[i].Length));
                        }
                        else
                        {
                            //We now need to available the respective data into blocks
                            Stream destinationStream = null;
                            if (DataBuildMode == DataBuildMode.Disk_Blocks)
                            {
                                string folderLocation = "DFS_" + NetworkComms.NetworkIdentifier;
                                string fileName       = Path.Combine(folderLocation, itemIdentifier + ".DFSItemData_" + i.ToString());

                                if (File.Exists(fileName))
                                {
                                    destinationStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                                    //if (StreamTools.MD5(destinationStream) != checksum)
                                    //    throw new Exception("Wrong place, wrong time, wrong file!");
                                }
                                else
                                {
                                    //Create the folder if it does not exist yet
                                    lock (DFS.globalDFSLocker)
                                    {
                                        if (!Directory.Exists(folderLocation))
                                        {
                                            Directory.CreateDirectory(folderLocation);
                                        }
                                    }

                                    destinationStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 8192, FileOptions.DeleteOnClose);
                                    destinationStream.SetLength(ChunkPositionLengthDict[i].Length);
                                    destinationStream.Flush();
                                }

                                if (!File.Exists(fileName))
                                {
                                    throw new Exception("At this point the item data file should have been created. This exception should not really be possible.");
                                }
                            }
                            else
                            {
                                //If we are not exclusively building to the disk we just use a memory stream at this stage
                                destinationStream = new MemoryStream(ChunkPositionLengthDict[i].Length);
                            }

                            //Ensure we start at the beginning of the stream
                            destinationStream.Seek(0, SeekOrigin.Begin);

                            //Copy over the correct part of the itemDataStream to the chunks
                            StreamTools.Write(itemDataStream, ChunkPositionLengthDict[i].Position, ChunkPositionLengthDict[i].Length, destinationStream, 8192, double.MaxValue, int.MaxValue);
                            ChunkDataStreams[i] = new StreamTools.ThreadSafeStream(destinationStream);
                        }
                    }
                }
                #endregion

                this.CompleteDataCheckSum = StreamTools.MD5(itemDataStream);
            }
        }