CNG (Cryptography API: Next Generation)

Post your working scripts, libraries and tools
serzh82saratov
Posts: 130
Joined: 01 Jul 2017, 03:04

Re: CNG (Cryptography API: Next Generation)

06 Jan 2021, 13:56

Thank you. That is, it complicates hacking. But how reliable is a CBC 256 bit and an empty IV?
kyuuuri
Posts: 336
Joined: 09 Jan 2016, 19:20

Re: CNG (Cryptography API: Next Generation)

07 Jan 2021, 04:25

serzh82saratov wrote:
06 Jan 2021, 13:56
Thank you. That is, it complicates hacking. But how reliable is a CBC 256 bit and an empty IV?
That question is more related to cryptography than to this thread, remember that knowing how to use a function doesn't mean you know exactly how it works. Cryptography is very complex and requires a lot of time to learn why things are implemented the way they are, instead of copy pasting an answer from other site I will link you directly to it: https://crypto.stackexchange.com/questions/8600/why-should-i-use-an-initialization-vector-iv-when-i-have-unique-keys

Don't get me wrong, I'm not saying "you can't ask that here", I'm just saying that while there might be people here with good knowledge in cryptography this forum/thread is not dedicated to cryptography.
The cryptography stackexchange site is a good place to search that kind of questions.

Hope that helps
serzh82saratov
Posts: 130
Joined: 01 Jul 2017, 03:04

Re: CNG (Cryptography API: Next Generation)

07 Jan 2021, 06:23

Thanks for the good answer. I understand that cryptography is difficult, I would even say very much, so I am not looking for a truth here that I cannot understand. I just want to get public opinion.
DefrostedChemist
Posts: 2
Joined: 02 Feb 2021, 15:22

Re: CNG (Cryptography API: Next Generation)

02 Feb 2021, 16:08

Hello jNizM,

First and foremost, thank you for your effort putting Class_CNG together for use with AHK.

I have not gotten the examples to work, but I believe its due to something simple caused by my inexperience.

I'm running AHK version 1.1.32.00 and Win10. I'm using what I believe is the latest version of your Class_CNG.ahk code updated 04-Jan-2021 from github. (Though your September 2020 version gave me the same result.)

I attempted to run your String with AES + CBC and with Key + IV and Base64 encode/decode examples.
Quoted Examples

My test script was as follows:

Code: Select all

#Include Class_CNG_Jan2021.ahk
;Examples:
;;;;Encrypt a String with AES + CBC and with Key + IV and Base64 Output
MsgBox % Crypt.Encrypt.String("AES", "CBC", "abcdefghijklmnop", "1234567890123456", "1234567890123456")
;;;; -> Nn9CFFuC+/O84cV1NiwLYoyd25Z9nmWv16dIFKzf2b4=

;;;;Decrypt a String with AES + CBC and with Key + IV and Base64 Input
MsgBox % Crypt.Decrypt.String("AES", "CBC", "Nn9CFFuC+/O84cV1NiwLYoyd25Z9nmWv16dIFKzf2b4=", "1234567890123456", "1234567890123456")
;;;; -> abcdefghijklmnop
When running this, the encode works and gives the expected result, but the decode throws the following error.
Specifically:

Code: Select all

---------------------------
Encrypt_Test.ahk
---------------------------
Error in #include file "U:\AHK\EncodeDecode\Class_CNG_Jan2021.ahk":
     A12

	Line#
	411: DllCall("bcrypt\BCryptDestroyHash", "ptr", hHash)  
	412: }
	416: {
	417: DllCall("bcrypt\BCryptDestroyKey", "ptr", hKey)  
	418: }
	422: {
	423: VarSetCapacity(pbInput, cbInput, 0)  
--->	424: DllCall("msvcrt\memcpy", "ptr", &pbInput, "ptr", &String, "ptr", cbInput)  
	426: if (IV != "")  
	427: {
	428: cbIV := VarSetCapacity(pbIV, BCRYPT_BLOCK_LENGTH, 0)
	429: StrPut(IV, &pbIV, BCRYPT_BLOCK_LENGTH, Encoding)  
	430: }
	432: 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)
	442: if (NT_STATUS = this.STATUS_SUCCESS)  

The current thread will exit.
---------------------------
OK   
---------------------------
And below is the entirety of the lines run by my test script.

Code: Select all

---- U:\AHK\EncodeDecode\Class_CNG_Jan2021.ahk
364: Crypt.BCrypt.hBCRYPT := DllCall("LoadLibrary", "str", "bcrypt.dll", "ptr")  
365: Crypt.BCrypt.STATUS_SUCCESS := 0  
645: Crypt.Helper.hCRYPT32 := DllCall("LoadLibrary", "str", "crypt32.dll", "ptr")   (0.03)
649: CRYPT_STRING := { "BASE64": 0x1, "BINARY": 0x2, "HEX": 0x4, "HEXRAW": 0xc }
650: CRYPT_STRING_NOCRLF := 0x40000000
674: CRYPT_STRING := { "BASE64": 0x1, "BINARY": 0x2, "HEX": 0x4, "HEXRAW": 0xc }
771: Crypt.Constants.BCRYPT_ALG_HANDLE_HMAC_FLAG := 0x00000008  
772: Crypt.Constants.BCRYPT_BLOCK_PADDING := 0x00000001  
776: Crypt.Constants.BCRYPT_CIPHER_OPERATION := 0x00000001  
777: Crypt.Constants.BCRYPT_HASH_OPERATION := 0x00000002  
778: Crypt.Constants.BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION := 0x00000004  
779: Crypt.Constants.BCRYPT_SECRET_AGREEMENT_OPERATION := 0x00000008  
780: Crypt.Constants.BCRYPT_SIGNATURE_OPERATION := 0x00000010  
781: Crypt.Constants.BCRYPT_RNG_OPERATION := 0x00000020  
782: Crypt.Constants.BCRYPT_KEY_DERIVATION_OPERATION := 0x00000040  
786: Crypt.Constants.BCRYPT_3DES_ALGORITHM := "3DES"  
787: Crypt.Constants.BCRYPT_3DES_112_ALGORITHM := "3DES_112"  
788: Crypt.Constants.BCRYPT_AES_ALGORITHM := "AES"  
789: Crypt.Constants.BCRYPT_AES_CMAC_ALGORITHM := "AES-CMAC"  
790: Crypt.Constants.BCRYPT_AES_GMAC_ALGORITHM := "AES-GMAC"  
791: Crypt.Constants.BCRYPT_DES_ALGORITHM := "DES"  
792: Crypt.Constants.BCRYPT_DESX_ALGORITHM := "DESX"  
793: Crypt.Constants.BCRYPT_MD2_ALGORITHM := "MD2"  
794: Crypt.Constants.BCRYPT_MD4_ALGORITHM := "MD4"  
795: Crypt.Constants.BCRYPT_MD5_ALGORITHM := "MD5"  
796: Crypt.Constants.BCRYPT_RC2_ALGORITHM := "RC2"  
797: Crypt.Constants.BCRYPT_RC4_ALGORITHM := "RC4"  
798: Crypt.Constants.BCRYPT_RNG_ALGORITHM := "RNG"  
799: Crypt.Constants.BCRYPT_SHA1_ALGORITHM := "SHA1"  
800: Crypt.Constants.BCRYPT_SHA256_ALGORITHM := "SHA256"  
801: Crypt.Constants.BCRYPT_SHA384_ALGORITHM := "SHA384"  
802: Crypt.Constants.BCRYPT_SHA512_ALGORITHM := "SHA512"  
803: Crypt.Constants.BCRYPT_PBKDF2_ALGORITHM := "PBKDF2"  
804: Crypt.Constants.BCRYPT_XTS_AES_ALGORITHM := "XTS-AES"  
808: Crypt.Constants.BCRYPT_BLOCK_LENGTH := "BlockLength"  
809: Crypt.Constants.BCRYPT_CHAINING_MODE := "ChainingMode"  
810: Crypt.Constants.BCRYPT_CHAIN_MODE_CBC := "ChainingModeCBC"  
811: Crypt.Constants.BCRYPT_CHAIN_MODE_CCM := "ChainingModeCCM"  
812: Crypt.Constants.BCRYPT_CHAIN_MODE_CFB := "ChainingModeCFB"  
813: Crypt.Constants.BCRYPT_CHAIN_MODE_ECB := "ChainingModeECB"  
814: Crypt.Constants.BCRYPT_CHAIN_MODE_GCM := "ChainingModeGCM"  
815: Crypt.Constants.BCRYPT_HASH_LENGTH := "HashDigestLength"  
816: Crypt.Constants.BCRYPT_OBJECT_LENGTH := "ObjectLength"  
029: {
086: {
146: {
197: {
267: {
318: {
369: {
375: {
393: {
415: {
421: {
427: {
470: {
512: {
535: {
556: {
570: {
587: {
602: {
615: {
628: {
648: {
673: {
701: {
724: {
736: {
749: {
---- U:\AHK\EncodeDecode\Encrypt_Test.ahk
004: MsgBox,Crypt.Encrypt.String("AES", "CBC", "abcdefghijklmnop", "1234567890123456", "1234567890123456")
---- U:\AHK\EncodeDecode\Class_CNG_Jan2021.ahk
030: Try
033: if !(ALGORITHM_IDENTIFIER := Crypt.Verify.EncryptionAlgorithm(AlgId))  
737: Switch Algorithm
739: Return,Crypt.Constants.BCRYPT_AES_ALGORITHM
037: if !(ALG_HANDLE := Crypt.BCrypt.OpenAlgorithmProvider(ALGORITHM_IDENTIFIER))  
616: NT_STATUS := DllCall("bcrypt\BCryptOpenAlgorithmProvider", "ptr*", phAlgorithm, "ptr",  &pszAlgId, "ptr",  pszImplementation, "uint", dwFlags)
621: if (NT_STATUS = this.STATUS_SUCCESS)  
622: Return,phAlgorithm
041: if (CHAINING_MODE := Crypt.Verify.ChainingMode(Mode))  
725: Switch ChainMode
727: Return,Crypt.Constants.BCRYPT_CHAIN_MODE_CBC
043: if !(Crypt.BCrypt.SetProperty(ALG_HANDLE, Crypt.Constants.BCRYPT_CHAINING_MODE, CHAINING_MODE))  
629: bInput := StrLen(pbInput)
630: NT_STATUS := DllCall("bcrypt\BCryptSetProperty", "ptr",   hObject, "ptr",   &pszProperty, "ptr",   &pbInput, "uint",  bInput, "uint",  dwFlags := 0)
636: if (NT_STATUS = this.STATUS_SUCCESS)  
637: Return,true
047: if !(KEY_HANDLE := Crypt.BCrypt.GenerateSymmetricKey(ALG_HANDLE, Key, Encoding))  
571: cbSecret := Crypt.Helper.StrPutVar(Key, pbSecret, Encoding)
702: if (Encoding = "hex")  
712: VarSetCapacity(Data, Length := StrPut(String, Encoding) * ((Encoding = "utf-16" || Encoding = "cp1200") ? 2 : 1) - 1)  
713: Return,StrPut(String, &Data, Length, Encoding)
572: NT_STATUS := DllCall("bcrypt\BCryptGenerateSymmetricKey", "ptr",  hAlgorithm, "ptr*", phKey, "ptr",  0, "uint", 0, "ptr",  &pbSecret, "uint", cbSecret, "uint", dwFlags := 0)
580: if (NT_STATUS = this.STATUS_SUCCESS)  
581: Return,phKey
051: if !(BLOCK_LENGTH := Crypt.BCrypt.GetProperty(ALG_HANDLE, Crypt.Constants.BCRYPT_BLOCK_LENGTH, 4))  
588: NT_STATUS := DllCall("bcrypt\BCryptGetProperty", "ptr",   hObject, "ptr",   &pszProperty, "uint*", pbOutput, "uint",  cbOutput, "uint*", pcbResult, "uint",  dwFlags := 0)
595: if (NT_STATUS = this.STATUS_SUCCESS)  
596: Return,pbOutput
055: cbInput := Crypt.Helper.StrPutVar(String, pbInput, Encoding)
702: if (Encoding = "hex")  
712: VarSetCapacity(Data, Length := StrPut(String, Encoding) * ((Encoding = "utf-16" || Encoding = "cp1200") ? 2 : 1) - 1)  
713: Return,StrPut(String, &Data, Length, Encoding)
056: if !(CIPHER_LENGTH := Crypt.BCrypt.Encrypt(KEY_HANDLE, pbInput, cbInput, IV, BLOCK_LENGTH, CIPHER_DATA, Crypt.Constants.BCRYPT_BLOCK_PADDING))  
473: if (IV != "")  
475: cbIV := VarSetCapacity(pbIV, BCRYPT_BLOCK_LENGTH, 0)
476: StrPut(IV, &pbIV, BCRYPT_BLOCK_LENGTH, Encoding)  
477: }
479: 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, "
489: if (NT_STATUS = this.STATUS_SUCCESS)  
491: VarSetCapacity(pbOutput, cbOutput, 0)  
492: NT_STATUS := DllCall("bcrypt\BCryptEncrypt", "ptr",   hKey, "ptr",   &pbInput, "uint",  cbInput, "ptr",   0, "ptr",   (pbIV ? &pbIV : 0), "uint",  (cbIV ? &cbIV : 0), "ptr",   &pbOutput, "uint
502: if (NT_STATUS = this.STATUS_SUCCESS)  
504: Return,cbOutput
060: if !(ENCRYPT := Crypt.Helper.CryptBinaryToString(CIPHER_DATA, CIPHER_LENGTH, Output))  
652: if (DllCall("crypt32\CryptBinaryToString", "ptr",   &pbBinary, "uint",  cbBinary, "uint",  (CRYPT_STRING[dwFlags] | CRYPT_STRING_NOCRLF), "ptr",   0, "uint*", pcchString))  
658: VarSetCapacity(pszString, pcchString << !!A_IsUnicode, 0)  
659: if (DllCall("crypt32\CryptBinaryToString", "ptr",   &pbBinary, "uint",  cbBinary, "uint",  (CRYPT_STRING[dwFlags] | CRYPT_STRING_NOCRLF), "ptr",   &pszString, "uint*", pcchString))  
665: Return,StrGet(&pszString)
062: }
068: Finally
069: {
071: if (KEY_HANDLE)  
072: Crypt.BCrypt.DestroyKey(KEY_HANDLE)  
422: DllCall("bcrypt\BCryptDestroyKey", "ptr", hKey)  
423: }
074: if (ALG_HANDLE)  
075: Crypt.BCrypt.CloseAlgorithmProvider(ALG_HANDLE)  
370: DllCall("bcrypt\BCryptCloseAlgorithmProvider", "ptr", hAlgorithm, "uint", 0)  
371: }
076: }
077: Return,ENCRYPT (1.51)
---- U:\AHK\EncodeDecode\Encrypt_Test.ahk
008: MsgBox,Crypt.Decrypt.String("AES", "CBC", "Nn9CFFuC+/O84cV1NiwLYoyd25Z9nmWv16dIFKzf2b4=", "1234567890123456", "1234567890123456")
---- U:\AHK\EncodeDecode\Class_CNG_Jan2021.ahk
087: Try
090: if !(ALGORITHM_IDENTIFIER := Crypt.Verify.EncryptionAlgorithm(AlgId))  
737: Switch Algorithm
739: Return,Crypt.Constants.BCRYPT_AES_ALGORITHM
094: if !(ALG_HANDLE := Crypt.BCrypt.OpenAlgorithmProvider(ALGORITHM_IDENTIFIER))  
616: NT_STATUS := DllCall("bcrypt\BCryptOpenAlgorithmProvider", "ptr*", phAlgorithm, "ptr",  &pszAlgId, "ptr",  pszImplementation, "uint", dwFlags)
621: if (NT_STATUS = this.STATUS_SUCCESS)  
622: Return,phAlgorithm
098: if (CHAINING_MODE := Crypt.Verify.ChainingMode(Mode))  
725: Switch ChainMode
727: Return,Crypt.Constants.BCRYPT_CHAIN_MODE_CBC
100: if !(Crypt.BCrypt.SetProperty(ALG_HANDLE, Crypt.Constants.BCRYPT_CHAINING_MODE, CHAINING_MODE))  
629: bInput := StrLen(pbInput)
630: NT_STATUS := DllCall("bcrypt\BCryptSetProperty", "ptr",   hObject, "ptr",   &pszProperty, "ptr",   &pbInput, "uint",  bInput, "uint",  dwFlags := 0)
636: if (NT_STATUS = this.STATUS_SUCCESS)  
637: Return,true
104: if !(KEY_HANDLE := Crypt.BCrypt.GenerateSymmetricKey(ALG_HANDLE, Key, Encoding))  
571: cbSecret := Crypt.Helper.StrPutVar(Key, pbSecret, Encoding)
702: if (Encoding = "hex")  
712: VarSetCapacity(Data, Length := StrPut(String, Encoding) * ((Encoding = "utf-16" || Encoding = "cp1200") ? 2 : 1) - 1)  
713: Return,StrPut(String, &Data, Length, Encoding)
572: NT_STATUS := DllCall("bcrypt\BCryptGenerateSymmetricKey", "ptr",  hAlgorithm, "ptr*", phKey, "ptr",  0, "uint", 0, "ptr",  &pbSecret, "uint", cbSecret, "uint", dwFlags := 0)
580: if (NT_STATUS = this.STATUS_SUCCESS)  
581: Return,phKey
108: if !(CIPHER_LENGTH := Crypt.Helper.CryptStringToBinary(String, CIPHER_DATA, Input))  
676: if (DllCall("crypt32\CryptStringToBinary", "ptr",   &pszString, "uint",  0, "uint",  CRYPT_STRING[dwFlags], "ptr",   0, "uint*", pcbBinary, "ptr",   0, "ptr",   0))  
684: VarSetCapacity(pbBinary, pcbBinary, 0)  
685: if (DllCall("crypt32\CryptStringToBinary", "ptr",   &pszString, "uint",  0, "uint",  CRYPT_STRING[dwFlags], "ptr",   &pbBinary, "uint*", pcbBinary, "ptr",   0, "ptr",   0))  
693: Return,pcbBinary
112: if !(BLOCK_LENGTH := Crypt.BCrypt.GetProperty(ALG_HANDLE, Crypt.Constants.BCRYPT_BLOCK_LENGTH, 4))  
588: NT_STATUS := DllCall("bcrypt\BCryptGetProperty", "ptr",   hObject, "ptr",   &pszProperty, "uint*", pbOutput, "uint",  cbOutput, "uint*", pcbResult, "uint",  dwFlags := 0)
595: if (NT_STATUS = this.STATUS_SUCCESS)  
596: Return,pbOutput
116: if !(DECRYPT_LENGTH := Crypt.BCrypt.Decrypt(KEY_HANDLE, CIPHER_DATA, CIPHER_LENGTH, IV, BLOCK_LENGTH, DECRYPT_DATA, Crypt.Constants.BCRYPT_BLOCK_PADDING))  
428: VarSetCapacity(pbInput, cbInput, 0)  
429: DllCall("msvcrt\memcpy", "ptr", &pbInput, "ptr", &String, "ptr", cbInput)  
122: Catch,Exception
125: Throw,Exception (4.80)
Given this information, I'm hoping you can help me sort out what I'm doing wrong.

Many thanks in advance!

Edit: Corrected the "entirety of the lines run by my test script" section.
User avatar
jNizM
Posts: 2681
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: CNG (Cryptography API: Next Generation)

03 Feb 2021, 03:00

Your example works for me
Image
[AHK] 1.1.33.02 x64 Unicode | [WIN] 10 Pro (Version 20H2) x64 | [GitHub] Profile
Donations are appreciated if I could help you
DefrostedChemist
Posts: 2
Joined: 02 Feb 2021, 15:22

Re: CNG (Cryptography API: Next Generation)

04 Feb 2021, 13:05

Hi jNizM,

Thanks for your response. It must be something about my setup then.

To try and sort this out, I made one script that I could test on multiple machines. It consists of your decode example line followed by your 04-Jan-2021 Class_CGN code.

Code: Select all

MsgBox % Crypt.Decrypt.String("AES", "CBC", "Nn9CFFuC+/O84cV1NiwLYoyd25Z9nmWv16dIFKzf2b4=", "1234567890123456", "1234567890123456")
; ===============================================================================================================================
; 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"
	}
}
I get the following results on a couple different systems:
A 64-bit Win7 Ultimate install (Service Pack 1) on Intel i7-4770k with AHK version 1.1.30.01 (11-Nov-2018). ChainMode error likley due to older version of AHK
A 64-bit Win7 Ultimate install (Service Pack 1) on Intel i7-4770k with AHK version 1.1.33.02 (17-Jul-2020, Current). Same DLL error from previous post.
A 64-bit install of Win10 Enterprise (Up to date) on AMD Ryzen 7 Pro 3700U with AHK version 1.1.32.00 (23-Nov-2019). Same DLL error from previous post.
A 64-bit install of Win10 Enterprise LTSC (Up to date) on Intel Xeon W-2123 with AHK version 1.1.33.02 (17-Jul-2020, Current). Same DLL error from previous post.

After switching around to a couple software and hardware configurations and getting the same error, I'm back to having no idea what is going wrong.

I'm copying your Class_CNG.ahk directly from https raw.githubusercontent.com /jNizM/AHK_CNG/master/src/Class_CNG.ahk and your example directly from https://www.autohotkey.com/boards/viewtopic.php?p=109959#p109959 to generate the script in the above code block.
I tried generating the script by pasting into Notepad as well as Notepad++. Same error result for both cases.

Any ideas on what else I could try?
Also, could you please try the code in my codeblock above to rule out any issues with my test script?

Thank you for your patience and assistance with this issue!

Return to “Scripts and Functions”

Who is online

Users browsing this forum: emrekarahan0001, Haswell and 19 guests