Create fingerprints of directories and files that incorporate name and directory structure
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