2017-02-10 572 views
2

我正在寫一個批處理文件,我需要它來驗證文件的MD5散列,然後繼續處理腳本。例如:在批處理中驗證MD5哈希值?

@echo off 
if MD5 equ 79054025255fb1a26e4bc422aef54eb4 (
     echo MD5 identical! 
) else (
     echo MD5 does not match. 
) 

謝謝!

回答

3

標準的Windows工具CERTUTIL可用於生成MD5(及其他)散列。

例如:

certutil -hashfile yourFile MD5 

然而,輸出(之前的版本的Windows 10)將不會被格式化爲連續的十六進制數字單個字符串。

npocmaka在他的批處理實用程序中使用了CERTUTIL來生成單個MD5字符串。

以類似的方式,我也用CERTUTIL我的工具:HASHSUM.BAT - Unix工具一樣的md5sum,shasum一個批處理文件,仿真等

HASHSUM.BAT確實比計算MD5單個文件多,但它也很方便使用你想要的東西。

例如:

echo 79054025255fb1a26e4bc422aef54eb4 yourFileName | hashsum /c /ns 
REM - There must be exactly two spaces between the MD5 hash and the filename 

會產生輸出像

---------- <stdin> ---------- 
OK: yourFileName 

---------- <stdin> ---------- 
*FAILED: yourFileName 

或者你可以把輸出的總量控制

echo 79054025255fb1a26e4bc422aef54eb4 yourFileName | hashsum /c /q && (
    echo MD5 identical! 
) || (
    echo MD5 does not match. 
) 

或者,如果你真的想要的,你可以自己捕捉的MD5值,並做比較:

for /f %%N in ('hashsum /a md5 yourFileName') do set "MD5=%%N" 
if %MD5% equ 79054025255fb1a26e4bc422aef54eb4 (
    echo MD5 identical! 
) else (
    echo MD5 does not match. 
) 

我張貼的代碼爲當前版本HASHSUM.BAT的1.4,但我不承諾保持此代碼最新。我建議你從DOSTIPS site where I originally posted it獲得代碼。在那裏你可以看到所有HASHSUM.BAT功能的更全面的討論,以及一些更多的使用例子。

@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment 
@goto :Batch 

::::HASHNUM.BAT history 
:::: 
:::: v1.4 2016-12-26 - Convert /A value to upper case because some Windows 
::::     versions are case sensitive. Also improve JScript file 
::::     read performance by reading 1000000 bytes instead of 1. 
:::: v1.3 2016-12-17 - Bug fixes: Eliminate unwanted \r\n from temp file by 
::::     reading stdin with JScript instead of FINDSTR. 
::::     Fix help to ignore history. 
:::: v1.2 2016-12-07 - Bug fixes: Exclude FORFILES directories and 
::::     correct setlocal/endlocal management in :getOptions 
:::: v1.1 2016-12-06 - New /V option, and minor bug fixes. 
:::: v1.0 2016-12-05 - Original release 
::: 
:::HASHSUM [/Option [Value]]... [File]... 
::: 
::: Print or check file hashes using any of the following standard 
::: hash algorithms: MD5, SHA1, SHA256, SHA384, or SHA512. 
::: 
::: HASHSUM always does a binary read - \r\n is never converted to \n. 
::: 
::: In the absence of /C, HASHSUM computes the hash for each File, and writes 
::: a manifest of the results. Each line of output consists of the hash value, 
::: followed by a space and an asterisk, followed by the File name. The default 
::: hash alogrithm is sha256. File may include wildcards, but must not contain 
::: any path information. 
::: 
::: If File is not given, then read from standard input and write the hash 
::: value only, without the trailing space, asterisk, or file name. 
::: 
::: Options: 
::: 
::: /? - Prints this help information to standard output. 
::: 
::: /?? - Prints paged help using MORE. 
::: 
::: /V - Prints the HASHNUM.BAT version. 
::: 
::: /A Algorithm 
::: 
:::   Specifies one of the following hash algorithms: 
:::   MD5, SHA1, SHA256, SHA384, SHA512 
::: 
::: /P RootPath 
::: 
:::   Specifies the root path for operations. 
:::   The default is the current directory. 
::: 
::: /S - Recurse into all Subdirectories. The relative path from the root 
:::   is included in the file name output. 
:::   This option is ignored if used with /C. 
::: 
::: /I - Include the RootPath in the file name output. 
:::   This option is ignored if used with /C. 
::: 
::: /T - Writes a space before each file name, rather than an 
:::   asterisk. However, files are still read in binary mode. 
:::   This option is ignored if used with /C. 
::: 
::: /C - Read hash values and file names from File (the manifest), and verify 
:::   that local files match. File may include path information with /C. 
::: 
:::   If File is not given, then read hash and file names from standard 
:::   input. Each line of input must have a hash, followed by two spaces, 
:::   or a space and an asterisk, followed by a file name. 
::: 
:::   If /A is not specified, then the algorithm is determined by the 
:::   File extension. If the extension is not a valid algorithm, then 
:::   the algorithm is derived based on the length of the first hash 
:::   within File. 
::: 
:::   Returns ERRORLEVEL 1 if any manifest File is not found or is invalid, 
:::   or if any local file is missing or does not match the hash value in 
:::   the manifest. If all files are found and match, then returns 0. 
::: 
::: /NE - (No Errors) Suppresses error messages when using /C. 
::: 
::: /NM - (No Matches) Suppresses listing of matching files when using /C. 
::: 
::: /NS - (No Summary) Suppresses summary information when using /C. 
::: 
::: /Q - (Quiet) Suppresses all output when using /C. 
::: 
:::HASHSUM.BAT version 1.4 was written by Dave Benham 
:::maintained at http://www.dostips.com/forum/viewtopic.php?f=3&t=7592 

============= :Batch portion =========== 
@echo off 
setlocal disableDelayedExpansion 

:: Define options 
set "options= /A:"" /C: /I: /P:"" /S: /T: /?: /??: /NE: /NM: /NS: /Q: /V: " 

:: Set default option values 
for %%O in (%options%) do for /f "tokens=1,* delims=:" %%A in ("%%O") do set "%%A=%%~B" 
set "/?=" 

:getOptions 
if not "%~1"=="" (
    set "test=%~1" 
    setlocal enableDelayedExpansion 
    if "!test:~0,1!" neq "/" endlocal & goto :endOptions 
    set "test=!options:*%~1:=! " 
    if "!test!"=="!options! " (
     endlocal 
     >&2 echo Invalid option %~1 
     exit /b 1 
) else if "!test:~0,1!"==" " (
     endlocal 
     set "%~1=1" 
) else (
     endlocal 
     set "%~1=%~2" 
     shift /1 
) 
    shift /1 
    goto :getOptions 
) 
:endOptions 

:: Display paged help 
if defined /?? (
    (for /f "delims=: tokens=*" %%A in ('findstr "^:::[^:] ^:::$" "%~f0"') do @echo(%%A)|more /e 
    exit /b 0 
) 2>nul 

:: Display help 
if defined /? (
    for /f "delims=: tokens=*" %%A in ('findstr "^:::[^:] ^:::$" "%~f0"') do echo(%%A 
    exit /b 0 
) 

:: Display version 
if defined /v (
    for /f "delims=: tokens=*" %%A in ('findstr /ric:"^:::%~nx0 version" "%~f0"') do echo(%%A 
    exit /b 0 
) 

:: If no file specified, then read stdin and write to a temp file 
set "tempFile=" 
if "%~1" equ "" set "tempFile=%~nx0.%time::=_%.%random%.tmp" 
if defined tempFile cscript //nologo //E:JScript "%~f0" "%temp%\%tempFile%" 

if defined /P cd /d "%/P%" || exit /b 1 
if defined /C goto :check 

:generate 
if defined tempFile cd /d "%temp%" 
if not defined /A set "/A=sha256" 
if defined /S set "/S=/s" 
if defined /T (set "/T= ") else set "/T=*" 
call :defineEmpty 
if not defined /P goto :generateLoop 
if not defined /I goto :generateLoop 
if "%/P:~-1%" equ "\" (set "/I=%/P:\=/%") else set "/I=%/P:\=/%/" 
set "rtn=0" 

:generateLoop 
(
    for /f "delims=" %%F in (
    'forfiles %/s% /m "%tempFile%%~1" /c "cmd /c if @isdir==FALSE echo @relpath" 2^>nul' 
) do for /f "delims=" %%A in (
    'certutil.exe -hashfile %%F %/A% ^| find /v ":" ^|^| if %%~zF gtr 0 (echo X^) else echo %empty%' 
) do (
    set "file=%%~F" 
    set "hash=%%A" 
    setlocal enableDelayedExpansion 
    set "file=!file:~2!" 
    if defined tempFile (
     if !hash! equ X (
     set "rtn=1" 
     echo ERROR 
    ) else echo !hash: =! 
    ) else (
     if !hash! equ X (
     set "rtn=1" 
     echo ERROR: !/I!!file! 
    ) else echo !hash: =! !/T!!/I!!file:\=/! 
    ) 
    endlocal 
) 
) || (
    set "rtn=1" 
    echo MISSING: %/T%%1 
) 
shift /1 
if "%~1" neq "" goto :generateLoop 
if defined tempFile del "%tempFile%" 
exit /b %rtn% 

:check 
if defined /Q for %%V in (/NE /NM /NS) do set "%%V=1" 
set /a manifestCnt=missingManifestCnt=invalidCnt=missingCnt=failCnt=okCnt=0 
:checkLoop 
set "alogorithm=%/A%" 
if defined tempFile set "tempFile=%temp%\%tempFile%" 
for %%F in ("%tempFile%%~1") do call :checkFile "%%~F" 
if defined tempFile del "%tempFile%" 
shift /1 
if "%~1" neq "" goto :checkLoop 

if not defined /NS (
    echo ========== SUMMARY ========== 
    echo Total manifests = %manifestCnt% 
    echo Matched files  = %okCnt% 
    echo(
    if %missingManifestCnt% gtr 0 echo Missing manifests = %missingManifestCnt% 
    if %invalidCnt% gtr 0   echo Invalid manifests = %invalidCnt% 
    if %missingCnt% gtr 0   echo Missing files  = %missingCnt% 
    if %failCnt% gtr 0   echo Failed files  = %failCnt% 
) 
set /a "1/(missingManifestCnt+invalidCnt+missingCnt+failCnt)" 2>nul && (
    echo(
    exit /b 1 
) 
exit /b 0 

:checkFile 
set /a manifestCnt+=1 
if not defined /Q if defined tempfile (echo ---------- ^<stdin^> ----------) else echo ---------- %1 ---------- 
if not defined algorithm set "/A=" 
set "src=%~1" 
if not defined /A echo *.md5*.sha1*.sha256*.sha384*.sha512*|find /i "*%~x1*" >nul && for /f "delims=." %%A in ("%~x1") do set "/A=%%A" 
findstr /virc:"^[abcdef][abcdef]* [ *][^ *?|<>]" %1 >nul 2>nul && (
    if not defined /NE if defined tempFile (echo *INVALID: ^<stdin^>) else echo *INVALID: %1 
    set /a invalidCnt+=1 
    exit /b 
) 
(
    for /f "usebackq tokens=1* delims=* " %%A in (%1) do (
    set "hash0=%%A" 
    set "file=%%B" 
    if defined /A (call :defineEmpty) else call :determineFormat 
    setlocal enableDelayedExpansion 
    set "file=!file:/=\!" 
    for /f "tokens=1* delims=" %%C in (
     'certutil.exe -hashfile "!file!" !/A! ^| find /v ":" ^|^| if exist "!file!" (echo !empty!^) else echo X' 
    ) do set "hash=%%C" 
    if /i "!hash0!" equ "!hash: =!" (
     if not defined /NM echo OK: !file! 
     endlocal 
     set /a okCnt+=1 
    ) else if !hash! equ X (
     if not defined /NE echo *MISSING: !file! 
     endlocal 
     set /a missingCnt+=1 
    ) else (
     if not defined /NE echo *FAILED: !file! 
     endlocal 
     set /a failCnt+=1 
    ) 
) 
) 2>nul || (
    if not defined /NE echo *MISSING: %1 
    set /a missingManifestCnt+=1 
) 
exit /b 

:determineFormat 
if "%hash0:~127%" neq "" (
    set "/A=SHA512" 
) else if "%hash0:~95%" neq "" (
    set "/A=SHA384" 
) else if "%hash0:~63%" neq "" (
    set "/A=SHA256" 
) else if "%hash0:~39%" neq "" (
    set "/A=SHA1" 
) else set "/A=MD5" 

:defineEmpty 
if /i "%/A%"=="md5" (
    set "empty=d41d8cd98f00b204e9800998ecf8427e" 
    set "/A=MD5" 
) else if /i "%/A%"=="sha1" (
    set "empty=da39a3ee5e6b4b0d3255bfef95601890afd80709" 
    set "/A=SHA1" 
) else if /i "%/A%"=="sha256" (
    set "empty=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" 
    set "/A=SHA256" 
) else if /i "%/A%"=="sha384" (
    set "empty=38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b" 
    set "/A=SHA384" 
) else if /i "%/A%"=="sha512" (
    set "empty=cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" 
    set "/A=SHA512" 
) else (
    echo ERROR: Invalid /A algorithm>&2 
    (goto) 2>nul&exit /b 1 
) 
exit /b 


************* JScript portion **********/ 
var fso = new ActiveXObject("Scripting.FileSystemObject"); 
var out = fso.OpenTextFile(WScript.Arguments(0),2,true); 
var chr; 
while(!WScript.StdIn.AtEndOfStream) { 
    chr=WScript.StdIn.Read(1000000); 
    out.Write(chr); 
} 
1

嘗試MD5.BAT

set "file=c:\myfile.ext" 
call md5.bat "%file%" md5 

if "%md5%" equ "79054025255fb1a26e4bc422aef54eb4" (
     echo MD5 identical! 
) else (
     echo MD5 does not match. 
)