当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 如何使用 Get-FileHash PowerShell Cmdlet

作者:精品下载站 日期:2024-12-14 13:06:20 浏览:12 分类:玩电脑

如何使用 Get-FileHash PowerShell Cmdlet


您需要比较两个文件或确保文件没有更改吗? PowerShell cmdlet Get-FileHash 为文件或数据流生成哈希值。哈希只是一种将一个值转换为另一个值的函数。有时,哈希值可能较小以节省空间,或者哈希值可能是用于验证文件的校验和。

在本文中,您将了解使用 Get-FileHash 的多种方法,以及有关哈希背景和安全最佳实践的更多详细信息!

先决条件

PowerShell 4 以上的任何版本,其中包括 Windows PowerShell 和 PowerShell Core。

什么是哈希?

如果您可以创建一个代表一些数据或文件的简单值怎么办?哈希值或数字签名允许您比较两组数据。哈希被认为是一致的和功能性的,因为相同的输入总是会创建相同的输出。

因此,即使输入中的单个字符发生更改,哈希也会有所不同。哈希值是使用特定的哈希算法(计算哈希值的方法)来计算的。

每种散列算法都有其非常适合的特定情况。通常需要在速度和安全性之间进行权衡。 MD5 等算法速度快,但哈希值复杂度较低。另一方面,SHA512 生成更复杂的哈希值,但总体速度较慢

对于安全措施,通常不建议使用 MD5。相反,请尝试使用 SHA512。

散列的一个重要用途是对数据进行签名。有时,两个不同的输入会产生相同的输出哈希。这称为哈希冲突。当任何人都可以预见地为特定算法创建哈希冲突时,该算法就会被认为不太安全或“损坏”。

PowerShell 的 Get-FileHash cmdlet 支持多种算法,如下所列。

  • PowerShell Core(版本 6 和 7):MD5SHA1SHA256SHA384SHA512
  • Windows PowerShell(版本 4 到 5.1):MACTripleDESMD5RIPEMD160SHA1SHA256SHA384SHA512

计算单个文件的哈希值

要熟悉 Get-FileHash cmdlet,请将单个文件传递给该命令,如以下示例所示。

Get-FileHash C:\Windows\write.exe

Get-FileHash 将输出所使用的算法、文件的哈希值以及您指定的文件的完整路径,如下所示。如果未指定其他算法,则所有版本的 PowerShell 的默认值为 SHA256

[玩转系统] 如何使用 Get-FileHash PowerShell Cmdlet

计算目录中文件的哈希值

要为目录中的每个文件生成哈希值,请在 Path 参数中使用通配符 (*)。您可能会注意到没有指定算法。

复制以下命令并从根 C:\ 目录运行,为 C:\Windows 目录中的所有可执行文件生成 SHA256 哈希值。

# The example below computes the hashes relative to the current directory
# notated by the "." before the "\".
Get-FileHash .\Windows\*.exe

[玩转系统] 如何使用 Get-FileHash PowerShell Cmdlet

递归生成所有文件的哈希值

要对目录及其子目录中的所有文件进行哈希处理,请通过 Get-ChildItem 递归列出项目,并将结果传递给 Get-FileHash。尽管您可以在 Get-FileHash 中使用通配符,但这不会递归遍历每个子目录。

Get-ChildItem -Path C:\py* -Recurse -Filter *.exe | Get-FileHash

[玩转系统] 如何使用 Get-FileHash PowerShell Cmdlet

通过计算属性将文件哈希添加到 Get-ChildItem 输出

Get-FileHash 本身的输出有限。当与 Get-ChildItem 结合使用时,许多文件属性会在输出中丢失。要保留文件信息,请创建一个计算属性来动态添加文件哈希。

下面的示例读取 windows-version.txt 示例文件,仅从 Get-ChildItemNameLength 属性/code> 输出,并添加 Hash 计算属性。

Select-Object uses a hashtable to create a calculated property. Define a "Name" and an
 "Expression", which operates on the current object in the pipeline.
 Get-ChildItem .\windows-version.txt | 
 Select-Object -Property Name,Length,
 @{name="Hash";expression={(Get-FileHash $_.FullName).hash}}

[玩转系统] 如何使用 Get-FileHash PowerShell Cmdlet

使用哈希比较两个目录中的所有文件

假设您有两个文件夹并且需要查找哪些文件不同。您可以通过使用 Get-FileHash 为每个文件生成哈希值,然后比较它们来比较这些文件夹中的所有文件。

基于您通过计算属性和 Get-FileHash 学到的知识,cmdlet Compare-Object 会比较每个文件的计算哈希并输出任何差异。

首先,检索一组可执行文件和计算出的哈希值,以便与 Compare-Object 一起使用。

# Retrieve all executables directly located within the C:\Windows directory and compute a hash value for each.
$WindowsExesOnly = Get-ChildItem C:\Windows\*.exe | 
Select-Object -Property *,
@{name="Hash";expression={(Get-FileHash $_.FullName -Algorithm MD5).hash}}

# Retrieve all executables located in any directory from the C:\ drive, but not recursively, and compute a hash value for each.
$SecondLevelExes = Get-ChildItem C:\*\*.exe | 
Select-Object -Property *,
@{name="Hash";expression={(Get-FileHash $_.FullName -Algorithm MD5).hash}}

接下来,使用 ReferenceObject 将生成的文件对象数组 $WindowsExesOnly$SecondLevelExes 提供给 Compare-ObjectDifferenceObject 参数。运行以下代码并传递 NameHash 属性以与 Compare-Object 进行比较。同时使用 NameHash 属性允许相同的文件但具有不同的文件名。

Compare-Object -Ref $WindowsExesOnly -Dif $SecondLevelExes -Property Name,Hash

Compare-Object 输出显示 SideIndicator 属性,该属性指示不相同的文件存在于哪个数组中。如下所示,六个唯一的文件位于 $SecondLevelExes 数组。

[玩转系统] 如何使用 Get-FileHash PowerShell Cmdlet

如果您想查看唯一文件的文件长度怎么办?使用 PassThru 参数,原始属性通过管道传递,并将 SideIndicator 属性添加到原始对象。

Compare-Object -Ref $WindowsExesOnly -Dif $SecondLevelExes -Property Name,Hash -PassThru | Select-Object SideIndicator,Name,Hash,Length

[玩转系统] 如何使用 Get-FileHash PowerShell Cmdlet

从数据流生成哈希值

到目前为止,您已经学习了如何查找文件的哈希值,但是 Get-FileHash 可以帮助您做得更好。它还可以获得未存储在文件中的数据的哈希值,即数据流。

请记住,任何差异,甚至是额外的换行符,都会导致哈希值发生变化。避免任何哈希问题的一种方法是将数据转换为数据流,并通过 InputStream 参数传递给 Get-FileHash,如下所示。

Create an in-memory stream of data with the [System.IO.MemoryStream] constructor.
 Retrieve the bytes of a string using the [System.Text.Encoding]::ASCII static method.
 $String = "Hello World"
 Get-FileHash -InputStream ([System.IO.MemoryStream]::New([System.Text.Encoding]::ASCII.GetBytes($String)))

[玩转系统] 如何使用 Get-FileHash PowerShell Cmdlet

事实上,您可以将任何一系列字节转换为 MemoryStream,即存储在 RAM 中的一系列数据,以便 Get-FileHash 生成散列来自,不仅仅是字符串!

计算拆分为多个文件(分块数据)的文件的哈希值

假设您有一个 5TB 的大型备份文件以及生成的哈希值来验证该文件。由于大小的原因,该文件被分成 100GB 的分块数据块,以实现存储灵活性。

验证原始文件的一种可能方法是将所有 100GB 文件组合在一起并验证结果文件的哈希值。当然,5TB 的磁盘空间很大!

相反,您可以组合各个文件的哈希值。通过组合哈希值,您可以跳过组合文件这一消耗磁盘空间的步骤。请参阅下面的代码,了解如何将分块数据流式传输为组合哈希值的示例。

# First, create a hash algorithm object using SHA256.
$Algorithm = [System.Security.Cryptography.HashAlgorithm]::Create("SHA256")

# Next, create a cryptographic stream of data using the SHA256 hash algorithm.
$CryptoStream = [System.Security.Cryptography.CryptoStream]::new(
    ([System.IO.Stream]::Null), 
    $Algorithm, 
    "Write"
)

# Retrieve each file and copy the data into the cryptographic stream.
foreach ($File in Get-ChildItem -File) {
    $FileStream = [io.file]::OpenRead($File.FullName)
    $FileStream.CopyTo($CryptoStream)
}

# Close all files and close out the cryptographic stream.
$FileStream.Close()
$CryptoStream.FlushFinalBlock()

# Combine all of the hashes as hexadecimal formats "X2" and join the values.
($Algorithm.Hash | ForEach-Object {$_.ToString("X2")}) -join ''

旁白:了解文件分块和流式传输

没有必要了解分块和流数据的所有来龙去脉来计算文件哈希,但要真正了解这一切是如何工作的!

为了说明这种分块和流式传输的性质,假设您的源文件包含 12 的值。每个数字之间有一个 Windows 换行符 (\r\n),如下面所示的十六进制编辑器所示。

[玩转系统] 如何使用 Get-FileHash PowerShell Cmdlet

该源文件已被拆分为两个文件,分别包含内容 12。在十六进制查看器中查看每个文件会显示每个文件都是三个字节,带有数字和 Windows 换行符。

[玩转系统] 如何使用 Get-FileHash PowerShell Cmdlet

如下所示,源文件哈希和这两个分块文件的哈希匹配。

[玩转系统] 如何使用 Get-FileHash PowerShell Cmdlet

重要的是要确保输入文件的顺序与源文件中的字节顺序匹配,以获得相同的哈希值。请注意,如果您使用 Sort-Object 更改输入文件的顺序,则哈希会完全更改。

[玩转系统] 如何使用 Get-FileHash PowerShell Cmdlet

有了这些知识,您几乎可以立即对 5TB 文件进行哈希处理!

下一步

在本文中,您学习了如何在 PowerShell 中使用 Get-FileHash cmdlet。您还了解了哈希的本质、安全哈希要求以及帮助您选择适合您需求的算法的最佳实践。

有了这些知识,您将能够彻底识别数据的更改,即使只更改了一个字符!

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯