Respostas:
Se o conteúdo for uma sequência:
$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 o conteúdo for um arquivo:
$someFilePath = "C:\foo.txt"
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes($someFilePath)))
A partir do PowerShell versão 4, é fácil fazer isso com arquivos prontos para uso com o Get-FileHash
cmdlet:
Get-FileHash <filepath> -Algorithm MD5
Isso certamente é preferível, pois evita os problemas que a primeira solução oferece, conforme identificado nos comentários (usa um fluxo, fecha e suporta arquivos grandes).
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."
Como um cara do Linux novato no Powershell, estou muito irritado com as lutas que estou tendo em obter uma soma md5, que seria simplesmente md5sum file.ext
no Linux.
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)))
isso oferece baixo uso de memória e nenhum limite de 2 GB .
$stream = [System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
em seguida, $hash = [System.BitConverter]::ToString($md5.ComputeHash($stream))
em seguida,$stream.Close()
Se você estiver usando as Extensões da comunidade do PowerShell, há um comando Get-Hash que fará isso facilmente:
C:\PS> "hello world" | Get-Hash -Algorithm MD5
Algorithm: MD5
Path :
HashString : E42B054623B3799CB71F0883900F2764
Get-FileHash
no vanilla PowerShell 4.0. Vide TechNet .
Aqui estão as duas linhas, basta alterar "olá" na linha 2:
PS C:\> [Reflection.Assembly]::LoadWithPartialName("System.Web")
PS C:\> [System.Web.Security.FormsAuthentication]::HashPasswordForStoringInConfigFile("hello", "MD5")
Aqui está uma função que eu uso que lida com caminhos relativos e absolutos:
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()
}
}
Agradecemos a @davor acima pela sugestão de usar Open () em vez de ReadAllBytes () e a @ jpmc26 pela sugestão de usar um bloco finalmente.
Dispose
chamada deve estar em um finally
bloco.
Outro comando interno que há muito tempo é instalado no Windows por padrão desde 2003 é o Certutil , que também pode ser chamado pelo PowerShell.
CertUtil -hashfile file.foo MD5
(Advertência: MD5 deve estar em maiúsculas para máxima robustez)
FipsAlgorithmPolicy
está ativada.
Existem muitos exemplos online usando o ComputeHash (). Meus testes mostraram que isso era muito lento ao executar uma conexão de rede. O trecho abaixo é muito mais rápido para mim, no entanto, sua milhagem pode variar:
$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
linha faz? O marcador de sintaxe não parece gostar.
Este site tem um exemplo: Usando o PowerShell para MD5 Checksums . Ele usa a estrutura .NET para instanciar uma instância do algoritmo de hash MD5 para calcular o hash.
Aqui está o código do artigo, incorporando o comentário de 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()
Conforme declarado na resposta aceita, Get-FileHash
é fácil usar com arquivos, mas também é possível usá-lo com strings:
$s = "asdf"
Get-FileHash -InputStream ([System.IO.MemoryStream]::New([System.Text.Encoding]::ASCII.GetBytes($s)))
Agora existe uma função Get-FileHash que é muito útil.
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
Apenas mude SHA384
para MD5
.
O exemplo é da documentação oficial do PowerShell 5.1 . A documentação tem mais exemplos.
Isso se tornará uma linha única se você baixar o FCIV (File Checksum Integrity Verifier) da Microsoft.
Fiz o download do FCIV a partir daqui: Disponibilidade e descrição do utilitário File Checksum Integrity Verifier
Execute o seguinte comando. Eu tinha dez arquivos para verificar.
Get-ChildItem WTAM*.tar | % {.\fciv $_.Name}
Linhas de alinhamento do PowerShell (seqüência de caracteres para 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("-","")
Isso retornará um hash MD5 para um arquivo em um computador 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()
}
Aqui está um exemplo bonito de impressão tentando verificar a impressão digital SHA256. Fiz o download do gpg4win v3.0.3 usando o PowerShell v4 (requer Get-FileHash
).
Faça o download do pacote em https://www.gpg4win.org/download.html , abra o PowerShell, pegue o hash na página de download e execute:
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))
}
Resultado:
Hash matches for file gpg4win-3.0.3.exe
Aqui está um exemplo de comando de uma linha com ambos computando a soma de verificação adequada do arquivo , como você acabou de baixar, e a compara com a soma de verificação publicada do original.
Por exemplo, escrevi um exemplo para downloads do projeto Apache JMeter . Nesse caso, você tem:
3a84491f10fb7b147101cf3926c4a855 * apache-jmeter-4.0.zip
Em seguida, usando este comando do PowerShell, você pode verificar a integridade do arquivo baixado:
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")
Resultado:
True
Explicação:
O primeiro operando do -eq
operador é o resultado da computação da soma de verificação para o arquivo:
(Get-FileHash .\apache-jmeter-4.0.zip -Algorithm MD5).Hash
O segundo operando é o valor publicado da soma de verificação. Primeiramente, obtemos o conteúdo do arquivo.md5, que é uma string e, em seguida, extraímos o valor do hash com base no formato da string:
Get-Content .\apache-jmeter-4.0.zip.md5 | Convert-String -Example "hash path=hash"
O arquivo e o arquivo.md5 devem estar na mesma pasta para este comando funcionar.
Isto é o que eu uso para obter um valor de hash consistente:
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()
}
Aqui está o trecho que estou usando para obter o MD5 para uma determinada sequência:
$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")})