文件的哈希值校验算法
文件MD5 CRC32.ahk
MsgBox % FileCRC32(A_AhkPath) MsgBox % MD5_File(A_AhkPath) ; ************ MD5 hashing functions by Laszlo ******************* FileCRC32( sFile="",cSz=4 ) { ; by SKAN 10-Oct-2009 www.autohotkey.com/community/viewtopic.php?t=64211 cSz := (cSz<0||cSz>8) ? 2**22 : 2**(18+cSz), VarSetCapacity(Buffer,cSz,0) , hFil := DllCall("CreateFile", "Str", sFile, "UInt", 0x80000000, "Int", 3, "Int", 0, "Int", 3, "Int", 0, "Int", 0) IfLess,hFil,1, Return,hFil hMod := DllCall("LoadLibrary", "Str", "ntdll.dll"), CRC32 := 0 , DllCall("GetFileSizeEx", "UInt",hFil, "UInt",&Buffer), fSz := NumGet(Buffer, 0,"Int64") Loop % ( fSz//cSz + !!Mod( fSz,cSz ) ) DllCall("ReadFile", "UInt", hFil, "UInt", &Buffer, "UInt", cSz, "UIntP",Bytes, "UInt",0) , CRC32 := DllCall("NTDLL\RtlComputeCrc32", "UInt", CRC32, "UInt", &Buffer, "UInt", Bytes, "UInt") DllCall("CloseHandle", "UInt", hFil) SetFormat, Integer, % SubStr((AFI := A_FormatInteger) "H", 0) CRC32 := SubStr(CRC32 + 0x1000000000, -7), DllCall("CharUpper", "Str", CRC32) SetFormat, Integer, %AFI% Return CRC32, DllCall("FreeLibrary", "UInt", hMod) } MD5_File(sFile="", cSz=4) { ; www.autohotkey.com/forum/viewtopic.php?p=275910#275910 cSz := (cSz<0||cSz>8) ? 2**22 : 2**(18+cSz), VarSetCapacity(Buffer, cSz, 0) hFil := DllCall("CreateFile", "Str", sFile, "UInt", 0x80000000, "Int", 1,"Int", 0,"Int", 3,"Int", 0,"Int", 0) IfLess,hFil,1, Return,hFil DllCall("GetFileSizeEx", "UInt", hFil, "Str", Buffer), fSz := NumGet(Buffer, 0, "Int64") VarSetCapacity(MD5_CTX, 104, 0), DllCall("advapi32\MD5Init", "Str", MD5_CTX) LoopNum := fSz//cSz Loop % (LoopNum +!!Mod(fSz,cSz)) { if (LoopNum > 125) ToolTip % (A_index * cSz *100) / fSz "%" DllCall("ReadFile", "UInt", hFil, "Str", Buffer, "UInt", cSz, "UIntP", bytesRead, "UInt", 0) , DllCall("advapi32\MD5Update", "Str", MD5_CTX, "Str", Buffer, "UInt", bytesRead) } if (LoopNum > 125) ToolTip DllCall("advapi32\MD5Final", "Str", MD5_CTX), DllCall("CloseHandle", "UInt", hFil) Loop % StrLen(Hex:="123456789ABCDEF0") N := NumGet(MD5_CTX, 87+A_Index, "Char"), MD5 .= SubStr(Hex,N>>4,1) . SubStr(Hex,N&15,1) Return MD5 } MD5(ByRef V, L=0) { ; www.autohotkey.com/forum/viewtopic.php?p=275910#275910 VarSetCapacity( MD5_CTX,104,0 ), DllCall( "advapi32\MD5Init", "Str",MD5_CTX ) DllCall("advapi32\MD5Update", "Str", MD5_CTX, "Str", V, "UInt", L ? L : VarSetCapacity(V) ) DllCall("advapi32\MD5Final", "Str", MD5_CTX ) Loop % StrLen(Hex:="123456789ABCDEF0") N := NumGet(MD5_CTX,87+A_Index, "Char"), MD5 .= SubStr(Hex,N>>4,1) . SubStr(Hex,N&15,1) Return MD5 }
Hash哈希检验.ahk
MsgBox % Hash("", A_AhkPath) ; 默认SHA256哈希格式为十六进制(默认为大写) MsgBox % Hash("Upper:0", A_AhkPath) ; 与上面相同,但哈希将使用小写形式 MsgBox % Hash("Base64:1", A_AhkPath) ; 默认SHA256哈希为Base64文本 MsgBox % Hash("alg:SHA512 Upper:0", A_AhkPath) ; SHA512哈希格式为十六进制(小写) MsgBox % Hash("alg:SHA512 Base64:1", A_AhkPath) ; 格式化为Base64文本的SHA512哈希 Hash(Options, ByRef Var, nBytes:="") { ; Hash() v0.37 by SKAN on D444/D445 @ tiny.cc/hashit Local HA := {"ALG":"SHA256","BAS":0, "UPP":1, "ENC":"UTF-8"} Loop, Parse, % Format("{:U}", Options), %A_Space%, + A := StrSplit(A_LoopField, ":", "+"), HA[ SubStr(A[1], 1, 3) ] := A[2] HA.X := ( HA.ENC="UTF-16" ? 2 : 1) OK1 := { "SHA1":1, "SHA256":1, "SHA384":1, "SHA512":1, "MD2":1, "MD4":1, "MD5":1 }[ HA.ALG ] OK2 := { "CP0":1, "UTF-8":1, "UTF-16":1}[ HA.ENC ] NaN := ( StrLen(nBytes) And (nBytes != Round(nBytes)) ), lVar := StrLen(Var) pNum := ( lVar And [var].GetCapacity(1)="" And (Var = Abs(Round(Var))) ), nVar := VarSetCapacity(Var) If ( OK1="" Or OK2="" Or NaN=1 Or lVar<1 Or (pNum=1 And nBytes<1) Or (pNum=0 And nVar<nBytes)) Return ( 0, ErrorLevel := OK1="" ? "Algorithm not known.`n=> MD2 MD4 MD5 SHA1 SHA256 SHA384 SHA512`nDefault: SHA256" : OK2="" ? "Codepage incorrect.`n=> CP0 UTF-16 UTF-8`nDefault: UTF-8" : NaN=1 ? "nBytes in incorrect format" : lVar<1 ? "Var is empty. Nothing to hash." : (pNum=1 And nBytes<1) ? "Pointer requires nBytes greater than 0." : (pNum=0 And nVar<nBytes) ? "Var's capacity is lesser than nBytes." : "" ) hBcrypt := DllCall("Kernel32.dll\LoadLibrary", "Str","Bcrypt.dll", "Ptr") DllCall("Bcrypt.dll\BCryptOpenAlgorithmProvider", "PtrP",hAlg:=0, "WStr",HA.ALG, "Ptr",0, "Int",0, "UInt") DllCall("Bcrypt.dll\BCryptCreateHash", "Ptr",hAlg, "PtrP",hHash:=0, "Ptr", 0, "Int", 0, "Ptr",0, "Int",0, "Int", 0) nLen := 0, FileLen := File := rBytes := sStr := nErr := "" If ( nBytes!="" And (pBuf:=pNum ? Var+0 : &Var) ) { If ( nBytes<=0 ) nBytes := StrPut(Var, HA.ENC) , VarSetCapacity(sStr, nBytes * HA.X) , nBytes := ( StrPut(Var, pBuf := &sStr, nBytes, HA.ENC) - 1 ) * HA.X nErr := DllCall("Bcrypt.dll\BCryptHashData", "Ptr",hHash, "Ptr",pBuf, "Int",nBytes, "Int", 0, "UInt") } Else { File := FileOpen(Var, "r -rwd") If ( (FileLen := File.Length) And VarSetCapacity(Bin, 65536) ) Loop If ( rBytes := File.RawRead(&Bin, 65536) ) nErr := DllCall("Bcrypt.dll\BCryptHashData", "Ptr",hHash, "Ptr",&Bin, "Int",rBytes, "Int", 0, "Uint") Until ( nErr Or File.AtEOF Or !rBytes ) File := ( FileLen="" ? 0 : File.Close() ) } DllCall("Bcrypt.dll\BCryptGetProperty", "Ptr",hAlg, "WStr", "HashDigestLength", "UIntP",nLen, "Int",4, "PtrP",0, "Int",0) VarSetCapacity(Hash, nLen) DllCall("Bcrypt.dll\BCryptFinishHash", "Ptr",hHash, "Ptr",&Hash, "Int",nLen, "Int", 0) DllCall("Bcrypt.dll\BCryptDestroyHash", "Ptr",hHash) DllCall("Bcrypt.dll\BCryptCloseAlgorithmProvider", "Ptr",hAlg, "Int",0) DllCall("Kernel32.dll\FreeLibrary", "Ptr",hBCrypt) If ( nErr=0 ) VarSetCapacity(sStr, 260, 0), nFlags := HA.BAS ? 0x40000001 : 0x4000000C , DllCall("Crypt32\CryptBinaryToString", "Ptr",&Hash, "Int",nLen, "Int",nFlags, "Str",sStr, "UIntP",130) , sStr := ( nFlags=0x4000000C And HA.UPP ? Format("{:U}", sStr) : sStr ) Return ( sStr, ErrorLevel := File=0 ? ( FileExist(Var) ? "Open file error. File in use." : "File does not exist." ) : FileLen=0 ? "Zero byte file. Nothing to hash." : (FileLen & rBytes=0) ? "Read file error." : nErr ? Format("Bcrypt error. 0x{:08X}", nErr) : nErr="" ? "Unknown error." : "" ) }
字符串哈希值校验算法 - 单函数实现
MD5.ahk
; MD5算法是一种广泛使用的散列函数,产生128位散列值 MsgBox % MD5("Hello World") "`n" . MD5("Hello World", 1) MD5(string, case := 0) { static MD5_DIGEST_LENGTH := 16 hModule := DllCall("LoadLibrary", "Str", "advapi32.dll", "Ptr") , VarSetCapacity(MD5_CTX, 104, 0), DllCall("advapi32\MD5Init", "Ptr", &MD5_CTX) , DllCall("advapi32\MD5Update", "Ptr", &MD5_CTX, "AStr", string, "UInt", StrLen(string)) , DllCall("advapi32\MD5Final", "Ptr", &MD5_CTX) loop % MD5_DIGEST_LENGTH o .= Format("{:02" (case ? "X" : "x") "}", NumGet(MD5_CTX, 87 + A_Index, "UChar")) return o, DllCall("FreeLibrary", "Ptr", hModule) }
CRC32.ahk
; CRC32在AutoHotkey中的实现 CRC32(str) { static table := [] loop 256 { crc := A_Index - 1 loop 8 crc := (crc & 1) ? (crc >> 1) ^ 0xEDB88320 : (crc >> 1) table[A_Index - 1] := crc } crc := ~0 loop, parse, str crc := table[(crc & 0xFF) ^ Asc(A_LoopField)] ^ (crc >> 8) return Format("{:#x}", ~crc) } MsgBox % CRC32("The quick brown fox jumps over the lazy dog") ; -> 0x414fa339 ; CRC32通过DllCall(WinAPI) CRC32WinAPI(str, enc = "UTF-8") { l := (enc = "CP1200" || enc = "UTF-16") ? 2 : 1, s := (StrPut(str, enc) - 1) * l VarSetCapacity(b, s, 0) && StrPut(str, &b, floor(s / l), enc) CRC32 := DllCall("ntdll.dll\RtlComputeCrc32", "UInt", 0, "Ptr", &b, "UInt", s) return Format("{:#x}", CRC32) } MsgBox % CRC32WinAPI("The quick brown fox jumps over the lazy dog") ; -> 0x414fa339 ; CRC32文件通过DllCall(WinAPI) CRC32_File(filename) { if !(f := FileOpen(filename, "r", "UTF-8")) throw Exception("Failed to open file: " filename, -1) f.Seek(0) while (dataread := f.RawRead(data, 262144)) crc := DllCall("ntdll.dll\RtlComputeCrc32", "uint", crc, "ptr", &data, "uint", dataread, "uint") f.Close() return Format("{:#x}", crc) } MsgBox % CRC32_File(A_AhkPath)
SHA1.ahk
; 在密码学中,SHA-1(安全哈希算法1)是一种加密哈希函数 MsgBox % SHA("Hello World") "`n" . SHA("Hello World", 1) SHA(string, case := 0) { static SHA_DIGEST_LENGTH := 20 hModule := DllCall("LoadLibrary", "Str", "advapi32.dll", "Ptr") , VarSetCapacity(SHA_CTX, 136, 0), DllCall("advapi32\A_SHAInit", "Ptr", &SHA_CTX) , DllCall("advapi32\A_SHAUpdate", "Ptr", &SHA_CTX, "AStr", string, "UInt", StrLen(string)) , DllCall("advapi32\A_SHAFinal", "Ptr", &SHA_CTX, "UInt", &SHA_CTX + 116) loop % SHA_DIGEST_LENGTH o .= Format("{:02" (case ? "X" : "x") "}", NumGet(SHA_CTX, 115 + A_Index, "UChar")) return o, DllCall("FreeLibrary", "Ptr", hModule) }
MD4.ahk
; MD4消息摘要算法是一个加密散列函数 MsgBox % MD4("Hello World") "`n" . MD4("Hello World", 1) MD4(string, case := 0) { static MD4_DIGEST_LENGTH := 16 hModule := DllCall("LoadLibrary", "Str", "advapi32.dll", "Ptr") , VarSetCapacity(MD4_CTX, 104, 0), DllCall("advapi32\MD4Init", "Ptr", &MD4_CTX) , DllCall("advapi32\MD4Update", "Ptr", &MD4_CTX, "AStr", string, "UInt", StrLen(string)) , DllCall("advapi32\MD4Final", "Ptr", &MD4_CTX) loop % MD4_DIGEST_LENGTH o .= Format("{:02" (case ? "X" : "x") "}", NumGet(MD4_CTX, 87 + A_Index, "UChar")) return o, DllCall("FreeLibrary", "Ptr", hModule) }
Adler32.ahk
; Adler-32是一种校验和算法 MsgBox % Adler32("Hello World") ; <== 0x180b041d MsgBox % Adler32("The quick brown fox jumps over the lazy dog") ; <== 0x5bdc0fda Adler32(str) { a := 1, b := 0 loop, parse, str b := Mod(b + (a := Mod(a + Asc(A_LoopField), 0xFFF1)), 0xFFF1) return Format("{:#x}", (b << 16) | a) }
综合的哈希值校验算法实现类库
; AES 的密码长度必须为 128位、192位、256位 也就是 16字节、24字节、32字节 中的一个,并且 IV 长度也要对应,否则将报错。 ; 从字符串创建 SHA-1 哈希值 MsgBox % Crypt.Hash.String("SHA1", "The quick brown fox jumps over the lazy dog") ; -> 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 ; 使用HMAC从字符串创建SHA-256哈希 MsgBox % Crypt.Hash.HMAC("SHA256", "The quick brown fox jumps over the lazy dog", "Secret Salt") ; -> 68dba4b3a6d5c36b6e3567e1a925fe87c7386162e8fb6e2e9f17ade4aa7dc262 ; 从文件创建SHA-256哈希 MsgBox % Crypt.Hash.File("SHA256", "C:\Program Files\AutoHotkey\AutoHotkey.exe") ; -> 0a9964fe0e0fb3f0679df317a65f9945c474dab8c4370b45b93da64a8b201b9f ; 使用SHA-1创建PBKDF2哈希,1500次迭代,从字符串中创建密钥大小为192 MsgBox % Crypt.Hash.PBKDF2("SHA1", "The quick brown fox jumps over the lazy dog", "Secret Salt", 1500, 192) ; -> 531c1bbae7c3de019d1f53adcac7d85bf2b04caba9d6d6d1 ; 更多示例详见:https://www.autohotkey.com/boards/viewtopic.php?p=109958#p109958 ; ============================================================================================== ; AutoHotkey wrapper for Cryptography API: Next Generation ; ; Author ....: jNizM ; Released ..: 2016-09-15 ; Modified ..: 2021-01-04 ; Github ....: https://github.com/jNizM/AHK_CNG ; Forum .....: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=23413 ; ============================================================================================== class Crypt { ; ===== PUBLIC CLASS / METHODS ============================================================================================== class Encrypt { String(AlgId, Mode := "", String := "", Key := "", IV := "", Encoding := "utf-8", Output := "BASE64") { try { ; verify the encryption algorithm if !(ALGORITHM_IDENTIFIER := Crypt.Verify.EncryptionAlgorithm(AlgId)) throw Exception("Wrong ALGORITHM_IDENTIFIER", -1) ; open an algorithm handle. if !(ALG_HANDLE := Crypt.BCrypt.OpenAlgorithmProvider(ALGORITHM_IDENTIFIER)) throw Exception("BCryptOpenAlgorithmProvider failed", -1) ; verify the chaining mode if (CHAINING_MODE := Crypt.Verify.ChainingMode(Mode)) ; set chaining mode property. if !(Crypt.BCrypt.SetProperty(ALG_HANDLE, Crypt.Constants.BCRYPT_CHAINING_MODE, CHAINING_MODE)) throw Exception("SetProperty failed", -1) ; generate the key from supplied input key bytes. if !(KEY_HANDLE := Crypt.BCrypt.GenerateSymmetricKey(ALG_HANDLE, Key, Encoding)) throw Exception("GenerateSymmetricKey failed", -1) ; calculate the block length for the IV. if !(BLOCK_LENGTH := Crypt.BCrypt.GetProperty(ALG_HANDLE, Crypt.Constants.BCRYPT_BLOCK_LENGTH, 4)) throw Exception("GetProperty failed", -1) ; use the key to encrypt the plaintext buffer. for block sized messages, block padding will add an extra block. cbInput := Crypt.Helper.StrPutVar(String, pbInput, Encoding) if !(CIPHER_LENGTH := Crypt.BCrypt.Encrypt(KEY_HANDLE, pbInput, cbInput, IV, BLOCK_LENGTH, CIPHER_DATA, Crypt.Constants.BCRYPT_BLOCK_PADDING)) throw Exception("Encrypt failed", -1) ; convert binary data to string (base64 / hex / hexraw) if !(ENCRYPT := Crypt.Helper.CryptBinaryToString(CIPHER_DATA, CIPHER_LENGTH, Output)) throw Exception("CryptBinaryToString failed", -1) } catch Exception { ; represents errors that occur during application execution throw Exception } finally { ; cleaning up resources if (KEY_HANDLE) Crypt.BCrypt.DestroyKey(KEY_HANDLE) if (ALG_HANDLE) Crypt.BCrypt.CloseAlgorithmProvider(ALG_HANDLE) } return ENCRYPT } } class Decrypt { String(AlgId, Mode := "", String := "", Key := "", IV := "", Encoding := "utf-8", Input := "BASE64") { try { ; verify the encryption algorithm if !(ALGORITHM_IDENTIFIER := Crypt.Verify.EncryptionAlgorithm(AlgId)) throw Exception("Wrong ALGORITHM_IDENTIFIER", -1) ; open an algorithm handle. if !(ALG_HANDLE := Crypt.BCrypt.OpenAlgorithmProvider(ALGORITHM_IDENTIFIER)) throw Exception("BCryptOpenAlgorithmProvider failed", -1) ; verify the chaining mode if (CHAINING_MODE := Crypt.Verify.ChainingMode(Mode)) ; set chaining mode property. if !(Crypt.BCrypt.SetProperty(ALG_HANDLE, Crypt.Constants.BCRYPT_CHAINING_MODE, CHAINING_MODE)) throw Exception("SetProperty failed", -1) ; generate the key from supplied input key bytes. if !(KEY_HANDLE := Crypt.BCrypt.GenerateSymmetricKey(ALG_HANDLE, Key, Encoding)) throw Exception("GenerateSymmetricKey failed", -1) ; convert encrypted string (base64 / hex / hexraw) to binary data if !(CIPHER_LENGTH := Crypt.Helper.CryptStringToBinary(String, CIPHER_DATA, Input)) throw Exception("CryptStringToBinary failed", -1) ; calculate the block length for the IV. if !(BLOCK_LENGTH := Crypt.BCrypt.GetProperty(ALG_HANDLE, Crypt.Constants.BCRYPT_BLOCK_LENGTH, 4)) throw Exception("GetProperty failed", -1) ; use the key to decrypt the data to plaintext buffer if !(DECRYPT_LENGTH := Crypt.BCrypt.Decrypt(KEY_HANDLE, CIPHER_DATA, CIPHER_LENGTH, IV, BLOCK_LENGTH, DECRYPT_DATA, Crypt.Constants.BCRYPT_BLOCK_PADDING)) throw Exception("Decrypt failed", -1) ; receive the decrypted plaintext DECRYPT := StrGet(&DECRYPT_DATA, DECRYPT_LENGTH, Encoding) } catch Exception { ; represents errors that occur during application execution throw Exception } finally { ; cleaning up resources if (KEY_HANDLE) Crypt.BCrypt.DestroyKey(KEY_HANDLE) if (ALG_HANDLE) Crypt.BCrypt.CloseAlgorithmProvider(ALG_HANDLE) } return DECRYPT } } class Hash { String(AlgId, String, Encoding := "utf-8", Output := "HEXRAW") { try { ; verify the hash algorithm if !(ALGORITHM_IDENTIFIER := Crypt.Verify.HashAlgorithm(AlgId)) throw Exception("Wrong ALGORITHM_IDENTIFIER", -1) ; open an algorithm handle if !(ALG_HANDLE := Crypt.BCrypt.OpenAlgorithmProvider(ALGORITHM_IDENTIFIER)) throw Exception("BCryptOpenAlgorithmProvider failed", -1) ; create a hash if !(HASH_HANDLE := Crypt.BCrypt.CreateHash(ALG_HANDLE)) throw Exception("CreateHash failed", -1) ; hash some data cbInput := Crypt.Helper.StrPutVar(String, pbInput, Encoding) if !(Crypt.BCrypt.HashData(HASH_HANDLE, pbInput, cbInput)) throw Exception("HashData failed", -1) ; calculate the length of the hash if !(HASH_LENGTH := Crypt.BCrypt.GetProperty(ALG_HANDLE, Crypt.Constants.BCRYPT_HASH_LENGTH, 4)) throw Exception("GetProperty failed", -1) ; close the hash if !(Crypt.BCrypt.FinishHash(HASH_HANDLE, HASH_DATA, HASH_LENGTH)) throw Exception("FinishHash failed", -1) ; convert bin to string (base64 / hex) if !(HASH := Crypt.Helper.CryptBinaryToString(HASH_DATA, HASH_LENGTH, Output)) throw Exception("CryptBinaryToString failed", -1) } catch Exception { ; represents errors that occur during application execution throw Exception } finally { ; cleaning up resources if (HASH_HANDLE) Crypt.BCrypt.DestroyHash(HASH_HANDLE) if (ALG_HANDLE) Crypt.BCrypt.CloseAlgorithmProvider(ALG_HANDLE) } return HASH } File(AlgId, FileName, Bytes := 1048576, Offset := 0, Length := -1, Encoding := "utf-8", Output := "HEXRAW") { try { ; verify the hash algorithm if !(ALGORITHM_IDENTIFIER := Crypt.Verify.HashAlgorithm(AlgId)) throw Exception("Wrong ALGORITHM_IDENTIFIER", -1) ; open an algorithm handle if !(ALG_HANDLE := Crypt.BCrypt.OpenAlgorithmProvider(ALGORITHM_IDENTIFIER)) throw Exception("BCryptOpenAlgorithmProvider failed", -1) ; create a hash if !(HASH_HANDLE := Crypt.BCrypt.CreateHash(ALG_HANDLE)) throw Exception("CreateHash failed", -1) ; hash some data if !(IsObject(File := FileOpen(FileName, "r", Encoding))) throw Exception("Failed to open file: " FileName, -1) Length := Length < 0 ? File.Length - Offset : Length if ((Offset + Length) > File.Length) throw Exception("Invalid parameters offset / length!", -1) while (Length > Bytes) && (Dataread := File.RawRead(Data, Bytes)) { if !(Crypt.BCrypt.HashData(HASH_HANDLE, Data, Dataread)) throw Exception("HashData failed", -1) Length -= Dataread } if (Length > 0) { if (Dataread := File.RawRead(Data, Length)) { if !(Crypt.BCrypt.HashData(HASH_HANDLE, Data, Dataread)) throw Exception("HashData failed", -1) } } ; calculate the length of the hash if !(HASH_LENGTH := Crypt.BCrypt.GetProperty(ALG_HANDLE, Crypt.Constants.BCRYPT_HASH_LENGTH, 4)) throw Exception("GetProperty failed", -1) ; close the hash if !(Crypt.BCrypt.FinishHash(HASH_HANDLE, HASH_DATA, HASH_LENGTH)) throw Exception("FinishHash failed", -1) ; convert bin to string (base64 / hex) if !(HASH := Crypt.Helper.CryptBinaryToString(HASH_DATA, HASH_LENGTH, Output)) throw Exception("CryptBinaryToString failed", -1) } catch Exception { ; represents errors that occur during application execution throw Exception } finally { ; cleaning up resources if (File) File.Close() if (HASH_HANDLE) Crypt.BCrypt.DestroyHash(HASH_HANDLE) if (ALG_HANDLE) Crypt.BCrypt.CloseAlgorithmProvider(ALG_HANDLE) } return HASH } HMAC(AlgId, String, Hmac, Encoding := "utf-8", Output := "HEXRAW") { try { ; verify the hash algorithm if !(ALGORITHM_IDENTIFIER := Crypt.Verify.HashAlgorithm(AlgId)) throw Exception("Wrong ALGORITHM_IDENTIFIER", -1) ; open an algorithm handle if !(ALG_HANDLE := Crypt.BCrypt.OpenAlgorithmProvider(ALGORITHM_IDENTIFIER, Crypt.Constants.BCRYPT_ALG_HANDLE_HMAC_FLAG)) throw Exception("BCryptOpenAlgorithmProvider failed", -1) ; create a hash if !(HASH_HANDLE := Crypt.BCrypt.CreateHash(ALG_HANDLE, Hmac, Encoding)) throw Exception("CreateHash failed", -1) ; hash some data cbInput := Crypt.helper.StrPutVar(String, pbInput, Encoding) if !(Crypt.BCrypt.HashData(HASH_HANDLE, pbInput, cbInput)) throw Exception("HashData failed", -1) ; calculate the length of the hash if !(HASH_LENGTH := Crypt.BCrypt.GetProperty(ALG_HANDLE, Crypt.Constants.BCRYPT_HASH_LENGTH, 4)) throw Exception("GetProperty failed", -1) ; close the hash if !(Crypt.BCrypt.FinishHash(HASH_HANDLE, HASH_DATA, HASH_LENGTH)) throw Exception("FinishHash failed", -1) ; convert bin to string (base64 / hex) if !(HMAC := Crypt.Helper.CryptBinaryToString(HASH_DATA, HASH_LENGTH, Output)) throw Exception("CryptBinaryToString failed", -1) } catch Exception { ; represents errors that occur during application execution throw Exception } finally { ; cleaning up resources if (HASH_HANDLE) Crypt.BCrypt.DestroyHash(HASH_HANDLE) if (ALG_HANDLE) Crypt.BCrypt.CloseAlgorithmProvider(ALG_HANDLE) } return HMAC } PBKDF2(AlgId, Password, Salt, Iterations := 4096, KeySize := 256, Encoding := "utf-8", Output := "HEXRAW") { try { ; verify the hash algorithm if !(ALGORITHM_IDENTIFIER := Crypt.Verify.HashAlgorithm(AlgId)) throw Exception("Wrong ALGORITHM_IDENTIFIER", -1) ; open an algorithm handle if !(ALG_HANDLE := Crypt.BCrypt.OpenAlgorithmProvider(ALGORITHM_IDENTIFIER, Crypt.Constants.BCRYPT_ALG_HANDLE_HMAC_FLAG)) throw Exception("BCryptOpenAlgorithmProvider failed", -1) ; derives a key from a hash value if !(Crypt.BCrypt.DeriveKeyPBKDF2(ALG_HANDLE, Password, Salt, Iterations, PBKDF2_DATA, KeySize / 8, Encoding)) throw Exception("CreateHash failed", -1) ; convert bin to string (base64 / hex) if !(PBKDF2 := Crypt.Helper.CryptBinaryToString(PBKDF2_DATA , KeySize / 8, Output)) throw Exception("CryptBinaryToString failed", -1) } catch Exception { ; represents errors that occur during application execution throw Exception } finally { ; cleaning up resources if (ALG_HANDLE) Crypt.BCrypt.CloseAlgorithmProvider(ALG_HANDLE) } return PBKDF2 } } ; ===== PRIVATE CLASS / METHODS ============================================================================================= /* CNG BCrypt Functions https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/ */ class BCrypt { static hBCRYPT := DllCall("LoadLibrary", "str", "bcrypt.dll", "ptr") static STATUS_SUCCESS := 0 CloseAlgorithmProvider(hAlgorithm) { DllCall("bcrypt\BCryptCloseAlgorithmProvider", "ptr", hAlgorithm, "uint", 0) } CreateHash(hAlgorithm, hmac := 0, encoding := "utf-8") { if (hmac) cbSecret := Crypt.helper.StrPutVar(hmac, pbSecret, encoding) NT_STATUS := DllCall("bcrypt\BCryptCreateHash", "ptr", hAlgorithm , "ptr*", phHash , "ptr", pbHashObject := 0 , "uint", cbHashObject := 0 , "ptr", (pbSecret ? &pbSecret : 0) , "uint", (cbSecret ? cbSecret : 0) , "uint", dwFlags := 0) if (NT_STATUS = this.STATUS_SUCCESS) return phHash return false } DeriveKeyPBKDF2(hPrf, Password, Salt, cIterations, ByRef pbDerivedKey, cbDerivedKey, Encoding := "utf-8") { cbPassword := Crypt.Helper.StrPutVar(Password, pbPassword, Encoding) cbSalt := Crypt.Helper.StrPutVar(Salt, pbSalt, Encoding) VarSetCapacity(pbDerivedKey, cbDerivedKey, 0) NT_STATUS := DllCall("bcrypt\BCryptDeriveKeyPBKDF2", "ptr", hPrf , "ptr", &pbPassword , "uint", cbPassword , "ptr", &pbSalt , "uint", cbSalt , "int64", cIterations , "ptr", &pbDerivedKey , "uint", cbDerivedKey , "uint", dwFlags := 0) if (NT_STATUS = this.STATUS_SUCCESS) return true return false } DestroyHash(hHash) { DllCall("bcrypt\BCryptDestroyHash", "ptr", hHash) } DestroyKey(hKey) { DllCall("bcrypt\BCryptDestroyKey", "ptr", hKey) } Decrypt(hKey, ByRef String, cbInput, IV, BCRYPT_BLOCK_LENGTH, ByRef pbOutput, dwFlags) { VarSetCapacity(pbInput, cbInput, 0) DllCall("msvcrt\memcpy", "ptr", &pbInput, "ptr", &String, "ptr", cbInput) if (IV != "") { cbIV := VarSetCapacity(pbIV, BCRYPT_BLOCK_LENGTH, 0) StrPut(IV, &pbIV, BCRYPT_BLOCK_LENGTH, Encoding) } NT_STATUS := DllCall("bcrypt\BCryptDecrypt", "ptr", hKey , "ptr", &pbInput , "uint", cbInput , "ptr", 0 , "ptr", (pbIV ? &pbIV : 0) , "uint", (cbIV ? &cbIV : 0) , "ptr", 0 , "uint", 0 , "uint*", cbOutput , "uint", dwFlags) if (NT_STATUS = this.STATUS_SUCCESS) { VarSetCapacity(pbOutput, cbOutput, 0) NT_STATUS := DllCall("bcrypt\BCryptDecrypt", "ptr", hKey , "ptr", &pbInput , "uint", cbInput , "ptr", 0 , "ptr", (pbIV ? &pbIV : 0) , "uint", (cbIV ? &cbIV : 0) , "ptr", &pbOutput , "uint", cbOutput , "uint*", cbOutput , "uint", dwFlags) if (NT_STATUS = this.STATUS_SUCCESS) { return cbOutput } } return false } Encrypt(hKey, ByRef pbInput, cbInput, IV, BCRYPT_BLOCK_LENGTH, ByRef pbOutput, dwFlags := 0) { ;cbInput := Crypt.Helper.StrPutVar(String, pbInput, Encoding) if (IV != "") { cbIV := VarSetCapacity(pbIV, BCRYPT_BLOCK_LENGTH, 0) StrPut(IV, &pbIV, BCRYPT_BLOCK_LENGTH, Encoding) } NT_STATUS := DllCall("bcrypt\BCryptEncrypt", "ptr", hKey , "ptr", &pbInput , "uint", cbInput , "ptr", 0 , "ptr", (pbIV ? &pbIV : 0) , "uint", (cbIV ? &cbIV : 0) , "ptr", 0 , "uint", 0 , "uint*", cbOutput , "uint", dwFlags) if (NT_STATUS = this.STATUS_SUCCESS) { VarSetCapacity(pbOutput, cbOutput, 0) NT_STATUS := DllCall("bcrypt\BCryptEncrypt", "ptr", hKey , "ptr", &pbInput , "uint", cbInput , "ptr", 0 , "ptr", (pbIV ? &pbIV : 0) , "uint", (cbIV ? &cbIV : 0) , "ptr", &pbOutput , "uint", cbOutput , "uint*", cbOutput , "uint", dwFlags) if (NT_STATUS = this.STATUS_SUCCESS) { return cbOutput } } return false } EnumAlgorithms(dwAlgOperations) { NT_STATUS := DllCall("bcrypt\BCryptEnumAlgorithms", "uint", dwAlgOperations , "uint*", pAlgCount , "ptr*", ppAlgList , "uint", dwFlags := 0) if (NT_STATUS = this.STATUS_SUCCESS) { addr := ppAlgList, BCRYPT_ALGORITHM_IDENTIFIER := [] loop % pAlgCount { BCRYPT_ALGORITHM_IDENTIFIER[A_Index, "Name"] := StrGet(NumGet(addr + A_PtrSize * 0, "uptr"), "utf-16") BCRYPT_ALGORITHM_IDENTIFIER[A_Index, "Class"] := NumGet(addr + A_PtrSize * 1, "uint") BCRYPT_ALGORITHM_IDENTIFIER[A_Index, "Flags"] := NumGet(addr + A_PtrSize * 1 + 4, "uint") addr += A_PtrSize * 2 } return BCRYPT_ALGORITHM_IDENTIFIER } return false } EnumProviders(pszAlgId) { NT_STATUS := DllCall("bcrypt\BCryptEnumProviders", "ptr", pszAlgId , "uint*", pImplCount , "ptr*", ppImplList , "uint", dwFlags := 0) if (NT_STATUS = this.STATUS_SUCCESS) { addr := ppImplList, BCRYPT_PROVIDER_NAME := [] loop % pImplCount { BCRYPT_PROVIDER_NAME.Push(StrGet(NumGet(addr + A_PtrSize * 0, "uptr"), "utf-16")) addr += A_PtrSize } return BCRYPT_PROVIDER_NAME } return false } FinishHash(hHash, ByRef pbOutput, cbOutput) { VarSetCapacity(pbOutput, cbOutput, 0) NT_STATUS := DllCall("bcrypt\BCryptFinishHash", "ptr", hHash , "ptr", &pbOutput , "uint", cbOutput , "uint", dwFlags := 0) if (NT_STATUS = this.STATUS_SUCCESS) return cbOutput return false } GenerateSymmetricKey(hAlgorithm, Key, Encoding := "utf-8") { cbSecret := Crypt.Helper.StrPutVar(Key, pbSecret, Encoding) NT_STATUS := DllCall("bcrypt\BCryptGenerateSymmetricKey", "ptr", hAlgorithm , "ptr*", phKey , "ptr", 0 , "uint", 0 , "ptr", &pbSecret , "uint", cbSecret , "uint", dwFlags := 0) if (NT_STATUS = this.STATUS_SUCCESS) return phKey return false } GetProperty(hObject, pszProperty, cbOutput) { NT_STATUS := DllCall("bcrypt\BCryptGetProperty", "ptr", hObject , "ptr", &pszProperty , "uint*", pbOutput , "uint", cbOutput , "uint*", pcbResult , "uint", dwFlags := 0) if (NT_STATUS = this.STATUS_SUCCESS) return pbOutput return false } HashData(hHash, ByRef pbInput, cbInput) { NT_STATUS := DllCall("bcrypt\BCryptHashData", "ptr", hHash , "ptr", &pbInput , "uint", cbInput , "uint", dwFlags := 0) if (NT_STATUS = this.STATUS_SUCCESS) return true return false } OpenAlgorithmProvider(pszAlgId, dwFlags := 0, pszImplementation := 0) { NT_STATUS := DllCall("bcrypt\BCryptOpenAlgorithmProvider", "ptr*", phAlgorithm , "ptr", &pszAlgId , "ptr", pszImplementation , "uint", dwFlags) if (NT_STATUS = this.STATUS_SUCCESS) return phAlgorithm return false } SetProperty(hObject, pszProperty, pbInput) { bInput := StrLen(pbInput) NT_STATUS := DllCall("bcrypt\BCryptSetProperty", "ptr", hObject , "ptr", &pszProperty , "ptr", &pbInput , "uint", bInput , "uint", dwFlags := 0) if (NT_STATUS = this.STATUS_SUCCESS) return true return false } } class Helper { static hCRYPT32 := DllCall("LoadLibrary", "str", "crypt32.dll", "ptr") CryptBinaryToString(ByRef pbBinary, cbBinary, dwFlags := "BASE64") { static CRYPT_STRING := { "BASE64": 0x1, "BINARY": 0x2, "HEX": 0x4, "HEXRAW": 0xc } static CRYPT_STRING_NOCRLF := 0x40000000 if (DllCall("crypt32\CryptBinaryToString", "ptr", &pbBinary , "uint", cbBinary , "uint", (CRYPT_STRING[dwFlags] | CRYPT_STRING_NOCRLF) , "ptr", 0 , "uint*", pcchString)) { VarSetCapacity(pszString, pcchString << !!A_IsUnicode, 0) if (DllCall("crypt32\CryptBinaryToString", "ptr", &pbBinary , "uint", cbBinary , "uint", (CRYPT_STRING[dwFlags] | CRYPT_STRING_NOCRLF) , "ptr", &pszString , "uint*", pcchString)) { return StrGet(&pszString) } } return false } CryptStringToBinary(pszString, ByRef pbBinary, dwFlags := "BASE64") { static CRYPT_STRING := { "BASE64": 0x1, "BINARY": 0x2, "HEX": 0x4, "HEXRAW": 0xc } if (DllCall("crypt32\CryptStringToBinary", "ptr", &pszString , "uint", 0 , "uint", CRYPT_STRING[dwFlags] , "ptr", 0 , "uint*", pcbBinary , "ptr", 0 , "ptr", 0)) { VarSetCapacity(pbBinary, pcbBinary, 0) if (DllCall("crypt32\CryptStringToBinary", "ptr", &pszString , "uint", 0 , "uint", CRYPT_STRING[dwFlags] , "ptr", &pbBinary , "uint*", pcbBinary , "ptr", 0 , "ptr", 0)) { return pcbBinary } } return false } StrPutVar(String, ByRef Data, Encoding) { if (Encoding = "hex") { String := InStr(String, "0x") ? SubStr(String, 3) : String VarSetCapacity(Data, (Length := StrLen(String) // 2), 0) loop % Length NumPut("0x" SubStr(String, 2 * A_Index - 1, 2), Data, A_Index - 1, "char") return Length } else { VarSetCapacity(Data, Length := StrPut(String, Encoding) * ((Encoding = "utf-16" || Encoding = "cp1200") ? 2 : 1) - 1) return StrPut(String, &Data, Length, Encoding) } } } class Verify { ChainingMode(ChainMode) { switch ChainMode { case "CBC", "ChainingModeCBC": return Crypt.Constants.BCRYPT_CHAIN_MODE_CBC case "CFB", "ChainingModeCFB": return Crypt.Constants.BCRYPT_CHAIN_MODE_CFB case "ECB", "ChainingModeECB": return Crypt.Constants.BCRYPT_CHAIN_MODE_ECB default: return "" } } EncryptionAlgorithm(Algorithm) { switch Algorithm { case "AES": return Crypt.Constants.BCRYPT_AES_ALGORITHM case "DES": return Crypt.Constants.BCRYPT_DES_ALGORITHM case "RC2": return Crypt.Constants.BCRYPT_RC2_ALGORITHM case "RC4": return Crypt.Constants.BCRYPT_RC4_ALGORITHM default: return "" } } HashAlgorithm(Algorithm) { switch Algorithm { case "MD2": return Crypt.Constants.BCRYPT_MD2_ALGORITHM case "MD4": return Crypt.Constants.BCRYPT_MD4_ALGORITHM case "MD5": return Crypt.Constants.BCRYPT_MD5_ALGORITHM case "SHA1", "SHA-1": return Crypt.Constants.BCRYPT_SHA1_ALGORITHM case "SHA256", "SHA-256": return Crypt.Constants.BCRYPT_SHA256_ALGORITHM case "SHA384", "SHA-384": return Crypt.Constants.BCRYPT_SHA384_ALGORITHM case "SHA512", "SHA-512": return Crypt.Constants.BCRYPT_SHA512_ALGORITHM default: return "" } } } ; ===== CONSTANTS ===================================================================== class Constants { static BCRYPT_ALG_HANDLE_HMAC_FLAG := 0x00000008 static BCRYPT_BLOCK_PADDING := 0x00000001 ; AlgOperations flags for use with BCryptEnumAlgorithms() static BCRYPT_CIPHER_OPERATION := 0x00000001 static BCRYPT_HASH_OPERATION := 0x00000002 static BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION := 0x00000004 static BCRYPT_SECRET_AGREEMENT_OPERATION := 0x00000008 static BCRYPT_SIGNATURE_OPERATION := 0x00000010 static BCRYPT_RNG_OPERATION := 0x00000020 static BCRYPT_KEY_DERIVATION_OPERATION := 0x00000040 ; https://docs.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-identifiers static BCRYPT_3DES_ALGORITHM := "3DES" static BCRYPT_3DES_112_ALGORITHM := "3DES_112" static BCRYPT_AES_ALGORITHM := "AES" static BCRYPT_AES_CMAC_ALGORITHM := "AES-CMAC" static BCRYPT_AES_GMAC_ALGORITHM := "AES-GMAC" static BCRYPT_DES_ALGORITHM := "DES" static BCRYPT_DESX_ALGORITHM := "DESX" static BCRYPT_MD2_ALGORITHM := "MD2" static BCRYPT_MD4_ALGORITHM := "MD4" static BCRYPT_MD5_ALGORITHM := "MD5" static BCRYPT_RC2_ALGORITHM := "RC2" static BCRYPT_RC4_ALGORITHM := "RC4" static BCRYPT_RNG_ALGORITHM := "RNG" static BCRYPT_SHA1_ALGORITHM := "SHA1" static BCRYPT_SHA256_ALGORITHM := "SHA256" static BCRYPT_SHA384_ALGORITHM := "SHA384" static BCRYPT_SHA512_ALGORITHM := "SHA512" static BCRYPT_PBKDF2_ALGORITHM := "PBKDF2" static BCRYPT_XTS_AES_ALGORITHM := "XTS-AES" ; https://docs.microsoft.com/en-us/windows/win32/seccng/cng-property-identifiers static BCRYPT_BLOCK_LENGTH := "BlockLength" static BCRYPT_CHAINING_MODE := "ChainingMode" static BCRYPT_CHAIN_MODE_CBC := "ChainingModeCBC" static BCRYPT_CHAIN_MODE_CCM := "ChainingModeCCM" static BCRYPT_CHAIN_MODE_CFB := "ChainingModeCFB" static BCRYPT_CHAIN_MODE_ECB := "ChainingModeECB" static BCRYPT_CHAIN_MODE_GCM := "ChainingModeGCM" static BCRYPT_HASH_LENGTH := "HashDigestLength" static BCRYPT_OBJECT_LENGTH := "ObjectLength" } }
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。
评论(0)