[AHK v2] Hash string and file functions

Post your working scripts, libraries and tools.
oif2003
Posts: 214
Joined: 17 Oct 2018, 11:43
Contact:

[AHK v2] Hash string and file functions

21 Nov 2018, 16:07

Hi,

Here are two basic hash functions:
hashString(String, Algorithm)
hashFile(FilePath, Algorithm)

Supported hash algorithms: MD2, MD4, MD5, SHA1, SHA256, SHA384, SHA512

hashString is done using Windows' Cryptography API: Next Generation (CNG)
https://docs.microsoft.com/en-us/window ... h-with-cng
According to the documentation:
Minimum supported client Windows Vista [desktop apps | UWP apps]
Minimum supported server Windows Server 2008 [desktop apps | UWP apps]

hashFile uses CertUtil -hashfile, so it is subject CertUtil's limitations.

Note: Tested on Windows 10 64 bit Pro with AutoHotkey v2 a100 32/64 bit

GitHub Link: https://github.com/oif2003/AHK_v2_64bit ... h.ahk?ts=4

Code: Select all

/*
	Basic string and file hash functions for AutoHotkey v2 a100
	by oif2003 (21 Nov 2018)
	Supported hash algorithms: MD2, MD4, MD5, SHA1, SHA256, SHA384, SHA512
*/

; == A quick demo ==
#SingleInstance force

;setup gui stuff
gui := GuiCreate(, "String and file hash demo")
gui.SetFont("s10", "Consolas")
editbox := gui.Add("Edit", "r22 w1020 readonly")
gui.Show()

Str_To_Hash  := "Hash me!"			;string to hash
File_To_Hash := A_ScriptFullPath	;file to hash

;algorithms to try
Hash_Types := ["MD2","MD4","MD5","SHA1","SHA256","SHA384","SHA512","AES"]

;hashString attempts
editbox.Value .= "string = " Str_To_Hash "`n"
for _, v in Hash_Types {
	if !hash := hashString(Str_To_Hash, v)	{ ;calling the hash function
		hash := "Unsupported request"
	}
	editbox.Value .= format("{:-6}", v) " = " . hash . (k != Hash_Types.Length() ? "`n" : "")
}

;hashFile attempts
editbox.Value .= "`nfile   = " File_To_Hash "`n"
for _, v in Hash_Types {
	if !hash := hashFile(file_To_Hash, v)	{ ;calling the hash function
		hash := (e := hashFile()) ? e : "Unsupported request"
	}
	editbox.Value .= format("{:-6}", v) " = " . hash . (k != Hash_Types.Length() ? "`n" : "")
}

;getting error message from bad CertUtil requests
editbox.Value .= hashFile("no such file", "MD5") "`n"
editbox.Value .= "The last error message was: "
editbox.Value .= hashFile() "`n"
; == end of demo ==


;-------------------------------------------------------------------------------------------------------------------
;hashFile(FullFilePath, Algorithm) - valid Algorithms: MD2, MD4, MD5, SHA1, SHA256, SHA384, SHA512
;-------------------------------------------------------------------------------------------------------------------
hashFile(file := "", algo := "") {	;using CertUtil
	static cPid := 0
	static lastError := ""	;stores last error message: strStdOut
	static Supported_Hash := Object("MD2",_,"MD4",_,"MD5",_,"SHA1",_,"SHA256",_,"SHA384",_,"SHA512",_)
	
	;return last error message
	if !file {
		return lastError
	}
	
	;check to see if requested algorithm is supported
	algo := StrUpper(algo)
	if !Supported_Hash.HasKey(algo) {
		return
	}
	
	;create and hide command window if we don't already have one
	if !cPid {
		_A_DetectHiddenWindows := A_DetectHiddenWindows
		A_DetectHiddenWindows  := true
		Run(A_ComSpec " /k ",, "Hide", cPid)
		WinWait("ahk_pid" cPid, , 10)
		DllCall("AttachConsole","uint", cPid)
		A_DetectHiddenWindows  := _A_DetectHiddenWindows
		
		;clean up on exiting script
		OnExit(()=>cleanUp(cPid))
	}
	
	;run command and get output
	objShell := ComObjCreate("WScript.Shell")
	objExec  := objShell.Exec('certutil -hashfile "' file '" ' algo)
	while !objExec.StdOut.AtEndOfStream {
		strStdOut := objExec.StdOut.ReadAll()
	}

	;parse output
	start := InStr(strStdOut, file ":") + StrLen(file) + 1
	end := InStr(strStdOut, "CertUtil: -hashfile command completed successfully.", , -1) - 1
	if start < end {
		return StrUpper(SubStr(strStdOut, start + 2, end - start - 2))
	} else {
		lastError := strStdOut
		return
	}
	
	;cleanUp function called on script exit (OnExit)
	cleanUp(_cPid) {
		_A_DetectHiddenWindows := A_DetectHiddenWindows
		A_DetectHiddenWindows := true
		DllCall("FreeConsole", "UInt")
		WinKill("ahk_pid" _cPid)
		A_DetectHiddenWindows := _A_DetectHiddenWindows
	}
}

;-------------------------------------------------------------------------------------------------------------------
;hashString(String, Algorithm) - valid Algorithms: MD2, MD4, MD5, SHA1, SHA256, SHA384, SHA512
;-------------------------------------------------------------------------------------------------------------------
hashString(string, algo) {
	;These are the supported formats, maybe someone else can get the rest to work?
	static Supported_Hash := Object("MD2",_,"MD4",_,"MD5",_,"SHA1",_,"SHA256",_,"SHA384",_,"SHA512",_)
	
	;check to see if requested algorithm is supported
	algo := StrUpper(algo)
	if !Supported_Hash.HasKey(algo) {
		return
	}
	
	;continue if algorithm is supported
	hModule := DllCall("LoadLibrary", "Str", "Bcrypt.dll", "Ptr")
	size := StrPutVar(string, str) - 1	;put string in str variable as UTF-8 for later use
	
	;See link for explaination of steps taken below: 
	;https://docs.microsoft.com/en-us/windows/desktop/SecCNG/creating-a-hash-with-cng
	;-------------------------------------------------------------------------------------------------
	;https://docs.microsoft.com/en-us/windows/desktop/api/Bcrypt/nf-bcrypt-bcryptopenalgorithmprovider
	DllCall("Bcrypt.dll\BCryptOpenAlgorithmProvider"
		,"Ptr*", phandle
		,"Str", algo
		,"Str", 
		,"UInt", 0
		,"UInt"	;returned error code see winnt.h
	)

	;https://docs.microsoft.com/en-us/windows/desktop/api/Bcrypt/nf-bcrypt-bcryptgetproperty
	DllCall("Bcrypt.dll\BCryptGetProperty"
		,"Ptr", phandle
		,"Str", "ObjectLength"
		,"UInt*", pbOutput
		,"UInt", 4
		,"UInt*", pcbResult
		,"UInt", 0
		,"UInt"	;returned error code see winnt.h
	)

	;https://docs.microsoft.com/en-us/windows/desktop/api/Bcrypt/nf-bcrypt-bcryptcreatehash
	cbHashObject := pbOutput
	VarSetCapacity(pbHashObject, cbHashObject, 0)
	DllCall("Bcrypt.dll\BCryptCreateHash"
		,"Ptr", phandle
		,"Ptr*", phHash
		,"Ptr", &pbHashObject
		,"UInt", cbHashObject
		,"Ptr", 0
		,"UInt", 0
		,"UInt", 0
		,"UInt"	;returned error code see winnt.h
	)

	;https://docs.microsoft.com/en-us/windows/desktop/api/Bcrypt/nf-bcrypt-bcrypthashdata
	DllCall("Bcrypt.dll\BCryptHashData"
		,"Ptr", phHash
		,"Ptr", &str ;&pbInput
		,"UInt", size ;cbInput
		,"UInt", 0
		,"UInt"	;returned error code see winnt.h
	)

	DllCall("Bcrypt.dll\BCryptGetProperty"
		,"Ptr", phandle
		,"Str", "HashDigestLength"
		,"UInt*", pbOutput
		,"UInt", 4
		,"UInt*", pcbResult
		,"UInt", 0
		,"UInt"	;returned error code see winnt.h
	)
	hashsize := pbOutput

	;https://docs.microsoft.com/en-us/windows/desktop/api/Bcrypt/nf-bcrypt-bcryptfinishhash
	cbOutput := hashsize
	VarSetCapacity(pbOutput, cbOutput, 0)
	DllCall("Bcrypt.dll\BCryptFinishHash"
		,"Ptr", phHash
		,"Ptr", &pbOutput
		,"UInt", cbOutput
		,"UInt", 0
		,"UInt"	;returned error code see winnt.h
	)

	;read each byte and append its 2 digit hex value to hashstr
	loop hashsize {
		hashstr .= format("{:02x}", NumGet(&pbOutput, A_Index - 1 , "UChar"))
	}

	;clean up
	DllCall("Bcrypt.dll\BCryptDestroyHash", "Ptr", phHash, "UInt")
	DllCall("Bcrypt.dll\BCryptCloseAlgorithmProvider", "Ptr", phandle, "UInt", 0, "UInt")
	DllCall("FreeLibrary", "Ptr", hModule)

	return StrUpper(hashstr)
	
	;-------------------------------------------------------------------------------------------------
	;helper function
	StrPutVar(string, ByRef var) {	;from AHK v2 doc
		VarSetCapacity(var, StrPut(string, "Utf-8"))
		return StrPut(string, &var, "Utf-8")
	}
}

Image
carno
Posts: 265
Joined: 20 Jun 2014, 16:48

Re: [AHK v2] Hash string and file functions

22 Jul 2021, 15:15

Thanks, great work!
guest3456
Posts: 3463
Joined: 09 Oct 2013, 10:31

Re: [AHK v2] Hash string and file functions

22 Jul 2021, 22:40

oif2003 wrote:
21 Nov 2018, 16:07
hashString is done using Windows' Cryptography API: Next Generation (CNG)
https://docs.microsoft.com/en-us/windows/desktop/SecCNG/creating-a-hash-with-cng
would be curious if you know how to sign the hash data as well, like the example here:

https://docs.microsoft.com/en-us/windows/win32/seccng/signing-data-with-cng

guest3456
Posts: 3463
Joined: 09 Oct 2013, 10:31

Re: [AHK v2] Hash string and file functions

24 Jul 2021, 14:33

malcev wrote:
23 Jul 2021, 05:16
guest3456, You can look at this examples
https://www.autohotkey.com/boards/viewtopic.php?f=6&t=89236
thanks that can give me a start


Return to “Scripts and Functions (v2)”

Who is online

Users browsing this forum: No registered users and 9 guests