Réponses:
Si le contenu est une chaîne:
$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 le contenu est un fichier:
$someFilePath = "C:\foo.txt"
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes($someFilePath)))
À partir de PowerShell version 4, cela est facile à faire pour les fichiers prêts à l' Get-FileHash
emploi avec l' applet de commande:
Get-FileHash <filepath> -Algorithm MD5
C'est certainement préférable car cela évite les problèmes qu'offre la première solution tels qu'identifiés dans les commentaires (utilise un flux, le ferme et prend en charge les gros fichiers).
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."
En tant que nouveau venu de Linux sur Powershell, je suis très ennuyé par les difficultés que j'ai pour obtenir une somme md5, qui serait simplement md5sum file.ext
sous Linux.
$hash = [System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)))
cela vous donne une faible utilisation de la mémoire et aucune limite de 2 Go .
$stream = [System.IO.File]::Open("$someFilePath",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
puis $hash = [System.BitConverter]::ToString($md5.ComputeHash($stream))
puis$stream.Close()
Si vous utilisez les extensions de communauté PowerShell, il existe une commande Get-Hash qui le fera facilement:
C:\PS> "hello world" | Get-Hash -Algorithm MD5
Algorithm: MD5
Path :
HashString : E42B054623B3799CB71F0883900F2764
Get-FileHash
dans vanilla PowerShell 4.0. Vide TechNet .
Voici les deux lignes, changez simplement "bonjour" à la ligne 2:
PS C:\> [Reflection.Assembly]::LoadWithPartialName("System.Web")
PS C:\> [System.Web.Security.FormsAuthentication]::HashPasswordForStoringInConfigFile("hello", "MD5")
Voici une fonction que j'utilise qui gère les chemins relatifs et absolus:
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()
}
}
Merci à @davor ci-dessus pour la suggestion d'utiliser Open () au lieu de ReadAllBytes () et à @ jpmc26 pour la suggestion d'utiliser un bloc finally.
Dispose
appel doit être dans un finally
bloc.
Une autre commande intégrée qui est installée depuis longtemps dans Windows par défaut et qui remonte à 2003 est Certutil , qui peut bien sûr être également appelée à partir de PowerShell.
CertUtil -hashfile file.foo MD5
(Attention: MD5 doit être en majuscules pour une robustesse maximale)
FipsAlgorithmPolicy
est activé.
Il existe de nombreux exemples en ligne utilisant ComputeHash (). Mes tests ont montré que c'était très lent lors de l'exécution sur une connexion réseau. L'extrait ci-dessous est beaucoup plus rapide pour moi, mais votre kilométrage peut varier:
$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
ligne? Le surligneur de syntaxe ne semble pas l'apprécier.
Ce site a un exemple: Utilisation de Powershell pour les sommes de contrôle MD5 . Il utilise le framework .NET pour instancier une instance de l'algorithme de hachage MD5 afin de calculer le hachage.
Voici le code de l'article, intégrant le commentaire 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()
Comme indiqué dans la réponse acceptée, Get-FileHash
est facile à utiliser avec des fichiers, mais il est également possible de l'utiliser avec des chaînes:
$s = "asdf"
Get-FileHash -InputStream ([System.IO.MemoryStream]::New([System.Text.Encoding]::ASCII.GetBytes($s)))
Il existe maintenant une fonction Get-FileHash qui est très pratique.
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
Changez simplement SHA384
pour MD5
.
L'exemple provient de la documentation officielle de PowerShell 5.1 . La documentation a plus d'exemples.
Cela devient une ligne unique si vous téléchargez le vérificateur d'intégrité de la somme de contrôle des fichiers (FCIV) de Microsoft.
J'ai téléchargé FCIV à partir d'ici: Disponibilité et description de l'utilitaire File Checksum Integrity Verifier
Exécutez la commande suivante. J'avais dix fichiers à vérifier.
Get-ChildItem WTAM*.tar | % {.\fciv $_.Name}
PowerShell One-Liners (chaîne en hachage)
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("-","")
Cela renverra un hachage MD5 pour un fichier sur un ordinateur distant:
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()
}
Voici un joli exemple d'impression tentant de vérifier l'empreinte digitale SHA256. J'ai téléchargé gpg4win v3.0.3 en utilisant PowerShell v4 (nécessite Get-FileHash
).
Téléchargez le package à partir de https://www.gpg4win.org/download.html , ouvrez PowerShell, récupérez le hachage sur la page de téléchargement et exécutez:
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))
}
Production:
Hash matches for file gpg4win-3.0.3.exe
Voici un exemple de commande en une ligne avec à la fois le calcul de la somme de contrôle appropriée du fichier , comme vous venez de le télécharger, et la comparaison avec la somme de contrôle publiée de l'original.
Par exemple, j'ai écrit un exemple de téléchargement à partir du projet Apache JMeter . Dans ce cas, vous avez:
3a84491f10fb7b147101cf3926c4a855 * apache-jmeter-4.0.zip
Ensuite, à l'aide de cette commande PowerShell, vous pouvez vérifier l'intégrité du fichier téléchargé:
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")
Production:
True
Explication:
Le premier opérande d' -eq
opérateur est le résultat du calcul de la somme de contrôle du fichier:
(Get-FileHash .\apache-jmeter-4.0.zip -Algorithm MD5).Hash
Le deuxième opérande est la valeur de la somme de contrôle publiée. Nous obtenons d'abord le contenu du fichier.md5 qui est une chaîne, puis nous extrayons la valeur de hachage en fonction du format de la chaîne:
Get-Content .\apache-jmeter-4.0.zip.md5 | Convert-String -Example "hash path=hash"
Le fichier et le fichier.md5 doivent être dans le même dossier pour que cette commande fonctionne.
C'est ce que j'utilise pour obtenir une valeur de hachage cohérente:
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()
}
Voici l'extrait que j'utilise pour obtenir le MD5 pour une chaîne donnée:
$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")})