Cara mendapatkan checksum MD5 di PowerShell

179

Saya ingin menghitung checksum MD5 dari beberapa konten. Bagaimana saya melakukan ini di PowerShell?

Luke101
sumber
3
Apa itu "beberapa konten"? file? tali?
vcsjones

Jawaban:

326

Jika kontennya berupa string:

$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)))

Jika konten adalah file:

$someFilePath = "C:\foo.txt"
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes($someFilePath)))

Mulai di PowerShell versi 4, ini mudah dilakukan untuk file di luar kotak dengan Get-FileHashcmdlet:

Get-FileHash <filepath> -Algorithm MD5

Ini tentu saja lebih disukai karena menghindari masalah yang ditawarkan oleh solusi pertama seperti yang diidentifikasi dalam komentar (menggunakan aliran, menutupnya, dan mendukung file besar).

vcsjones
sumber
12
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."Sebagai orang Linux yang baru mengenal Powershell, saya sangat jengkel dengan perjuangan yang saya alami untuk mendapatkan jumlah md5, yang hanya ada md5sum file.extdi Linux.
StockB
@StockB Jawaban Keith di bawah ini mungkin akan menangani ini dengan lebih baik. Saya setuju, ada beberapa kekurangan dengan PowerShell.
vcsjones
5
Saya telah menginstal vanilla PowerShell tanpa ekstensi, jadi saya mogok dan mengunduh klon md5sum baris perintah sebagai gantinya, yang bekerja sangat baik. Saya ingin menyukai barang-barang Microsoft, tetapi saya tidak bisa.
StockB
23
Metode @StockB vcsjones tidak buffered ... = sangat membutuhkan memori untuk file besar. Saya sarankan Anda bekerja dengan stream: $hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)))Ini memberi Anda penggunaan memori rendah dan tidak ada batas 2GB .
Davor Josipovic
20
@davor yang menjaga aliran tetap terbuka untuk jangka waktu yang tidak ditentukan, jadi Anda tidak dapat menghapus file sampai Powershell ditutup. $stream = [System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)maka $hash = [System.BitConverter]::ToString($md5.ComputeHash($stream))kemudian$stream.Close()
Joe Amenta
57

Jika Anda menggunakan PowerShell Community Extensions ada commandlet Get-Hash yang akan melakukan ini dengan mudah:

C:\PS> "hello world" | Get-Hash -Algorithm MD5


Algorithm: MD5


Path       :
HashString : E42B054623B3799CB71F0883900F2764
Keith Hill
sumber
10
Get-Hash berasal dari PowerShell Community Extensions. Ketika Anda tidak bisa atau tidak akan menggunakan paket mereka telah menambahkan cmdlet Get-FileHashdi vanilla PowerShell 4.0. Vide TechNet .
Tomasz Cudziło
Perhatikan bahwa ini (dan mungkin sebagian besar solusi PS) mengkodekan string sebagai UTF-16 (little-endian?).
Christian Mann
Tautan ke PowerShell Community Extensions mengalihkan ke arsip CodePlex (CodePlex ditutup pada 2017). Mungkin berubah menjadi yang GitHub ? (Apakah lokasi master baru di GitHub?)
Peter Mortensen
16

Berikut adalah dua baris, cukup ganti "halo" di baris # 2:

PS C:\> [Reflection.Assembly]::LoadWithPartialName("System.Web")
PS C:\> [System.Web.Security.FormsAuthentication]::HashPasswordForStoringInConfigFile("hello", "MD5")
AvkashChauhan
sumber
1
Hasil ini tidak sama dengan output yang saya dapatkan dengan jawaban yang diterima. Itu menghitung hash dari STRING "hello", bukan dari FILE yang akan ditentukan oleh jalur apa pun yang saya ganti "hello" dengan, benar?
RobertG
1
Benar, tetapi OP tidak meminta file, dan saya datang ke sini untuk mencari solusi string
Chris F Carroll
16

Inilah fungsi yang saya gunakan yang menangani jalur relatif dan absolut:

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()
    }
}

Terima kasih kepada @davor di atas atas saran untuk menggunakan Open () dan bukan ReadAllBytes () dan ke @ jpmc26 untuk saran untuk menggunakan blok akhirnya.

David
sumber
2
Pendekatan ini lebih baik IMHO daripada vcsjones 'dan Keith karena dapat mengambil input file yang lebih besar dari 2GB dan tidak memerlukan ekstensi atau PowerShell 4.0.
Chirag Bhatia - chirag64
1
The Disposepanggilan harus berada dalam finallyblok.
jpmc26
12

Perintah bawaan lain yang telah lama diinstal di Windows secara default sejak 2003 adalah Certutil , yang tentu saja dapat dipanggil dari PowerShell juga.

CertUtil -hashfile file.foo MD5

(Peringatan: MD5 harus dalam semua batas untuk ketahanan maksimal)

danekan
sumber
1
Ini adalah opsi yang baik ketika FipsAlgorithmPolicydiaktifkan.
William John Holden
9

Ada banyak contoh online menggunakan ComputeHash (). Pengujian saya menunjukkan ini sangat lambat ketika menjalankan koneksi jaringan. Cuplikan di bawah ini berjalan lebih cepat untuk saya, namun jarak tempuh Anda mungkin berbeda-beda:

$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
cmcginty
sumber
1
Anda metode mengatasi batas 2Gb dari ReadAllBytes dari jawaban lain, yang persis apa yang saya butuhkan.
Jay
Apa yang dilakukan backtick di write-progresstelepon? Stabilo sintaks sepertinya tidak menyukainya.
mwfearnley
1
@ mwfearnley Backtick memungkinkan kelanjutan garis. blogs.technet.microsoft.com/heyscriptingguy/2015/06/19/…
cmcginty
6

Situs ini memiliki contoh: Menggunakan Powershell untuk Checksums MD5 . Ia menggunakan .NET framework untuk membuat instance dari algoritma hash MD5 untuk menghitung hash.

Berikut kode dari artikel tersebut, menggabungkan komentar 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()
neontapir
sumber
1
Bagus kecuali itu tidak berfungsi untuk file hanya baca! Dibutuhkan $ stream = New-Object System.IO.FileStream ($ Path, [System.IO.FileMode] :: Open, [System.IO.FileAccess] :: Read)
Stephen Connolly
1
Jika tautannya mati, jawabannya akan sangat tidak berguna. stackoverflow.com/help/how-to-answer
Saya dengan Monica
1
Menanggapi apa yang saya anggap downvote Anda, saya memotong dan menempelkan kode dari artikel di sini. Saya tidak melakukan itu tahun lalu, karena saya merasa itu plagiarisme. Menambahkan adaptasi baca-saja Stephen membuat saya merasa itu layak untuk dikirim.
neontapir
@neontapir hanya untuk mengatakan: posting sesuatu kata demi kata (atau dengan adaptasi) hanya plagiarisme jika Anda tidak mengakui sumbernya. Hak cipta (secara hukum atau moral) adalah masalah yang terpisah, tetapi saya tidak akan cenderung mengkhawatirkan hal itu dengan sebagian besar cuplikan kode.
mwfearnley
6

Sebagaimana dinyatakan dalam jawaban yang diterima, Get-FileHashmudah digunakan dengan file, tetapi juga dimungkinkan untuk menggunakannya dengan string:

$s = "asdf"
Get-FileHash -InputStream ([System.IO.MemoryStream]::New([System.Text.Encoding]::ASCII.GetBytes($s)))
Wensveen
sumber
5

Sekarang ada fungsi Get-FileHash yang sangat berguna.

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

Ubah saja SHA384ke MD5.

Contohnya adalah dari dokumentasi resmi PowerShell 5.1 . Dokumentasi memiliki lebih banyak contoh.

Braulio J. Solano
sumber
3

PowerShell One-Liners (string ke hash)

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("-","")
YourWishIsMine
sumber
1

Ini akan mengembalikan hash MD5 untuk file di komputer jarak jauh:

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()
}
Belum Diukuran
sumber
1

Contoh untuk opsi menu klik kanan juga:

[HKEY_CLASSES_ROOT\*\shell\SHA1 PS check\command]
@="C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe -NoExit -Command Get-FileHash -Algorithm SHA1 '%1'"
Niklas E
sumber
0

Ini adalah contoh cantik yang mencoba memverifikasi sidik jari SHA256. Saya mengunduh gpg4win v3.0.3 menggunakan PowerShell v4 (membutuhkan Get-FileHash).

Unduh paket dari https://www.gpg4win.org/download.html , buka PowerShell, ambil hash dari halaman unduh, dan jalankan:

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)) 
}

Keluaran:

Hash matches for file gpg4win-3.0.3.exe
Thomas
sumber
0

Berikut ini adalah contoh satu baris-perintah dengan baik menghitung checksum yang tepat dari berkas , seperti yang baru saja Anda unduh, dan membandingkannya dengan checksum asli yang diterbitkan.

Sebagai contoh, saya menulis contoh untuk mengunduh dari proyek Apache JMeter . Dalam hal ini Anda memiliki:

  1. file biner yang diunduh
  2. checksum dari aslinya yang diterbitkan dalam file.md5 sebagai satu string dalam format:

3a84491f10fb7b147101cf3926c4a855 * apache-jmeter-4.0.zip

Kemudian menggunakan perintah PowerShell ini, Anda dapat memverifikasi integritas file yang diunduh:

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")

Keluaran:

True

Penjelasan:

Operan pertama -eqoperator adalah hasil perhitungan checksum untuk file:

(Get-FileHash .\apache-jmeter-4.0.zip -Algorithm MD5).Hash

Operan kedua adalah nilai checksum yang dipublikasikan. Kami pertama-tama mendapatkan konten file.md5 yang merupakan satu string dan kemudian kami mengekstrak nilai hash berdasarkan format string:

Get-Content .\apache-jmeter-4.0.zip.md5 | Convert-String -Example "hash path=hash"

Baik file dan file.md5 harus berada di folder yang sama untuk pekerjaan perintah ini.

Egor B Eremeev
sumber
0

Inilah yang saya gunakan untuk mendapatkan nilai hash yang konsisten:

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()
}
pengguna2529654
sumber
Dari mana Anda menyalin kode PowerShell? https://communary.net/ ?
Peter Mortensen
0

Berikut ini cuplikan yang saya gunakan untuk mendapatkan MD5 untuk string yang diberikan:

$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")}) 
Peter
sumber