PowerShell'de MD5 sağlama toplamı nasıl alınır?


Yanıtlar:


326

İçerik bir dize ise:

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

İçerik bir dosyaysa:

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

PowerShell sürüm 4'ten başlayarak, Get-FileHashcmdlet ile kutudan çıkan dosyalar için bunu yapmak kolaydır :

Get-FileHash <filepath> -Algorithm MD5

Yorumlarda belirtildiği gibi ilk çözümün sunduğu sorunları önlediği için bu kesinlikle tercih edilir (bir akış kullanır, kapatır ve büyük dosyaları destekler).


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."Powershell'de yeni olan bir Linux adamı olarak, bir md5 toplamı elde ettiğim mücadelelerden çok rahatsızım, ki bu sadece md5sum file.extLinux'ta olacak.
StockB

@StockB Keith'in aşağıdaki cevabı muhtemelen bunu daha iyi ele alacaktır. Katılıyorum, powershell ile ilgili bazı eksiklikler var.
vcsjones

5
Hiçbir uzantıları olmadan yüklü vanilya PowerShell var, bu yüzden bozuldu ve bunun yerine harika çalışan bir komut satırı md5sum klonu indirdim. Microsoft'un eşyalarını beğenmek istiyorum, ama yapamam.
StockB

23
@StockB vcsjones yöntemi arabelleğe alınmaz ... = büyük dosyalar için çok fazla bellek gerektirir. Akışlarla çalışmanızı öneririm: $hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)))Bu size düşük bellek kullanımı sağlar ve 2 GB sınırlaması yoktur .
Davor Josipovic

20
@davor akışı belirsiz bir süre açık tutar, bu nedenle Powershell kapatılıncaya kadar dosyayı silemezsiniz. $stream = [System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)sonra o $hash = [System.BitConverter]::ToString($md5.ComputeHash($stream))zaman$stream.Close()
Joe Amenta

57

PowerShell Topluluk Uzantıları kullanıyorsanız, bunu kolayca yapacak bir Get-Hash komut dosyası vardır:

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


Algorithm: MD5


Path       :
HashString : E42B054623B3799CB71F0883900F2764

10
Get-Hash, PowerShell Topluluk Uzantılarından gelir. Paketi kullanamıyorsanız veya kullanmayacağınız zaman Get-FileHashvanilya PowerShell 4.0'a bir cmdlet eklediler . Vide TechNet .
Tomasz Cudziło

Bu (ve muhtemelen çoğu PS çözümü) dizeyi UTF-16 (küçük endian?) Olarak kodladığını unutmayın.
Christian Mann

PowerShell Topluluk Uzantıları bağlantısı CodePlex arşivine yönlendirir (CodePlex 2017'de kapatılmıştır). Belki GitHub'a geçelim ? (GitHub'daki yeni ana konum mu?)
Peter Mortensen

16

İşte iki satır, sadece # 2 satırındaki "merhaba" yı değiştirin:

PS C:\> [Reflection.Assembly]::LoadWithPartialName("System.Web")
PS C:\> [System.Web.Security.FormsAuthentication]::HashPasswordForStoringInConfigFile("hello", "MD5")

1
Bunun sonucu, kabul edilen cevapla aldığım çıktıya eşit değil. "Merhaba" ile değiştirdiğim herhangi bir yolla tanımlanacak bir DOSYA değil, STRING "merhaba" karmasını hesaplar, doğru mu?
RobertG

1
Doğru, ama OP bir dosya istemedi ve buraya dize çözümü aramaya geldim
Chris F Carroll

16

İşte göreceli ve mutlak yolları işleyen bir fonksiyon:

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

ReadAllBytes () yerine Open () kullanma önerisi için yukarıdaki @davor ve nihayet blok kullanma önerisi için @ jpmc26.


2
Bu yaklaşım, vcsjones ve Keith'lerden daha iyi IMHO'dur, çünkü 2GB'tan büyük dosyaların girişini alabilir ve herhangi bir uzantıya veya PowerShell 4.0'a ihtiyaç duymaz.
Chirag Bhatia - chirag64

1
DisposeArama bir olmalıdır finallybloğun.
jpmc26

12

Varsayılan olarak 2003'e kadar uzanan Windows'ta uzun süredir yüklü olan başka bir yerleşik komut , elbette PowerShell'den de çağrılabilen Certutil'dir .

CertUtil -hashfile file.foo MD5

(Uyarı: MD5 maksimum sağlamlık için tüm başlıklarda olmalıdır)


1
FipsAlgorithmPolicyEtkinleştirildiğinde bu iyi bir seçenektir .
William John Holden

9

ComputeHash () kullanarak çevrimiçi olarak birçok örnek vardır. Testlerim, bir ağ bağlantısı üzerinden çalışırken bunun çok yavaş olduğunu gösterdi. Aşağıdaki snippet benim için çok daha hızlı çalışıyor, ancak kilometreniz değişebilir:

$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

1
Metod, diğer cevaplardan ReadAllBytes 2Gb sınırının üstesinden gelir, ki tam da ihtiyacım olan şey budur.
Jay

Hattaki backtick ne yapıyor write-progress? Sözdizimi vurgulayıcı hoşuna gitmiyor gibi görünüyor.
mwfearnley

1
@mwfearnley Backtick hattın devam etmesini sağlar. blogs.technet.microsoft.com/heyscriptingguy/2015/06/19/…
cmcginty

6

Bu sitenin bir örneği var: MD5 Sağlama Toplamları için Powershell kullanma . Karma çerçevesini hesaplamak için MD5 karma algoritmasının bir örneğini başlatmak için .NET çerçevesini kullanır.

Stephen'ın yorumunu içeren makalenin kodu:

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

1
Sadece salt okunur dosyalar için işe yaramazsa iyi! $ Stream = New-Object System.IO.FileStream ($ Path, [System.IO.FileMode] :: Open, [System.IO.FileAccess] :: Okuma)
Stephen Connolly

1
Bağlantı koparsa, cevap oldukça işe yaramaz olacaktır. stackoverflow.com/help/how-to-answer
Monica ile birlikte oldum

1
Düşündüğün şeye cevaben, buradaki makaledeki kodu kestim ve yapıştırdım. Bunu geçen yıl yapmadım çünkü intihal olduğunu hissettim. Stephen'ın salt okunur uyarlaması eklemek, göndermeye değer olduğunu hissettirdi.
neontapir

@neontapir sadece söylemek gerekirse: kelimesi kelimesine bir şey (ya da uyarlamalar ile) göndermek, sadece kaynağı kabul etmiyorsanız intihal demektir. Telif hakkı (yasal veya ahlaki olarak) ayrı bir konudur, ancak çoğu kod parçacığıyla ilgili endişe etmem.
mwfearnley

6

Kabul edilen cevapta belirtildiği gibi, Get-FileHashdosyalarla kullanımı kolaydır, ancak dizelerle kullanmak da mümkündür:

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

5

Şimdi çok kullanışlı bir Get-FileHash işlevi var.

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

Sadece değiştirmek SHA384için MD5.

Örnek, PowerShell 5.1'in resmi belgelerinden alınmıştır . Belgelerin daha fazla örneği var.



3

PowerShell Tek Katmanları (dizeden karmaya)

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

1

Bu, uzak bilgisayardaki bir dosya için MD5 karmasını döndürür:

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

1

Sağ tıklama menüsü seçeneği için de örnek:

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

0

İşte SHA256 parmak izini doğrulamaya çalışan güzel bir örnek. PowerShell v4 kullanarak gpg4win v3.0.3 sürümünü indirdim (gerektirir Get-FileHash).

Paketi https://www.gpg4win.org/download.html adresinden indirin, PowerShell'i açın, indirme sayfasından karmayı alın ve çalıştırın:

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

Çıktı:

Hash matches for file gpg4win-3.0.3.exe

0

Aşağıda, dosyanın uygun sağlama toplamını hesaplayan tek satırlık bir komut örneği verilmiştir yeni indirdiğiniz gibi de orijinalin yayınlanan sağlama toplamıyla karşılaştıran .

Örneğin , Apache JMeter projesinden indirmeler için bir örnek yazdım . Bu durumda:

  1. indirilen ikili dosya
  2. file.md5 dosyasında biçiminde bir dize olarak yayınlanan orijinalin sağlama toplamı :

3a84491f10fb7b147101cf3926c4a855 * apache-jmeter-4.0.zip

Ardından bu PowerShell komutunu kullanarak indirilen dosyanın bütünlüğünü doğrulayabilirsiniz:

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

Çıktı:

True

Açıklama:

İşlecin ilk işleneni -eq, dosyanın sağlama toplamının hesaplanmasının bir sonucudur:

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

İkinci işlenen yayınlanan sağlama toplamı değeridir. Öncelikle bir dize olan file.md5 dosyasının içeriğini alırız ve sonra dize biçimine göre karma değerini çıkarırız:

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

Bu komutun çalışması için hem dosya hem de dosya.md5 aynı klasörde olmalıdır.


0

Tutarlı bir karma değer elde etmek için kullandığım şey budur:

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

PowerShell kodunu nereden kopyaladınız? https://communary.net/ ?
Peter Mortensen

0

İşte belirli bir dize için MD5 almak için kullanıyorum snippet'i:

$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")}) 
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.