Как ни странно, но я не могу найти портативное приложение для вычисления одного отдельного хэша (типа, типа SHA256, SHA512, Whirlpool, SHA3?) для выбранного файла! Это все, что я нашел:
Есть Multihasher , но он не поддерживает некоторые важные типы хэшей, такие как SHA-3 и Whirlpool.
В HashTab есть все, что мне нужно, но... как жаль! Это устанавливаемая dll для системной интеграции без портативного приложения.
На самом деле, я немного в шоке от этой ситуации. Я никогда не ожидал, что не смогу найти подходящее программное обеспечение для такой распространенной проблемы.
Некоторое время назад я сделал для себя небольшую утилиту командной строки. Загрузите его, если вы найдете его полезным.
Программа никогда ранее не публиковалась (и не подписывалась), поэтому может быть определена как вредоносное ПО (по крайней мере , так говорит VirusTotal ).
Он написан на Python 3. Это источник:
# -*- coding: utf-8 -*-
import os.path
import pprint
import time
import json
import sys
import re
import hashlib
import zlib
import sha3 # This adds sha_3 functions to the hashlib module, install with 'pip install pysha3'
class crc32(object):
name = 'crc32'
digest_size = 4
block_size = 1
def __init__(self, arg=''):
arg = arg.encode()
self.__digest = 0
self.update(arg)
def copy(self):
copy = super(self.__class__, self).__new__(__class__)
copy.__digest = self.__digest
return copy
def digest(self):
return self.__digest
def hexdigest(self):
return '{:08x}'.format(self.__digest)
def update(self, arg):
self.__digest = zlib.crc32(arg, self.__digest) & 0xffffffff
hashlib.crc32 = crc32
def md4File(path, block_size=256*128):
md4 = hashlib.new("md4")
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
md4.update(chunk)
return md4.hexdigest()
def md5File(path, block_size=256*128):
md5 = hashlib.md5()
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
md5.update(chunk)
return md5.hexdigest()
def sha1File(path, block_size=256*128):
sha1 = hashlib.sha1()
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
sha1.update(chunk)
return sha1.hexdigest()
def crc32File(path, block_size=256*128):
crc32 = hashlib.crc32()
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
crc32.update(chunk)
return crc32.hexdigest()
def sha224File(path, block_size=256*128):
sha224 = hashlib.sha224()
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
sha224.update(chunk)
return sha224.hexdigest()
def sha256File(path, block_size=256*128):
sha256 = hashlib.sha224()
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
sha256.update(chunk)
return sha256.hexdigest()
def sha384File(path, block_size=256*128):
sha384 = hashlib.sha384()
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
sha384.update(chunk)
return sha384.hexdigest()
def sha512File(path, block_size=256*128):
sha512 = hashlib.sha512()
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
sha512.update(chunk)
return sha512.hexdigest()
def ripemd160File(path, block_size=256*128):
rmd160 = hashlib.new("ripemd160")
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
rmd160.update(chunk)
return rmd160.hexdigest()
def dsaFile(path, block_size=256*128):
dsa = hashlib.new("dsa")
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
dsa.update(chunk)
return dsa.hexdigest()
def whirlpoolFile(path, block_size=256*128):
wrp = hashlib.new("whirlpool")
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
wrp.update(chunk)
return wrp.hexdigest()
def sha3_224File(path, block_size=256*128):
sha3_224 = hashlib.sha3_224()
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
sha3_224.update(chunk)
return sha3_224.hexdigest()
def sha3_256File(path, block_size=256*128):
sha3_256 = hashlib.sha3_256()
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
sha3_256.update(chunk)
return sha3_256.hexdigest()
def sha3_384File(path, block_size=256*128):
sha3_384 = hashlib.sha3_384()
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
sha3_384.update(chunk)
return sha3_384.hexdigest()
def sha3_512File(path, block_size=256*128):
sha3_512 = hashlib.sha3_512()
with open(path,'rb') as f:
for chunk in iter(lambda: f.read(block_size), b''):
sha3_512.update(chunk)
return sha3_512.hexdigest()
def getJson(results):
jdump = json.dumps(results, ensure_ascii=False)
return re.sub('[^\s!-~]', '?', jdump)
def getString(results):
text = ""
for i in results:
text += "File: " + i + "\n"
for j in results[i]:
text += j[0] + ": " + j[1] + "\n"
text += "\n"
return re.sub('[^\s!-~]', '?', text[:-2])
def showHelp(name):
nameT = name.replace("\\","/").split("/")[-1]
helpText = """
//////////////////////
/ File/Folder hasher /
//////////////////////
Usage: %s path [-md4] [-md5]
[-sha1] [-crc32]
[-sha224] [-sha256]
[-sha384] [-sha512]
[-ripemd160] [-whirlpool]
[-sha3_224] [-sha3_256]
[-sha3_384] [-sha3_512]
[-all]
[-file <file name>]
[-json]
Options:
path Path to file or directory to hash
-all Use all hash algorithms.
-file Save hash report to a text file
-json Format output in json
Hash algorithm options:
-md4
-md5
-sha1
-crc32
-sha224
-sha256
-sha384
-sha512
-ripemd160
-whirlpool
-sha3_224
-sha3_256
-sha3_384
-sha3_512
"""
print(helpText % nameT)
def main():
args = sys.argv
if len(args) < 3:
print("Not enough arguments!")
showHelp(args[0])
sys.exit(1)
allowed = [
"-file",
"-all",
"-md4",
"-md5",
"-sha1",
"-crc32",
"-sha224",
"-sha256",
"-sha384",
"-sha512",
"-ripemd160",
"-whirlpool",
"-json",
"-raw",
"-sha3_224",
"-sha3_256",
"-sha3_384",
"-sha3_512",
]
hashes = [
"-md4",
"-md5",
"-sha1",
"-crc32",
"-sha224",
"-sha256",
"-sha384",
"-sha512",
"-ripemd160",
"-whirlpool",
"-sha3_224",
"-sha3_256",
"-sha3_384",
"-sha3_512",
]
dataContain = [
"-file",
]
b = 2
for i in args[b:]:
if args.count(i) > 1:
print("Repeating options: " + i)
showHelp(args[0])
sys.exit(1)
if not i in allowed and args[b-1] not in dataContain:
print("Invalid option: " + i)
print(args[b+1])
showHelp(args[0])
sys.exit(1)
b += 1
else:
if args[-1] in dataContain:
print("'%s' option must have a file path next to it." % i)
showHelp(args[0])
sys.exit(1)
for i in args[2:]:
if i in hashes + ["-all"]:
break
else:
print("No hashes specified.")
showHelp(args[0])
sys.exit(1)
collisions = {
"-all" : ["-md4", "-md5", "-sha1",
"-crc32", "-sha224", "-sha256",
"-sha384", "-sha512", "-ripemd160",
"-whirlpool", "-sha3_224", "-sha3_256",
"-sha3_384", "-sha3_512",]
}
for i in collisions:
if i in args:
for j in collisions[i]:
if j in args:
print("Colliding options. (" + i + " and " + j + ")")
showHelp(args[0])
sys.exit(1)
fileName = args[1]
fileNameT = fileName.replace("\\", "/").split("/")[-1]
if os.path.isfile(fileName):
ftype = "file"
elif os.path.isdir(fileName):
ftype = "directory"
else:
print("File or directory does not exits or you don't have permission to read it.")
showHelp(args[0])
sys.exit(1)
funcTable = {
"-md4" : ("MD4", md4File),
"-md5" : ("MD5", md5File),
"-sha1" : ("SHA1", sha1File),
"-crc32" : ("CRC32", crc32File),
"-sha224" : ("SHA224", sha224File),
"-sha256" : ("SHA256", sha256File),
"-sha384" : ("SHA384", sha384File),
"-sha512" : ("SHA512", sha512File),
"-ripemd160" : ("Ripemd160", ripemd160File),
"-whirlpool" : ("Whirlpool", whirlpoolFile),
"-sha3_224" : ("SHA3-224", sha3_224File),
"-sha3_256" : ("SHA3-256", sha3_256File),
"-sha3_384" : ("SHA3-384", sha3_384File),
"-sha3_512" : ("SHA3-512", sha3_512File),
}
funcList = []
if "-all" in args:
for i in hashes:
funcList.append(funcTable[i])
else:
for i in hashes:
if i in args:
funcList.append(funcTable[i])
try:
if ftype == "file":
print("Hashing...\n")
results = {}
results[fileNameT] = []
st = time.time()
try:
for function in funcList:
hash = function[1](fileName)
results[fileNameT].append([function[0], hash])
except KeyboardInterrupt:
print("Hashing canceled.")
sys.exit(2)
except PermissionError:
print("You don't have permission to access the file.")
showHelp(args[0])
sys.exit(2)
et = time.time()
if "-json" in args:
strResults = getJson(results)
elif "-raw" in args:
strResults = results
else:
strResults = getString(results)
if "-file" in args:
print("Writing file...")
f = open(args[args.index("-file") + 1], "w")
f.write(strResults)
f.close()
print("File saved sucessfully in %s seconds." % str("{0:.2f}".format(et-st)))
else:
print(strResults)
print("\nCalculated in %s seconds." % str("{0:.2f}".format(et-st)))
sys.exit(0)
else:
filenum = 0
print("Scanning files...")
st = time.time()
try:
for subdir, dirs, files in os.walk(fileName):
for file in files:
filenum += 1
except KeyboardInterrupt:
print("Files not scanned. Progress cannot be tracked.")
filenum = -1
if filenum == 0:
print("Directory is empty or you don't have permission to read it.")
showHelp(args[0])
sys.exit(1)
print("Number of files: " + str(filenum))
print("Hashing...\n")
results = {}
onfile = 1
passed = 0
try:
if filenum == -1:
print(" | Hashing... | ???%", end="\r")
for subdir, dirs, files in os.walk(fileName):
for file in files:
results[os.path.join(subdir, file)] = []
if filenum != -1:
perc = onfile/filenum
percnum = "{0:.2f}".format(perc*100)
toprint = " |" + ("#" * int((20*perc))) + " " * int(20-int(20*perc)) + "| " + percnum + "%"
print(toprint, end="\r")
for function in funcList:
try:
try:
hash = function[1](os.path.join(subdir, file))
results[os.path.join(subdir, file)].append([function[0], hash])
except PermissionError:
results[os.path.join(subdir, file)].append(["Error", "Access denied"])
passed += 1
except FileNotFoundError:
results[os.path.join(subdir, file)].append(["Error", "File not found"])
passed += 1
except Exception as e:
results[os.path.join(subdir, file)].append(["Error", str(e)])
passed += 1
onfile += 1
else:
print(" |####################| 100% \n")
except KeyboardInterrupt:
print("Hashing canceled. ")
sys.exit(2)
et = time.time()
print("Passed %s files" % str(passed))
if "-json" in args:
strResults = getJson(results)
elif "-raw" in args:
strResults = results
else:
strResults = getString(results)
if "-file" in args:
print("Writing file...")
f = open(args[args.index("-file") + 1], "wb")
f.write(strResults.encode())
f.close()
print("\nFile saved sucessfully in %s seconds." % str("{0:.2f}".format(et-st)))
else:
print(strResults)
print("\nCalculated in %s seconds." % str("{0:.2f}".format(et-st)))
sys.exit(0)
except MemoryError:
print("Maximum memory reached. Please consider using an x64 version of the program and upgrading your RAM.\n")
if __name__ == "__main__":
main()
Он может хешировать файл или папку с помощью следующих алгоритмов:
md4
мд5
sha3_512
Вы также можете сохранить хешированные значения в файле или отформатировать их с помощью json для упрощения анализа.
Хорошая вещь в том, что вы можете легко создать файл .bat для автоматизации.
Если вам действительно нужна эта программа, но вы доверяете своему антивирусу больше, чем мне, скомпилируйте приведенный выше исходник с помощью pyinstaller .
pip install pyinstaller
pyinstaller hasher.py
4.5 Необязательно запустите: pyinstaller hasher.py --onefile
если вы хотите, чтобы исполняемый файл был только однимОбратите внимание, что совместимость скомпилированного exe не проверялась, потому что у меня нет времени.
rhash — это инструмент командной строки, который может вычислять отдельные хэши.
Вы можете использовать мой сценарий shellex.bat, чтобы добавить запись в контекстное меню проводника, которая показывает хэш в окне консоли.
Например, это добавит команду «CRC32» в каждый файл (вставьте ее и выполните из пакетного файла):
call shellex * CRC32 ""%~d0\PortableApps\ConEmu\ConEmu.exe" /cmd "%PROGRAMFILES%\Rhash\rhash.exe" -C --simple ""%%%%1"""
Еще один вариант использования certuil — здесь .
Кстати, для небольших файлов я предпочитаю HashMyFiles из-за более удобного графического интерфейса.
Томас Веллер
Томас Веллер
wb9688
лирически злой