CNG (Cryptography API: Next Generation)
-
- Posts: 137
- Joined: 01 Jul 2017, 03:04
Re: CNG (Cryptography API: Next Generation)
Thank you. That is, it complicates hacking. But how reliable is a CBC 256 bit and an empty IV?
Re: CNG (Cryptography API: Next Generation)
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-keysserzh82saratov wrote: ↑06 Jan 2021, 13:56Thank you. That is, it complicates hacking. But how reliable is a CBC 256 bit and an empty IV?
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
-
- Posts: 137
- Joined: 01 Jul 2017, 03:04
Re: CNG (Cryptography API: Next Generation)
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.
-
- Posts: 2
- Joined: 02 Feb 2021, 15:22
Re: CNG (Cryptography API: Next Generation)
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.
My test script was as follows:
When running this, the encode works and gives the expected result, but the decode throws the following error.
Specifically:
And below is the entirety of the lines run by my test script.
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.
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
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
---------------------------
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)
Many thanks in advance!
Edit: Corrected the "entirety of the lines run by my test script" section.
Re: CNG (Cryptography API: Next Generation)
Your example works for me
![Image](https://i.imgur.com/nFnVHux.png)
![Image](https://i.imgur.com/nFnVHux.png)
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
-
- Posts: 2
- Joined: 02 Feb 2021, 15:22
Re: CNG (Cryptography API: Next Generation)
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.
I get the following results on a couple different systems:
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!
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"
}
}
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!
-
- Posts: 104
- Joined: 07 Aug 2015, 15:53
Re: CNG (Cryptography API: Next Generation)
File encryption example?
Last edited by murataygun on 22 Jul 2021, 07:20, edited 1 time in total.
Re: CNG (Cryptography API: Next Generation)
Have you tried updating AHK?DefrostedChemist wrote: ↑04 Feb 2021, 13:05I get the following results on a couple different systems:
---------------------------
Decode_Test.ahk
---------------------------
Error at line 718.
Line Text: switch ChainMode
Error: This line does not contain a recognized action.
The program will exit.
---------------------------
OK
---------------------------
CNG Encrypt/Decrypt an Object
Hello @jNizM,
First, thank you for this most excellent library.
In the [Encrypting Data with CNG] section of your original post you noted:
Possible Inputs / Outputs
* Base64
* Hex / Hexraw
* Binary
Does this mean that an AutoHotkey Object could be encrypted/decrypted ?
I tried the test below and wondering if it is architecturally impossible for it to work because the object is actually a memory construct:
First, thank you for this most excellent library.
In the [Encrypting Data with CNG] section of your original post you noted:
Possible Inputs / Outputs
* Base64
* Hex / Hexraw
* Binary
Does this mean that an AutoHotkey Object could be encrypted/decrypted ?
I tried the test below and wondering if it is architecturally impossible for it to work because the object is actually a memory construct:
Code: Select all
#SingleInstance , Force
#Include Class_CNG.ahk
#Include <array_lib>
; >>>>> Encryption works | Decryption works <<<<<
testString = [ "a" , "b" , "c" ]
cryptInput := Crypt.Encrypt.String("AES", "CBC", testString , "1234567890123456", "1234567890123456")
MsgBox , 4096 , cryptInput , % cryptInput
cryptOutput := Crypt.Decrypt.String("AES", "CBC", cryptInput , "1234567890123456", "1234567890123456")
MsgBox , 4096 , cryptOutput , % cryptOutput
; >>>>> Encryption works | Decryption fails <<<<<
testObject := [ "a" , "b" , "c" ]
cryptInput := Crypt.Encrypt.String("AES", "CBC", testObject , "1234567890123456", "1234567890123456")
MsgBox , 4096 , cryptInput , % cryptInput
cryptOutput := Crypt.Decrypt.String("AES", "CBC", cryptInput , "1234567890123456", "1234567890123456")
Array_Gui( cryptOutput , "" ,, "cryptOutput" )
ExitApp
Re: CNG (Cryptography API: Next Generation)
jNizM, You have error in functions.
This
Should be like this
https://github.com/jNizM/AHK_CNG/blob/master/src/functions/bcrypt_md5.ahk#L43
This
Code: Select all
VarSetCapacity(pbInput, (StrPut(string, encoding) - 1) * ((encoding = "utf-16" || encoding = "cp1200") ? 2 : 1), 0) && cbInput := StrPut(string, &pbInput, encoding) - 1
Code: Select all
VarSetCapacity(pbInput, (StrPut(string, encoding) - 1) * ((encoding = "utf-16" || encoding = "cp1200") ? 2 : 1), 0) && cbInput := (StrPut(string, &pbInput, encoding) - 1) * ((encoding = "utf-16" || encoding = "cp1200") ? 2 : 1)
Re: CNG (Cryptography API: Next Generation)
@elmo im not sure, but I dont think this works like this. you need to loop throw the array and encrypt the array items itself. later you loop again and decrypt all the array items
@malcev fixed
@malcev fixed
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
-
- Posts: 3
- Joined: 27 Jan 2022, 22:29
Re: CNG (Cryptography API: Next Generation)
"BCryptOpenAlgorithmProvider failed" for every hash and encryption algorithm I've tried.
Runs fine on my home Windows 10. On my work computer, it fails with the above message. bcrypt.dll is in the expected location and has the same permissions as my home computer.
Any idea what could be preventing it from being able to use bcrypt.dll? I ran it as Administrator too, but that didn't help.
Runs fine on my home Windows 10. On my work computer, it fails with the above message. bcrypt.dll is in the expected location and has the same permissions as my home computer.
Any idea what could be preventing it from being able to use bcrypt.dll? I ran it as Administrator too, but that didn't help.
Re: CNG (Cryptography API: Next Generation)
@ZizzyZizzy can you link to the one you tried?
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
-
- Posts: 3
- Joined: 27 Jan 2022, 22:29
Re: CNG (Cryptography API: Next Generation)
I tried the one attached to the very first post here, I also tried this one:
https://github.com/jNizM/AHK_CNG/tree/master/src/v1.1_deprecated
It's just odd that it works perfectly on my home Windows 10 and not my Work laptop running the same version.
Oh, and I also tried copying bcrypt.dll to the same working dir as the script. That didn't work either.
-
- Posts: 3
- Joined: 27 Jan 2022, 22:29
Re: CNG (Cryptography API: Next Generation)
Well clearly I didn't READ the instructions, so I never ran Installer.ahk in the installed folder.ZizzyZizzy wrote: ↑28 Jan 2022, 10:35I tried the one attached to the very first post here, I also tried this one:
https://github.com/jNizM/AHK_CNG/tree/master/src/v1.1_deprecated
It's just odd that it works perfectly on my home Windows 10 and not my Work laptop running the same version.
Oh, and I also tried copying bcrypt.dll to the same working dir as the script. That didn't work either.
Once I replaced the AuotHotkey.exe with AutoHotkeyU64.exe, the problem was solved.
Re: CNG (Cryptography API: Next Generation)
Masonjar13 wrote: ↑05 Oct 2016, 04:34Ah, alright. Thanks for clearing that up. In that case, however, you still call BCryptDestroyHash() in the W10 versions, making it redundant, yes?
My operating system is Windows 7 64-bit.AHK is to install V1.1.34.02
I want to use the AES CBC for decryption.
Code: Select all
t:= Decrypt.String("AES", "CBC", "Nn9CFFuC+/O84cV1NiwLYoyd25Z9nmWv16dIFKzf2b4=", "1234567890123456", "1234567890123456")
Do want to run this code separately as AHK?
Or do want to put this into "class_cng.ahk"?
Thanks!
- Attachments
-
- 2022-08-09_13-22-47.png (49.47 KiB) Viewed 2763 times
Re: CNG (Cryptography API: Next Generation)
according to your error message, you are trying to use the v2 version of the CNG library, but your installed AHK version is 1.1.34.02lwx228 wrote: ↑09 Aug 2022, 00:30Masonjar13 wrote: ↑05 Oct 2016, 04:34Ah, alright. Thanks for clearing that up. In that case, however, you still call BCryptDestroyHash() in the W10 versions, making it redundant, yes?
My operating system is Windows 7 64-bit.AHK is to install V1.1.34.02
I want to use the AES CBC for decryption.
How would write AHK to implement the functionality of this Github example?Code: Select all
t:= Decrypt.String("AES", "CBC", "Nn9CFFuC+/O84cV1NiwLYoyd25Z9nmWv16dIFKzf2b4=", "1234567890123456", "1234567890123456")
Do want to run this code separately as AHK?
Or do want to put this into "class_cng.ahk"?
Thanks!
so you should use this version of the library instead:
https://github.com/jNizM/AHK_CNG/blob/master/src/v1.1_deprecated/Class_CNG.ahk
Re: CNG (Cryptography API: Next Generation)
guest3456 wrote: ↑09 Aug 2022, 09:05according to your error message, you are trying to use the v2 version of the CNG library, but your installed AHK version is 1.1.34.02lwx228 wrote: ↑09 Aug 2022, 00:30Masonjar13 wrote: ↑05 Oct 2016, 04:34Ah, alright. Thanks for clearing that up. In that case, however, you still call BCryptDestroyHash() in the W10 versions, making it redundant, yes?
My operating system is Windows 7 64-bit.AHK is to install V1.1.34.02
I want to use the AES CBC for decryption.
How would write AHK to implement the functionality of this Github example?Code: Select all
t:= Decrypt.String("AES", "CBC", "Nn9CFFuC+/O84cV1NiwLYoyd25Z9nmWv16dIFKzf2b4=", "1234567890123456", "1234567890123456")
Do want to run this code separately as AHK?
Or do want to put this into "class_cng.ahk"?
Thanks!
so you should use this version of the library instead:
https://github.com/jNizM/AHK_CNG/blob/master/src/v1.1_deprecated/Class_CNG.ahk
Yes, I'm already writing code and running it using version V1.
The V2 version above is just to show that I am currently using V 1.1.34.2.
I know how to code and run code using version V1.
But is it correct to code and this way?I just added a line on the AHK of V1 version you provided. Is that all right?
Thank you very much!I mainly don't understand here (Win 7 64-bit)
Re: CNG (Cryptography API: Next Generation)
its not correct or incorrect. its your choice
typically the standard procedure would be to write your code in a separate file, and have an #include statement either at the top or bottom, which would include the library file. you'd have to take care to either put your new script file in the same folder as the library file, or put the library file in a proper include directory. see here:
https://www.autohotkey.com/docs/commands/_Include.htm
if you scroll up early in the thread you will see people utilizing #include in their test scripts like here:
viewtopic.php?p=379770#p379770
Re: CNG (Cryptography API: Next Generation)
OK!its not correct or incorrect. its your choice
typically the standard procedure would be to write your code in a separate file, and have an #include statement either at the top or bottom, which would include the library file. you'd have to take care to either put your new script file in the same folder as the library file, or put the library file in a proper include directory. see here:
https://www.autohotkey.com/docs/commands/_Include.htm
if you scroll up early in the thread you will see people utilizing #include in their test scripts like here:
viewtopic.php?p=379770#p379770
Thanks!
- Attachments
-
- 2022-08-11_21-35-03.png (15.33 KiB) Viewed 2533 times