/
Get-FileHash.ps1
227 lines (195 loc) · 7.24 KB
/
Get-FileHash.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
#requires -version 2.0
# -----------------------------------------------------------------------------
# Script: Get-FileHash.ps1
# Version: 1.0
# Author: Jeffery Hicks
# http://jdhitsolutions.com/blog
# http://twitter.com/JeffHicks
# Date: 3/31/2011
# Keywords: MD5, SHA1, Checksum
# Comments:
#
# "Those who forget to script are doomed to repeat their work."
#
# ****************************************************************
# * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED *
# * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF *
# * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, *
# * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. *
# ****************************************************************
# -----------------------------------------------------------------------------
Function Get-FileHash {
<#
.SYNOPSIS
Calculate file hash or checksum.
.DESCRIPTION
This command will compute a checksum or filehash for one or more files. The default hashing
algorithm is MD5 but you can also specify SHA1 or SHA256. The command will write a custom
object to the pipeline like this:
Date : 3/30/2011 2:31:42 PM
FullName : C:\scripts\get-filehash.ps1
FileHash : 26B527B37717E2F1A85BD91EF40BCBBE
HashType : MD5
Filename : get-filehash.ps1
Size : 9244
NOTE: You must have permissions to read the file. This will work with system and read-only
files but not with hidden files unless you use -FORCE.
.PARAMETER PSPath
The filename and path of the file to compute. This has aliases of name,file, and path.
.PARAMETER Type
The hashing algorithm. The default is MD5. Other options are SHA1 and SHA256.
.PARAMETER Force
Process hidden files.
.EXAMPLE
PS C:\> Get-Filehash $profile
Date : 3/30/2011 2:29:09 PM
FullName : C:\Users\Jeff\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
FileHash : C68E7BC1755A59EABB0C4BFC12A98C0B
HashType : MD5
Filename : Microsoft.PowerShellISE_profile.ps1
Size : 2760
Return the file hash of the PowerShell profile script.
.EXAMPLE
PS C:\> dir c:\scripts\ -recurse -include *.ps*,*.vbs,*.bat | Get-Filehash | Export-CLIXML E:\ScriptsHash.xml
Get file hashes for all scripts and export to an XML file.
.NOTES
NAME : Get-FileHash
VERSION : 1.0
LAST UPDATED: 3/30/2011
AUTHOR : Jeffery Hicks
Learn more with a copy of Windows PowerShell 2.0: TFM (SAPIEN Press 2010)
.LINK
http://jdhitsolutions.com/blog/2011/03/get-file-hash/
.LINK
Get-Item
.INPUTS
Strings for filenames and paths.
.OUTPUTS
Custom object
#>
[cmdletbinding(SupportsShouldProcess=$True,ConfirmImpact="Low")]
Param (
[Parameter(Position=0,Mandatory=$True,HelpMessage="Enter file name and path.",
ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
[ValidateNotNullorEmpty()]
[Alias("name","file","path")]
[string[]]$PSPath,
[Parameter(Position=1,Mandatory=$False)]
[Alias("hash")]
[ValidateSet("MD5","SHA1","SHA256")]
[string]$Type = "MD5",
[switch]$Force
)
Begin
{
#what time are we starting?
$cmdStart=Get-Date
Write-Verbose "$(Get-Date) Starting $($myinvocation.mycommand)"
if ($force)
{
Write-Verbose "$(Get-Date) Using -Force to find hidden files"
}
#create the hash provider
Switch ($Type) {
"sha1" {
$provider = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
}
"sha256" {
$provider = New-Object System.Security.Cryptography.SHA256CryptoServiceProvider
}
"md5" {
$provider = New-Object System.Security.Cryptography.MD5CryptoServiceProvider
}
}
Write-Verbose "$(Get-Date) Calculating $type hash"
} #begin
Process
{
Foreach ($name in $PSPath) {
Write-Verbose "$(Get-Date) Verifying $name"
#verify file exists
if (Test-Path -Path $name)
{
Write-Verbose "$(Get-Date) Path verified"
Try
{
#get the file item
if ($force)
{
$file=Get-Item -Path $name -force -ErrorAction "Stop"
}
else
{
$file=Get-Item -Path $name -ErrorAction "Stop"
}
}
Catch
{
Write-Warning "Cannot get item $name. Verify it is not a hidden file (did you use -Force?) and that you have correct permissions."
}
#only process if we were able to get the item
if ($file)
{
#only process if file size is greater than 0
#this will also fail if the object is not from the
#filesystem provider
if ($file.length -gt 0)
{
Write-Verbose "$(Get-Date) Opening file stream"
if ($pscmdlet.ShouldProcess($file.fullname))
{
Try
{
$inStream = $file.OpenRead()
Write-Verbose "$(Get-Date) Computing hash"
$start=Get-Date
$hashBytes = $provider.ComputeHash($inStream)
$end=Get-Date
Write-Verbose "$(Get-Date) hash computed in $(($end-$start).ToString())"
Write-Verbose "$(Get-Date) Closing file stream"
$inStream.Close() | Out-Null
#define a hash string variable
$hashString=""
Write-Verbose "$(Get-Date) hashing file bytes"
foreach ($byte in $hashBytes)
{
#calculate the hash
$hashString+=$byte.ToString("X2")
}
#write the hash object to the pipeline
New-Object -TypeName PSObject -Property @{
Filename=$file.name
FullName=$file.Fullname
FileHash=$hashString
HashType=$Type
Size=$file.length
Date=Get-Date
}
} #try
Catch
{
Write-Warning "Failed to get file contents for $($file.name)."
Write-Warning $_.Exception.Message
}
} #should process
} #if $file.length
else
{
Write-Warning "$(Get-Date) File size for $name is 0 or is not from the filesystem provider."
}
}#if $file
} #if Test-Path
else
{
Write-Warning "$(Get-Date) Failed to find $name."
}
} #foreach $file
} #process
End
{
Write-Verbose "$(Get-Date) Ending $($myinvocation.mycommand)"
#what time did we finish?
$cmdEnd=Get-Date
Write-Verbose "$(Get-Date) Total processing time $(($cmdEnd-$cmdStart).ToString())"
}
} #end function