Risposte:
Se il contenuto è una stringa:
$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)))
Se il contenuto è un file:
$someFilePath = "C:\foo.txt"
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes($someFilePath)))
A partire da PowerShell versione 4, questo è facile da fare per i file Get-FileHash
pronti all'uso con il cmdlet:
Get-FileHash <filepath> -Algorithm MD5
Questo è certamente preferibile poiché evita i problemi che la prima soluzione offre come identificati nei commenti (usa un flusso, lo chiude e supporta file di grandi dimensioni).
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."
Come un ragazzo Linux nuovo a Powershell, sono molto infastidito dalle difficoltà che sto avendo per ottenere una somma md5, che sarebbe semplicemente md5sum file.ext
su Linux.
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)))
questo ti dà un basso utilizzo della memoria e nessun limite di 2 GB .
$stream = [System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
poi $hash = [System.BitConverter]::ToString($md5.ComputeHash($stream))
poi$stream.Close()
Se si utilizzano le estensioni della community di PowerShell, è disponibile un commandlet Get-Hash che lo farà facilmente:
C:\PS> "hello world" | Get-Hash -Algorithm MD5
Algorithm: MD5
Path :
HashString : E42B054623B3799CB71F0883900F2764
Get-FileHash
in PowerShell 4.0 vaniglia. Vide TechNet .
Ecco le due righe, basta cambiare "ciao" nella riga # 2:
PS C:\> [Reflection.Assembly]::LoadWithPartialName("System.Web")
PS C:\> [System.Web.Security.FormsAuthentication]::HashPasswordForStoringInConfigFile("hello", "MD5")
Ecco una funzione che uso che gestisce percorsi relativi e assoluti:
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()
}
}
Grazie a @davor sopra per il suggerimento di usare Open () invece di ReadAllBytes () e @ jpmc26 per il suggerimento di usare un blocco finally.
Dispose
chiamata dovrebbe essere in un finally
blocco.
Un altro comando integrato installato da tempo in Windows per impostazione predefinita risalente al 2003 è Certutil , che ovviamente può essere invocato anche da PowerShell.
CertUtil -hashfile file.foo MD5
(Avvertenza: MD5 dovrebbe essere in tutti i tappi per la massima robustezza)
FipsAlgorithmPolicy
è abilitata.
Ci sono molti esempi online usando ComputeHash (). I miei test hanno dimostrato che ciò è stato molto lento durante l'esecuzione su una connessione di rete. Lo snippet di seguito è molto più veloce per me, tuttavia il tuo chilometraggio può variare:
$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
linea? L'evidenziatore della sintassi non sembra gradirlo.
Questo sito ha un esempio: utilizzo di Powershell per checksum MD5 . Utilizza il framework .NET per istanziare un'istanza dell'algoritmo hash MD5 per calcolare l'hash.
Ecco il codice dell'articolo, che incorpora il commento di 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()
Come indicato nella risposta accettata, Get-FileHash
è facile da usare con i file, ma è anche possibile usarlo con le stringhe:
$s = "asdf"
Get-FileHash -InputStream ([System.IO.MemoryStream]::New([System.Text.Encoding]::ASCII.GetBytes($s)))
Ora c'è una funzione Get-FileHash che è molto utile.
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
Passa SHA384
a MD5
.
L'esempio è tratto dalla documentazione ufficiale di PowerShell 5.1 . La documentazione ha più esempi.
Questo diventa un liner se scarichi File Checksum Integrity Verifier (FCIV) da Microsoft.
Ho scaricato FCIV da qui: disponibilità e descrizione dell'utilità File Checksum Integrity Verifier
Esegui il seguente comando. Avevo dieci file da controllare.
Get-ChildItem WTAM*.tar | % {.\fciv $_.Name}
PowerShell One-Liners (da stringa a 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("-","")
Ciò restituirà un hash MD5 per un file su un computer remoto:
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()
}
Ecco un esempio di stampa piuttosto che tenta di verificare l'impronta digitale SHA256. Ho scaricato gpg4win v3.0.3 usando PowerShell v4 (richiede Get-FileHash
).
Scarica il pacchetto da https://www.gpg4win.org/download.html , apri PowerShell, prendi l'hash dalla pagina di download ed esegui:
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))
}
Produzione:
Hash matches for file gpg4win-3.0.3.exe
Ecco un esempio di comando a una riga con entrambi che calcolano il checksum corretto del file , come appena scaricato, sia il confronto con il checksum pubblicato dell'originale.
Ad esempio, ho scritto un esempio per i download dal progetto Apache JMeter . In questo caso hai:
3a84491f10fb7b147101cf3926c4a855 * apache-jmeter-4.0.zip
Quindi, utilizzando questo comando PowerShell, è possibile verificare l'integrità del file scaricato:
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")
Produzione:
True
Spiegazione:
Il primo operando di -eq
operatore è il risultato del calcolo del checksum per il file:
(Get-FileHash .\apache-jmeter-4.0.zip -Algorithm MD5).Hash
Il secondo operando è il valore di checksum pubblicato. Innanzitutto otteniamo il contenuto del file.md5 che è una stringa e quindi estraiamo il valore hash in base al formato stringa:
Get-Content .\apache-jmeter-4.0.zip.md5 | Convert-String -Example "hash path=hash"
Sia file che file.md5 devono trovarsi nella stessa cartella per questo comando.
Questo è quello che uso per ottenere un valore hash coerente:
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()
}
Ecco lo snippet che sto usando per ottenere MD5 per una determinata stringa:
$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")})