Exemple #1
0
        /// <summary>
        /// Hashes a requested number of subsegments within a file segment.
        /// </summary>
        /// <param name="memoryMappedFile">File, mapped to memory for very efficient access, to hash subsegments of</param>
        /// <param name="segmentStart">Position in file of the segment for which you want to hash subsegments</param>
        /// <param name="segmentLength">Length in file of the segment for which you want to hash subsegments</param>
        /// <param name="subsegmentCount">Number of subsegments to hash</param>
        /// <param name="hashAlgorithmName">Name of the hash algorithm to use</param>
        /// <returns>Colletion of <paramref name="subsegmentCount"/> hash segments</returns>
        public SegmentHash[] GetSubsegmentHashes(
            MemoryMappedFile memoryMappedFile,
            long segmentStart,
            long segmentLength,
            byte subsegmentCount,
            HashAlgorithmName hashAlgorithmName)
        {
            Contract.Requires(memoryMappedFile != null);
            Contract.Requires(segmentStart >= 0);
            Contract.Requires(segmentLength >= 0);
            Contract.Requires(subsegmentCount >= 1);
            Contract.Ensures(Contract.Result <SegmentHash[]>() != null);
            Contract.Ensures(Contract.Result <SegmentHash[]>().Length == subsegmentCount);
            Contract.Ensures(Contract.Result <SegmentHash[]>().All(h => h != null && !string.IsNullOrEmpty(h.Hash)));

            GetSegmentationParameters(segmentLength, subsegmentCount, out var standardSubsegmentLength, out var subsegmentLengths);
            using (var hasher = CryptoConfig.CreateFromName(hashAlgorithmName.Name) as HashAlgorithm)
            {
                var subsegmentHashes = new SegmentHash[subsegmentCount];
                for (var i = 0; i < subsegmentLengths.Count(); ++i)
                {
                    var start  = segmentStart + i * standardSubsegmentLength;
                    var length = subsegmentLengths[i];

                    subsegmentHashes[i] = GetSegmentHash(memoryMappedFile, hasher, start, length);
                }

                return(subsegmentHashes);
            }
        }
Exemple #2
0
        /// <summary>
        /// Finds the first segment in a file where it differs from a given reference set of segment hashes, and then
        /// drills down into that segment, pulling subsegment hashes for further comparison.
        /// </summary>
        /// <param name="referenceSegmentHashes">Segment hashes to compare the given file segments to</param>
        /// <param name="file">File to check against the <paramref name="referenceSegmentHashes"/></param>
        /// <param name="segmentStart">Position in file of the segment that is described by <paramref name="referenceSegmentHashes"/></param>
        /// <param name="segmentLength">Length in file of the segment that is described by <paramref name="referenceSegmentHashes"/></param>
        /// <param name="subsegmentCount">Number of subsegment hashes to break the first differing segment into</param>
        /// <param name="hashAlgorithmName">Hash algorithm name used for comparing data</param>
        /// <param name="diffSubsegmentHashes">Will be populated with the collection of <paramref name="subsegmentCount"/> hashes from the first differing segment or <c>null</c> if no difference is found.</param>
        /// <returns><c>true</c> if a difference is found, else <c>false</c></returns>
        public bool TryGetSubsegmentHashesOfFirstDiff(
            SegmentHash[] referenceSegmentHashes,
            FileInfo file,
            long segmentStart,
            long segmentLength,
            byte subsegmentCount,
            HashAlgorithmName hashAlgorithmName,
            out SegmentHash[] diffSubsegmentHashes)
        {
            Contract.Requires(referenceSegmentHashes != null && referenceSegmentHashes.Length > 0);
            Contract.Ensures(referenceSegmentHashes.All(h => h != null && !string.IsNullOrEmpty(h.Hash)));
            Contract.Requires(file != null);
            Contract.Requires(file.Exists);
            Contract.Requires(segmentStart >= 0);
            Contract.Requires(segmentLength >= 0);
            Contract.Requires(subsegmentCount >= 1);
            Contract.Ensures(Contract.ValueAtReturn(out diffSubsegmentHashes) != null);
            Contract.Ensures(Contract.ValueAtReturn(out diffSubsegmentHashes).Length == subsegmentCount);
            Contract.Ensures(Contract.ValueAtReturn(out diffSubsegmentHashes).All(h => h != null && !string.IsNullOrEmpty(h.Hash)));

            GetSegmentationParameters(segmentLength, subsegmentCount, out var standardSubsegmentLength, out var subsegmentLengths);
            using (var hasher = CryptoConfig.CreateFromName(hashAlgorithmName.Name) as HashAlgorithm)
                using (var memoryMappedFile = MemoryMappedFile.CreateFromFile(file.FullName))
                {
                    for (var i = 0; i < subsegmentLengths.Count(); ++i)
                    {
                        var start  = segmentStart + i * standardSubsegmentLength;
                        var length = subsegmentLengths[i];

                        SegmentHash subsegmentHash = GetSegmentHash(memoryMappedFile, hasher, start, length);

                        if (subsegmentHash.Hash != referenceSegmentHashes[i].Hash)
                        {
                            diffSubsegmentHashes = this.GetSubsegmentHashes(
                                memoryMappedFile,
                                subsegmentHash.Start,
                                subsegmentHash.Length,
                                subsegmentCount,
                                hashAlgorithmName);
                            return(true);
                        }
                    }
                }

            diffSubsegmentHashes = null;
            return(false);
        }
Exemple #3
0
        private static SegmentHash GetSegmentHash(MemoryMappedFile memoryMappedFile, HashAlgorithm hasher, long start, long length)
        {
            Contract.Requires(memoryMappedFile != null);
            Contract.Requires(hasher != null);
            Contract.Requires(start >= 0);
            Contract.Requires(length >= 0);

            var segmentHash = new SegmentHash {
                Start = start, Length = length
            };

            using (var segmentStream = memoryMappedFile.CreateViewStream(start, length, MemoryMappedFileAccess.Read))
            {
                segmentHash.Hash = Convert.ToBase64String(hasher.ComputeHash(segmentStream));
            }

            return(segmentHash);
        }