Created
October 15, 2016 13:34
-
-
Save GrantTrebbin/bacc9f1ea0376b58cac44729a57ace91 to your computer and use it in GitHub Desktop.
Create fingerprints of directories and files that incorporate name and directory structure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Hex_To_Bytes($hex){ | |
# Takes a string with an even number of hexadecimal characters and | |
# converts it two characters at a time to an array of bytes half as long | |
# Initialize ouput byte array | |
$hexLength = $hex.Length | |
$byteLength = $hexLength / 2 | |
$bytes = ,0 * ($byteLength) | |
# generate bytes by taking 2 hexadecimal characters at a time | |
for($i=0; $i -lt $byteLength; $i++){ | |
$bytes[$i] = [System.Convert]::ToByte($hex.Substring($i*2,2),16) | |
} | |
return $bytes | |
} | |
function XOR_Hex($hex1, $hex2){ | |
# Takes two strings of hexadecimal characters | |
# Find the length of the longest hex value | |
$l1 = $hex1.length | |
$length = $l1 | |
$l2 = $hex2.length | |
if ($l2 -gt $length) {$length = $l2} | |
# Round that length up to the nearest even number | |
$length = 2 * [Math]::Ceiling($length/2) | |
# Make both hex strings this long by padding the left with zeros | |
$hex1 = $hex1.PadLeft($length, '0') | |
$hex2 = $hex2.PadLeft($length, '0') | |
# Convert these strings to byte arrays | |
$b1 = Hex_To_Bytes $hex1 | |
$b2 = Hex_To_Bytes $hex2 | |
# XOR the the byte arrays | |
$xored = ,0 * ($length/2) | |
for ($i = 0; $i -lt $b1.Count; $i++){ | |
$xored[$i] = [char]($b1[$i] -bxor $b2[$i]) | |
} | |
# Convert the byte array into a hex string | |
$hexstring = [System.BitConverter]::ToString($xored) -replace '-' | |
return $hexstring | |
} | |
function Byte_Hash([array]$bytesToHash) { | |
# Calculate the hash of a byte array | |
$hasher = new-object System.Security.Cryptography.MD5CryptoServiceProvider | |
$hashByteArray = $hasher.ComputeHash($bytesToHash) | |
# Convert the byte array to a hexadecimal string | |
foreach($byte in $hashByteArray) | |
{ | |
$result += "{0:X2}" -f $byte | |
} | |
return $result; | |
} | |
function String_Hash([string]$textToHash) { | |
# Calculate the hash of a UTF8 byte representation of a String | |
$bytesToHash = [System.Text.Encoding]::UTF8.GetBytes($textToHash) | |
$result = Byte_Hash $bytesToHash | |
return $result; | |
} | |
function Hash_File($FilePath){ | |
# Extract the file name from the path | |
$fileName = Split-Path -Path $FilePath.ToString() -Leaf | |
# Get the hash of the file and file name | |
$contentHash = (Get-FileHash $FilePath -Algorithm MD5).Hash | |
$nameHash = String_Hash $fileName | |
# Combine the two hashes with an XOR | |
$xorOfHashes = XOR_HEX $nameHash $contentHash | |
# Take the hash of the XOR result and return it | |
$byteXorOfHashes = Hex_To_Bytes $xorOfHashes | |
$hashOfXor = Byte_Hash $byteXorOfHashes | |
return $hashOfXor | |
} | |
function Hash_Directory($directoryPath){ | |
# Get all the items in a directory | |
$items = Get-ChildItem -Path $directoryPath -Filter "" -Force| Select FullName | |
$contentHash = "00000000000000000000000000000000" | |
# Process each item | |
ForEach($item in $items){ | |
# Get the attributes of each item | |
$itemName = (Get-Item -Force $item.FullName) | |
$Attributes = $itemName.Attributes.ToString() | |
$reparsePoint = $Attributes.Contains("ReparsePoint") | |
$directory = $Attributes.Contains("Directory") | |
$calculateHash = $true | |
# Include or exclude reparse point directories | |
if (($reparsePoint -eq $true) -and ($directory -eq $true)){ | |
$calculateHash = $true | |
} | |
# Include or exclude reparse point files | |
if (($reparsePoint -eq $true) -and ($directory -eq $false)){ | |
$calculateHash = $true | |
} | |
# Calculate the item hash and combine it with the total | |
if ($calculateHash -eq $true){ | |
$itemHash = Get_Item_Hash $item.FullName | |
$contentHash = XOR_Hex $contentHash $itemHash | |
} | |
} | |
# Hash the name of the directory | |
$directoryName = Split-Path -Path $directoryPath.ToString() -Leaf | |
$nameHash = String_Hash $directoryName | |
# Combine the name and content hashes | |
$xorOfHashes = XOR_HEX $nameHash $contentHash | |
# Hash the combined hash | |
$byteXorOfHashes = Hex_To_Bytes $xorOfHashes | |
$hashOfXor = Byte_Hash $byteXorOfHashes | |
return $hashOfXor | |
} | |
function Get_Item_Hash($item){ | |
# Find the object | |
$itemobject = Get-Item $item -Force | |
# Take the appropriate action if the object is a file or directory | |
$IsDirectory = $itemobject -is [System.IO.DirectoryInfo] | |
if($IsDirectory -eq $true){ | |
$hashValue = Hash_Directory $item | |
}else{ | |
$hashValue = Hash_File $item | |
} | |
# This displays the DirHash for all objects found when traversing the tree | |
Write-Host $hashValue $item | |
return $hashValue | |
} | |
# Just a test location - change to suit your own circumstances | |
$Location = "D:\Grant\Projects\xHashTest" | |
Get_Item_Hash $Location |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment