Câu trả lời:
Nếu nội dung là một chuỗi:
$someString = "Hello, World!"
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$utf8 = New-Object -TypeName System.Text.UTF8Encoding
$hash = [System.BitConverter]::ToString($md5.ComputeHash($utf8.GetBytes($someString)))
Nếu nội dung là một tệp:
$someFilePath = "C:\foo.txt"
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes($someFilePath)))
Bắt đầu từ PowerShell phiên bản 4, điều này rất dễ thực hiện đối với các tệp nằm ngoài hộp với Get-FileHash
lệnh ghép ngắn:
Get-FileHash <filepath> -Algorithm MD5
Điều này chắc chắn là tốt hơn vì nó tránh được các vấn đề mà giải pháp đầu tiên đưa ra như được xác định trong các nhận xét (sử dụng một luồng, đóng nó và hỗ trợ các tệp lớn).
Exception calling "ReadAllBytes" with "1" argument(s): "The file is too long. This operation is currently limited to supporting files less than 2 gigabytes in size."
Là một người Linux mới biết đến Powershell, tôi rất khó chịu với những cuộc đấu tranh mà tôi đang có một khoản tiền md5, điều này chỉ đơn giản là md5sum file.ext
trên Linux.
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)))
Điều này cho phép bạn sử dụng bộ nhớ thấp và không giới hạn 2GB .
$stream = [System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
sau $hash = [System.BitConverter]::ToString($md5.ComputeHash($stream))
đó$stream.Close()
Nếu bạn đang sử dụng Tiện ích mở rộng cộng đồng PowerShell, có một lệnh Get-Hash sẽ thực hiện việc này một cách dễ dàng:
C:\PS> "hello world" | Get-Hash -Algorithm MD5
Algorithm: MD5
Path :
HashString : E42B054623B3799CB71F0883900F2764
Get-FileHash
trong vanilla PowerShell 4.0. Vide TechNet .
Đây là hai dòng, chỉ cần thay đổi "xin chào" trong dòng # 2:
PS C:\> [Reflection.Assembly]::LoadWithPartialName("System.Web")
PS C:\> [System.Web.Security.FormsAuthentication]::HashPasswordForStoringInConfigFile("hello", "MD5")
Đây là một chức năng tôi sử dụng để xử lý các đường dẫn tương đối và tuyệt đối:
function md5hash($path)
{
$fullPath = Resolve-Path $path
$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$file = [System.IO.File]::Open($fullPath,[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
try {
[System.BitConverter]::ToString($md5.ComputeHash($file))
} finally {
$file.Dispose()
}
}
Cảm ơn @davor ở trên về đề xuất sử dụng Open () thay vì ReadAllBytes () và @ jpmc26 cho đề xuất sử dụng khối cuối cùng.
Dispose
gọi nên ở trong một finally
khối.
Một lệnh tích hợp khác đã được cài đặt từ lâu trong Windows theo mặc định có từ năm 2003 là Certutil , tất nhiên cũng có thể được gọi từ PowerShell.
CertUtil -hashfile file.foo MD5
(Hãy cẩn thận: MD5 phải có trong tất cả các mũ để có độ bền tối đa)
FipsAlgorithmPolicy
được kích hoạt.
Có rất nhiều ví dụ trực tuyến sử dụng ComputeHash (). Thử nghiệm của tôi cho thấy điều này rất chậm khi chạy qua kết nối mạng. Đoạn mã dưới đây chạy nhanh hơn nhiều đối với tôi, tuy nhiên số dặm của bạn có thể thay đổi:
$md5 = [System.Security.Cryptography.MD5]::Create("MD5")
$fd = [System.IO.File]::OpenRead($file)
$buf = New-Object byte[] (1024*1024*8) # 8 MB buffer
while (($read_len = $fd.Read($buf,0,$buf.length)) -eq $buf.length){
$total += $buf.length
$md5.TransformBlock($buf,$offset,$buf.length,$buf,$offset)
Write-Progress -Activity "Hashing File" `
-Status $file -percentComplete ($total/$fd.length * 100)
}
# Finalize the last read
$md5.TransformFinalBlock($buf, 0, $read_len)
$hash = $md5.Hash
# Convert hash bytes to a hexadecimal formatted string
$hash | foreach { $hash_txt += $_.ToString("x2") }
Write-Host $hash_txt
write-progress
dòng làm gì? Cú pháp highlighter dường như không thích nó.
Trang web này có một ví dụ: Sử dụng Powershell cho MD5 Checksums . Nó sử dụng .NET framework để khởi tạo một thể hiện của thuật toán băm MD5 để tính toán hàm băm.
Đây là mã từ bài viết, kết hợp với nhận xét của Stephen:
param
(
$file
)
$algo = [System.Security.Cryptography.HashAlgorithm]::Create("MD5")
$stream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open,
[System.IO.FileAccess]::Read)
$md5StringBuilder = New-Object System.Text.StringBuilder
$algo.ComputeHash($stream) | % { [void] $md5StringBuilder.Append($_.ToString("x2")) }
$md5StringBuilder.ToString()
$stream.Dispose()
Như đã nêu trong câu trả lời được chấp nhận, Get-FileHash
rất dễ sử dụng với các tệp, nhưng cũng có thể sử dụng nó với các chuỗi:
$s = "asdf"
Get-FileHash -InputStream ([System.IO.MemoryStream]::New([System.Text.Encoding]::ASCII.GetBytes($s)))
Hiện tại đã có chức năng Get-FileHash rất tiện dụng.
PS C:\> Get-FileHash C:\Users\Andris\Downloads\Contoso8_1_ENT.iso -Algorithm SHA384 | Format-List
Algorithm : SHA384
Hash : 20AB1C2EE19FC96A7C66E33917D191A24E3CE9DAC99DB7C786ACCE31E559144FEAFC695C58E508E2EBBC9D3C96F21FA3
Path : C:\Users\Andris\Downloads\Contoso8_1_ENT.iso
Chỉ cần thay đổi SHA384
thành MD5
.
Ví dụ là từ tài liệu chính thức của PowerShell 5.1 . Các tài liệu có nhiều ví dụ.
Điều này sẽ trở thành một lớp lót nếu bạn tải xuống Trình kiểm tra tính toàn vẹn tệp (FCIV) từ Microsoft.
Tôi đã tải xuống FCIV từ đây: Tính khả dụng và mô tả của tiện ích Trình kiểm tra toàn vẹn tệp kiểm tra tệp
Chạy lệnh sau. Tôi đã có mười tập tin để kiểm tra.
Get-ChildItem WTAM*.tar | % {.\fciv $_.Name}
PowerShell One-Liners (chuỗi để băm)
MD5
([System.BitConverter]::ToString((New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider).ComputeHash((New-Object -TypeName System.Text.UTF8Encoding).GetBytes("Hello, World!")))).Replace("-","")
SHA1
([System.BitConverter]::ToString((New-Object -TypeName System.Security.Cryptography.SHA1CryptoServiceProvider).ComputeHash((New-Object -TypeName System.Text.UTF8Encoding).GetBytes("Hello, World!")))).Replace("-","")
SHA256
([System.BitConverter]::ToString((New-Object -TypeName System.Security.Cryptography.SHA256CryptoServiceProvider).ComputeHash((New-Object -TypeName System.Text.UTF8Encoding).GetBytes("Hello, World!")))).Replace("-","")
SHA384
([System.BitConverter]::ToString((New-Object -TypeName System.Security.Cryptography.SHA384CryptoServiceProvider).ComputeHash((New-Object -TypeName System.Text.UTF8Encoding).GetBytes("Hello, World!")))).Replace("-","")
SHA512
([System.BitConverter]::ToString((New-Object -TypeName System.Security.Cryptography.SHA512CryptoServiceProvider).ComputeHash((New-Object -TypeName System.Text.UTF8Encoding).GetBytes("Hello, World!")))).Replace("-","")
Điều này sẽ trả về hàm băm MD5 cho một tệp trên máy tính từ xa:
Invoke-Command -ComputerName RemoteComputerName -ScriptBlock {
$fullPath = Resolve-Path 'c:\Program Files\Internet Explorer\iexplore.exe'
$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$file = [System.IO.File]::OpenRead($fullPath)
$hash = [System.BitConverter]::ToString($md5.ComputeHash($file))
$hash -replace "-", ""
$file.Dispose()
}
Dưới đây là một ví dụ in đẹp cố gắng xác minh dấu vân tay SHA256. Tôi đã tải xuống gpg4win v3.0.3 bằng PowerShell v4 (yêu cầu Get-FileHash
).
Tải xuống gói từ https://www.gpg4win.org/doad.html , mở PowerShell, lấy hàm băm từ trang tải xuống và chạy:
cd ${env:USERPROFILE}\Downloads
$file = "gpg4win-3.0.3.exe"
# Set $hash to the hash reference from the download page:
$hash = "477f56212ee60cc74e0c5e5cc526cec52a069abff485c89c2d57d1b4b6a54971"
# If you have an MD5 hash: # $hashAlgo="MD5"
$hashAlgo = "SHA256"
$computed_hash = (Get-FileHash -Algorithm $hashAlgo $file).Hash.ToUpper()
if ($computed_hash.CompareTo($hash.ToUpper()) -eq 0 ) {
Write-Output "Hash matches for file $file"
}
else {
Write-Output ("Hash DOES NOT match for file {0}: `nOriginal hash: {1} `nComputed hash: {2}" -f ($file, $hash.ToUpper(), $computed_hash))
}
Đầu ra:
Hash matches for file gpg4win-3.0.3.exe
Dưới đây là ví dụ một dòng lệnh với cả tính toán tổng kiểm tra chính xác của tệp , giống như bạn vừa tải xuống và so sánh nó với tổng kiểm tra đã xuất bản của bản gốc.
Chẳng hạn, tôi đã viết một ví dụ để tải xuống từ dự án Apache JMeter . Trong trường hợp này, bạn có:
3a84491f10fb7b147101cf3926c4a855 * apache-jmeter-4.0.zip
Sau đó, sử dụng lệnh PowerShell này, bạn có thể xác minh tính toàn vẹn của tệp đã tải xuống:
PS C:\Distr> (Get-FileHash .\apache-jmeter-4.0.zip -Algorithm MD5).Hash -eq (Get-Content .\apache-jmeter-4.0.zip.md5 | Convert-String -Example "hash path=hash")
Đầu ra:
True
Giải trình:
Toán hạng đầu tiên của -eq
toán tử là kết quả của việc tính toán tổng kiểm tra cho tệp:
(Get-FileHash .\apache-jmeter-4.0.zip -Algorithm MD5).Hash
Toán hạng thứ hai là giá trị tổng kiểm tra được công bố. Trước tiên, chúng tôi nhận nội dung của tệp.m.m5 là một chuỗi và sau đó chúng tôi trích xuất giá trị băm dựa trên định dạng chuỗi:
Get-Content .\apache-jmeter-4.0.zip.md5 | Convert-String -Example "hash path=hash"
Cả file và file.md5 phải nằm trong cùng một thư mục để lệnh này hoạt động.
Đây là những gì tôi sử dụng để có được giá trị băm nhất quán:
function New-CrcTable {
[uint32]$c = $null
$crcTable = New-Object 'System.Uint32[]' 256
for ($n = 0; $n -lt 256; $n++) {
$c = [uint32]$n
for ($k = 0; $k -lt 8; $k++) {
if ($c -band 1) {
$c = (0xEDB88320 -bxor ($c -shr 1))
}
else {
$c = ($c -shr 1)
}
}
$crcTable[$n] = $c
}
Write-Output $crcTable
}
function Update-Crc ([uint32]$crc, [byte[]]$buffer, [int]$length, $crcTable) {
[uint32]$c = $crc
for ($n = 0; $n -lt $length; $n++) {
$c = ($crcTable[($c -bxor $buffer[$n]) -band 0xFF]) -bxor ($c -shr 8)
}
Write-Output $c
}
function Get-CRC32 {
<#
.SYNOPSIS
Calculate CRC.
.DESCRIPTION
This function calculates the CRC of the input data using the CRC32 algorithm.
.EXAMPLE
Get-CRC32 $data
.EXAMPLE
$data | Get-CRC32
.NOTES
C to PowerShell conversion based on code in https://www.w3.org/TR/PNG/#D-CRCAppendix
Author: Øyvind Kallstad
Date: 06.02.2017
Version: 1.0
.INPUTS
byte[]
.OUTPUTS
uint32
.LINK
https://communary.net/
.LINK
https://www.w3.org/TR/PNG/#D-CRCAppendix
#>
[CmdletBinding()]
param (
# Array of Bytes to use for CRC calculation
[Parameter(Position = 0, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[byte[]]$InputObject
)
$dataArray = @()
$crcTable = New-CrcTable
foreach ($item in $InputObject) {
$dataArray += $item
}
$inputLength = $dataArray.Length
Write-Output ((Update-Crc -crc 0xffffffffL -buffer $dataArray -length $inputLength -crcTable $crcTable) -bxor 0xffffffffL)
}
function GetHash() {
[CmdletBinding()]
param(
[Parameter(Position = 0, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string]$InputString
)
$bytes = [System.Text.Encoding]::UTF8.GetBytes($InputString)
$hasCode = Get-CRC32 $bytes
$hex = "{0:x}" -f $hasCode
return $hex
}
function Get-FolderHash {
[CmdletBinding()]
param(
[Parameter(Position = 0, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string]$FolderPath
)
$FolderContent = New-Object System.Collections.ArrayList
Get-ChildItem $FolderPath -Recurse | Where-Object {
if ([System.IO.File]::Exists($_)) {
$FolderContent.AddRange([System.IO.File]::ReadAllBytes($_)) | Out-Null
}
}
$hasCode = Get-CRC32 $FolderContent
$hex = "{0:x}" -f $hasCode
return $hex.Substring(0, 8).ToLower()
}
Đây là đoạn mã mà tôi đang sử dụng để lấy MD5 cho một chuỗi đã cho:
$text = "text goes here..."
$md5 = [Security.Cryptography.MD5CryptoServiceProvider]::new()
$utf8 = [Text.UTF8Encoding]::UTF8
$bytes= $md5.ComputeHash($utf8.GetBytes($text))
$hash = [string]::Concat($bytes.foreach{$_.ToString("x2")})