Respuestas:
Si el contenido es una cadena:
$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)))
Si el contenido es un archivo:
$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 de PowerShell versión 4, esto es fácil de hacer para los archivos Get-FileHash
listos para usar con el cmdlet:
Get-FileHash <filepath> -Algorithm MD5
Esto es ciertamente preferible ya que evita los problemas que ofrece la primera solución identificada en los comentarios (usa una secuencia, la cierra y admite archivos 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 un chico de Linux nuevo en Powershell, estoy muy molesto con las dificultades que estoy teniendo para obtener una suma md5, que sería simplemente md5sum file.ext
en Linux.
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)))
esto le da un bajo uso de memoria y no hay límite de 2GB .
$stream = [System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
entonces $hash = [System.BitConverter]::ToString($md5.ComputeHash($stream))
luego$stream.Close()
Si está utilizando las Extensiones de comunidad de PowerShell, hay un comando Get-Hash que lo hará fácilmente:
C:\PS> "hello world" | Get-Hash -Algorithm MD5
Algorithm: MD5
Path :
HashString : E42B054623B3799CB71F0883900F2764
Get-FileHash
en Vanilla PowerShell 4.0. Vide TechNet .
Aquí están las dos líneas, simplemente cambie "hola" en la línea # 2:
PS C:\> [Reflection.Assembly]::LoadWithPartialName("System.Web")
PS C:\> [System.Web.Security.FormsAuthentication]::HashPasswordForStoringInConfigFile("hello", "MD5")
Aquí hay una función que uso que maneja rutas relativas y absolutas:
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()
}
}
Gracias a @davor arriba por la sugerencia de usar Open () en lugar de ReadAllBytes () y a @ jpmc26 por la sugerencia de usar un bloque finalmente.
Dispose
llamada debe estar en un finally
bloque.
Otro comando incorporado que se instaló por mucho tiempo en Windows de forma predeterminada desde 2003 es Certutil , que por supuesto también se puede invocar desde PowerShell.
CertUtil -hashfile file.foo MD5
(Advertencia: MD5 debe estar en mayúsculas para máxima robustez)
FipsAlgorithmPolicy
está habilitada.
Hay muchos ejemplos en línea usando ComputeHash (). Mi prueba mostró que esto era muy lento cuando se ejecutaba a través de una conexión de red. El fragmento a continuación funciona mucho más rápido para mí, sin embargo, su kilometraje puede 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
línea? Al resaltador de sintaxis no parece gustarle.
Este sitio tiene un ejemplo: Uso de Powershell para sumas de verificación MD5 . Utiliza el marco .NET para crear una instancia del algoritmo hash MD5 para calcular el hash.
Aquí está el código del artículo, incorporando el comentario 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()
Como se indica en la respuesta aceptada, Get-FileHash
es fácil de usar con archivos, pero también es posible usarlo con cadenas:
$s = "asdf"
Get-FileHash -InputStream ([System.IO.MemoryStream]::New([System.Text.Encoding]::ASCII.GetBytes($s)))
Ahora hay una función Get-FileHash que es muy ú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
Solo cambia SHA384
a MD5
.
El ejemplo es de la documentación oficial de PowerShell 5.1 . La documentación tiene más ejemplos.
Esto se convierte en una línea si descarga File Checksum Integrity Verifier (FCIV) de Microsoft.
Descargué FCIV desde aquí: Disponibilidad y descripción de la utilidad File Checksum Integrity Verifier
Ejecute el siguiente comando. Tenía diez archivos para verificar.
Get-ChildItem WTAM*.tar | % {.\fciv $_.Name}
PowerShell One-Liners (cadena 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("-","")
Esto devolverá un hash MD5 para un archivo en una computadora remota:
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()
}
Aquí hay un bonito ejemplo de impresión que intenta verificar la huella digital SHA256. Descargué gpg4win v3.0.3 usando PowerShell v4 (requiere Get-FileHash
).
Descargue el paquete de https://www.gpg4win.org/download.html , abra PowerShell, tome el hash de la página de descarga y ejecute:
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))
}
Salida:
Hash matches for file gpg4win-3.0.3.exe
Aquí hay un ejemplo de comando de una línea con ambos computando la suma de verificación adecuada del archivo , como la que acaba de descargar, y la comparación con la suma de verificación publicada del original.
Por ejemplo, escribí un ejemplo para descargas del proyecto Apache JMeter . En este caso tienes:
3a84491f10fb7b147101cf3926c4a855 * apache-jmeter-4.0.zip
Luego, utilizando este comando de PowerShell, puede verificar la integridad del archivo descargado:
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")
Salida:
True
Explicación:
El primer operando del -eq
operador es el resultado de calcular la suma de comprobación para el archivo:
(Get-FileHash .\apache-jmeter-4.0.zip -Algorithm MD5).Hash
El segundo operando es el valor de suma de control publicado. Primero obtenemos contenido del archivo.md5, que es una cadena y luego extraemos el valor hash en función del formato de cadena:
Get-Content .\apache-jmeter-4.0.zip.md5 | Convert-String -Example "hash path=hash"
Tanto file como file.md5 deben estar en la misma carpeta para que este comando funcione.
Esto es lo que uso para obtener un valor 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()
}
Aquí está el fragmento que estoy usando para obtener el MD5 para una cadena dada:
$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")})