231 votes

Comment obtenir une somme de contrôle MD5 dans PowerShell ?

Je voudrais calculer un MD5 somme de contrôle de certains contenus. Comment puis-je faire cela dans PowerShell ?

6 votes

Qu'est-ce qu'un "contenu" ? Un fichier ? Une chaîne de caractères ?

413voto

vcsjones Points 51910

À partir de la version 4 de PowerShell, cette opération est facile à réaliser pour les fichiers à l'aide de la commande Get-FileHash cmdlet :

Get-FileHash <filepath> -Algorithm MD5

C'est certainement préférable car cela évite les problèmes que la solution pour l'ancien PowerShell offre comme indiqué dans les commentaires (utilise un flux, le ferme, et supporte les gros fichiers).

Si le contenu est une chaîne de caractères :

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

Pour les anciennes versions de PowerShell

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

14 votes

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 Linuxien novice dans l'utilisation de Powershell, je suis très ennuyé par les difficultés que j'ai à obtenir une somme md5, qui serait tout simplement md5sum file.ext sur Linux.

1 votes

@StockB La réponse de Keith ci-dessous va probablement mieux gérer ce problème. Je suis d'accord, il y a quelques lacunes avec powershell.

7 votes

J'ai installé vanilla PowerShell sans extensions, alors j'ai craqué et téléchargé un clone de md5sum en ligne de commande à la place, qui fonctionne très bien. Je veux aimer les produits de Microsoft, mais je n'y arrive pas.

58voto

Keith Hill Points 73162

Si vous utilisez le Extensions communautaires PowerShell il existe une commandlet Get-Hash qui permet de le faire facilement :

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

Algorithm: MD5

Path       :
HashString : E42B054623B3799CB71F0883900F2764

13 votes

Get-Hash provient de PowerShell Community Extensions. Lorsque vous ne pouvez pas ou ne voulez pas utiliser le paquet, ils ont ajouté une cmdlet Get-FileHash dans vanilla PowerShell 4.0. Vidéo : TechNet .

0 votes

Notez que cette solution (et probablement la plupart des solutions PS) encode la chaîne en UTF-16 (little-endian ?).

0 votes

Le lien vers les extensions de la communauté PowerShell redirige vers les archives de CodePlex (CodePlex a fermé en 2017). Peut-être faudrait-il modifier le GitHub one ? (Le nouvel emplacement du master est-il sur GitHub ?)

20voto

David Points 268

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.

2 votes

Cette approche est meilleure, à mon avis, que celle de vcsjones et de Keith parce qu'elle peut prendre en entrée des fichiers de plus de 2 Go et qu'elle n'a pas besoin d'extensions ou de PowerShell 4.0.

3 votes

Le site Dispose doit être dans un finally bloc.

19voto

AvkashChauhan Points 14572

Voici les deux lignes, changez juste "hello" dans la ligne #2 :

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

1 votes

Le résultat de cette opération ne correspond pas à la sortie que j'obtiens avec la réponse acceptée. Il calcule le hachage de la chaîne "hello", et non d'un fichier qui serait défini par n'importe quel chemin avec lequel je remplacerais "hello", correct ?

3 votes

C'est vrai, mais l'OP n'a pas demandé de fichier, et je suis venu ici pour chercher une solution à la chaîne.

10voto

Casey Points 19286

Il existe de nombreux exemples en ligne utilisant ComputeHash(). Mes tests ont montré que cette méthode était très lente lorsqu'elle était exécutée sur une connexion réseau. L'extrait ci-dessous fonctionne beaucoup plus rapidement pour moi, mais votre expérience 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

1 votes

Votre méthode permet de surmonter la limite de 2Gb de ReadAllBytes des autres réponses, ce qui est exactement ce dont j'avais besoin.

0 votes

Que fait le backtick sur le write-progress fait-elle ? Le surligneur syntaxique ne semble pas l'apprécier.

1 votes

@mwfearnley Le backtick permet de poursuivre la ligne. blogs.technet.microsoft.com/heyscriptingguy/2015/06/19/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X