Hashing it Out in PowerShell: Using Get-FileHash

PowerShell 4.0 introduced a new cmdlet, Get-FileHash, primarily for use with Desired State Configuration (DSC). In a pull server configuration, you need to provide file hashes so that servers can recognize changes. That is the primary purpose of a file hash as far as I am concerned is for file integrity. Windows supports several different hashing algorithms, which you should not confuse with encryption.

All a hashing algorithm does is calculate a hash value, also usually referred to as a checksum. If the file changes in any way, even with the addition or removal of a single character, then the next time the hash is calculated it will be different.

The hash can’t tell you what changed, only that the current version of the file is different than the original based on the hash. Let’s look at some ways of using file hashes in PowerShell, outside of DSC.

To create a hash, all you need is a file.

PowerShell

1

get-filehashC:\work\x.zip

Creating a hash with Windows PowerShell. (Image Credit: Jeff Hicks)

The default hashing algorithm in SHA256, but you can use any of these:

SHA1

SHA256

SHA384

SHA512

MACTripleDES

MD5

RIPEMD160

I’m not going to explain each algorithm, as I don’t think it really matters. All we are doing is calculating a file hash, and as long as you use the same algorithm to compare two files I don’t think it makes a difference. For the most part all of these perform reasonably well, especially on small files. Once you start getting into gigabyte size files, then you might notice a difference. In fact, I put together a simple performance testing script.

My script takes a file as input and measures how long it takes to generate a hash using each algorithm.

PowerShell

1

C:\scripts\Demo-FileHash.ps1-PathD:\Vhd\Demo2.vhdx|sortHashtime

Using a PowerShell to determine how long it will take to generate a hash. (Image Credit: Jeff Hicks)

Even on smaller files you will most likely see hashing performance like this. The default SHA256 definitely requires a bit of time to calculate. Personally, I see no reason not to use MD5 for file hashes. It is fast and ubiquitous.

PowerShell

1

get-filehashD:\vhd\Demo2.vhdx-AlgorithmMD5

Using MD5 for file hashes in PowerShell. (Image Credit: Jeff Hicks)

If you want to use this as a default, add it to $PSDefaultParameterValues.

PowerShell

1

$PSDefaultParameterValues.add("Get-FileHash:Algorithm","MD5")

You would insert this command into your PowerShell profile script. Now Get-FileHash will use this algorithm by default.

I prefer to keep hash information in separate directory on the off chance that a bad actor might try to fudge the original file hashes. At some later date, I import the XML file to access the original file hashes.

PowerShell

1

$zHash=Import-Clixml-Pathc:\work\ziphash.xml

At some point after the original file hashes where generated, some of the zip files change. I can use the information from the XML file to compare the stored file hash against a new version, making sure to use the same algorithm. Any files that don’t match are piped to the end.

Next, let’s see how we might use this cmdlet with copying files. If the file hash between the original file and the copy is different, then something happened during the copy process and the file is most likely corrupt. Here’s how you might copy a single file.

The only reason I’m using Write-Host is to make it clear what I’m doing and if there is a problem copying the file.

Using a script to copy a single file. (Image Credit: Jeff Hicks)

This same technique would work for multiple files as well.

PowerShell

1

2

$dest=\\jdh-nvnas\temp

dirc:\scripts\*.xml|foreach{

The only thing I changed was the destination and the files to be copied. I used my NAS with the hope that there might be a network hiccup and cause a problem, but the copy still worked.

Copying a file in Windows PowerShell. (Image Credit: Jeff Hicks)

The last thing I thought I would try is create a proxy function for Copy-Item. My version is essentially Copy-Item, but it also calculates a file hash for each file before it is copied and after. If the file hashes don’t match, PowerShell will throw an exception.

PowerShell

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

#requires -version 4.0

FunctionCopy-ItemWithHash{

<#

.Synopsis

Copy file with hash

.Description

This is a proxy function to Copy-Item that will include hashes for the original file and copy. New properties will be added to the copied file, OriginalHash and CopyHash. The default hashing algorithm is MD5.

This function includes the same algorithm parameter as Get-FileHash, although I set my default to MD5 for performance. I haven’t tested this function under all situations, but it seems to work for simple file copies.

MEMBER LOGIN:

BECOME A PETRI MEMBER:

About the Contributor

Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, teacher and consultant. Jeff has written for numerous online sites and print publications and is a frequent speaker at technology conferences and user groups. His latest book is PowerShell Scripting and Toolmaking.