CNG (Cryptography API: Next Generation)
Re: CNG (Cryptography API: Next Generation)
Since the library uses advapi32.dll to generate hashes, I am worried that maybe different Windows systems will have different versions of advapi32.dll in their System32 folder, which might use slightly different implementation, causing a different hash to be generated, which would break my entire app.
Is this a legitimate concern or am I being too OCD? Should I copy advapi32.dll into my A_ScriptDir to force it to use that version instead of the one in System32 which could be different between systems. edit: and is that even legal from a copyright point?
Is this a legitimate concern or am I being too OCD? Should I copy advapi32.dll into my A_ScriptDir to force it to use that version instead of the one in System32 which could be different between systems. edit: and is that even legal from a copyright point?
Re: CNG (Cryptography API: Next Generation)
pneumatic,
Every implementation of a given hash function (say, SHA256) must give the same hash, under any OS, under any circumstance. If it does not, the implementation is faulty.
Every implementation of a given hash function (say, SHA256) must give the same hash, under any OS, under any circumstance. If it does not, the implementation is faulty.
Re: CNG (Cryptography API: Next Generation)
Yes, that does make sense.
I guess one other worry I have is that different versions of that dll might use different format parameters to the functions, like maybe an Int64 instead of an Int, or return an address instead of a Ptr to an address, and then my whole app breaks on that system.
But I doubt it, because Microsoft would know that doing stuff like that would break so many apps!
I think it should be fine. My goal is to prevent download aggregator sites from packing their own malware into my compiled ahk exe (or vice versa) by verifying the hash of the exe.
Re: CNG (Cryptography API: Next Generation)
1. The lib uses bcrypt.dll and not advapi32.dll
2. Every correct implementation of a hash function gives the same results on every OS / WEB
2. Every correct implementation of a hash function gives the same results on every OS / WEB
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: CNG (Cryptography API: Next Generation)
Hello, I'm trying to use your AES encryption / decryption class.
I want to move it to only 2 functions, 1 for decryption and 1 for encryption but I encountered an error I couldn't fix:
Code 1:
Output: f1461877468516263ea376f8588c8bc0c1413ca7712f9d4d5e624b95 Incorrect
Expected: f1461877468516263ea376f8588c8bc0c1413ca7712f9d4d5e624b95efda69c5
Code 2:
Output: f1461877468516263ea376f8588c8bc0c1413ca7712f9d4d5e624b95efda69c5 Correct
Expected: f1461877468516263ea376f8588c8bc0c1413ca7712f9d4d5e624b95efda69c5
For some reason in Code 1 the output is shorter, it's the same hash but with missing characters.
On Code 1: CIPHER_LENGTH = 112 Incorrect
On Code 2: CIPHER_LENGTH = 128 Correct
I don't know what's the problem there. I simply moved the DllCall inside the function and replaced the parameters with the real variables.
Thanks in advance.
I want to move it to only 2 functions, 1 for decryption and 1 for encryption but I encountered an error I couldn't fix:
Code 1:
Code: Select all
hash := "f1461877468516263ea376f8588c8bc0c1413ca7712f9d4d5e624b95efda69c5"
VarSetCapacity(str, 128)
StrPut(hash, &str)
str := encrypt(hash, "1234567890123456", "431GddAtuifssBogjCkgdoswMasegvsA5fkd8/*4-fa@#d")
msgbox % decrypt(str, "1234567890123456", "431GddAtuifssBogjCkgdoswMasegvsA5fkd8/*4-fa@#d", 128)
return
decrypt(string, iv, key, len)
{
global
static BCRYPT_AES_ALGORITHM := "AES"
static BCRYPT_OBJECT_LENGTH := "ObjectLength"
static BCRYPT_BLOCK_LENGTH := "BlockLength"
static BCRYPT_CHAINING_MODE := "ChainingMode"
static BCRYPT_CHAIN_MODE_CBC := "ChainingModeCBC"
static BCRYPT_OPAQUE_KEY_BLOB := "OpaqueKeyBlob"
static BCRYPT_BLOCK_PADDING := 0x00000001
static hBCRYPT := DllCall("LoadLibrary", "str", "bcrypt.dll", "ptr")
DllCall("bcrypt\BCryptOpenAlgorithmProvider", "ptr*", ALG_HANDLE, "ptr", &BCRYPT_AES_ALGORITHM, "ptr", 0, "uint", 0)
DllCall("bcrypt\BCryptGetProperty", "ptr", ALG_HANDLE, "ptr", &BCRYPT_OBJECT_LENGTH, "uint*", OBJECT_LENGTH, "uint", 4, "uint*", cbResult, "uint", 0)
DllCall("bcrypt\BCryptGetProperty", "ptr", ALG_HANDLE, "ptr", &BCRYPT_BLOCK_LENGTH, "uint*", BLOCK_LENGTH, "uint", 4, "uint*", cbResult, "uint", 0)
DllCall("bcrypt\BCryptSetProperty", "ptr", ALG_HANDLE, "ptr", &BCRYPT_CHAINING_MODE, "ptr", &BCRYPT_CHAIN_MODE_CBC, "uint", StrLen(BCRYPT_CHAIN_MODE_CBC), "uint", 0)
VarSetCapacity(KEY_OBJECT, OBJECT_LENGTH, 0)
VarSetCapacity(pbSecret, cbSecret := StrPut(KEY, "UTF-8"), 0) && StrPut(KEY, &pbSecret, "UTF-8"), cbSecret--
DllCall("bcrypt\BCryptGenerateSymmetricKey", "ptr", ALG_HANDLE, "ptr*", KEY_HANDLE, "ptr", &KEY_OBJECT, "uint", OBJECT_LENGTH, "ptr", &pbSecret, "uint", cbSecret, "uint", 0)
VarSetCapacity(pbInput, len, 0)
DllCall("msvcrt\memcpy", "ptr", &pbInput, "ptr", &string, "ptr", len)
VarSetCapacity(pbIV, BLOCK_LENGTH, 0)
DllCall("msvcrt\memcpy", "ptr", &pbIV, "ptr", &iv, "ptr", BLOCK_LENGTH)
DllCall("bcrypt\BCryptDecrypt", "ptr", KEY_HANDLE, "ptr", &pbInput, "uint", len, "ptr", 0, "ptr", &pbIV, "uint", BLOCK_LENGTH, "ptr", 0, "uint", 0, "uint*", CIPHER_LENGTH, "uint", BCRYPT_BLOCK_PADDING)
VarSetCapacity(CIPHER_DATA, CIPHER_LENGTH, 0)
; The next line is the only one that differs from Code2
DllCall("bcrypt\BCryptDecrypt", "ptr", KEY_HANDLE, "ptr", &pbInput, "uint", len, "ptr", 0, "ptr", &pbIV, "uint", BLOCK_LENGTH, "ptr", &CIPHER_DATA, "uint", CIPHER_LENGTH, "uint*", CIPHER_LENGTH, "uint", BCRYPT_BLOCK_PADDING)
DllCall("bcrypt.dll\BCryptDestroyKey", "ptr", KEY_HANDLE)
DllCall("bcrypt\BCryptCloseAlgorithmProvider", "ptr", ALG_HANDLE, "uint", 0)
return StrGet(&CIPHER_DATA, CIPHER_LENGTH /= 2, "utf-16")
}
Expected: f1461877468516263ea376f8588c8bc0c1413ca7712f9d4d5e624b95efda69c5
Code 2:
Code: Select all
hash := "f1461877468516263ea376f8588c8bc0c1413ca7712f9d4d5e624b95efda69c5"
VarSetCapacity(str, 128)
StrPut(hash, &str)
str := encrypt(hash, "1234567890123456", "431GddAtuifssBogjCkgdoswMasegvsA5fkd8/*4-fa@#d")
msgbox % decrypt(str, "1234567890123456", "431GddAtuifssBogjCkgdoswMasegvsA5fkd8/*4-fa@#d", 128)
return
decrypt(string, iv, key, len)
{
global
static BCRYPT_AES_ALGORITHM := "AES"
static BCRYPT_OBJECT_LENGTH := "ObjectLength"
static BCRYPT_BLOCK_LENGTH := "BlockLength"
static BCRYPT_CHAINING_MODE := "ChainingMode"
static BCRYPT_CHAIN_MODE_CBC := "ChainingModeCBC"
static BCRYPT_OPAQUE_KEY_BLOB := "OpaqueKeyBlob"
static BCRYPT_BLOCK_PADDING := 0x00000001
static hBCRYPT := DllCall("LoadLibrary", "str", "bcrypt.dll", "ptr")
DllCall("bcrypt\BCryptOpenAlgorithmProvider", "ptr*", ALG_HANDLE, "ptr", &BCRYPT_AES_ALGORITHM, "ptr", 0, "uint", 0)
DllCall("bcrypt\BCryptGetProperty", "ptr", ALG_HANDLE, "ptr", &BCRYPT_OBJECT_LENGTH, "uint*", OBJECT_LENGTH, "uint", 4, "uint*", cbResult, "uint", 0)
DllCall("bcrypt\BCryptGetProperty", "ptr", ALG_HANDLE, "ptr", &BCRYPT_BLOCK_LENGTH, "uint*", BLOCK_LENGTH, "uint", 4, "uint*", cbResult, "uint", 0)
DllCall("bcrypt\BCryptSetProperty", "ptr", ALG_HANDLE, "ptr", &BCRYPT_CHAINING_MODE, "ptr", &BCRYPT_CHAIN_MODE_CBC, "uint", StrLen(BCRYPT_CHAIN_MODE_CBC), "uint", 0)
VarSetCapacity(KEY_OBJECT, OBJECT_LENGTH, 0)
VarSetCapacity(pbSecret, cbSecret := StrPut(KEY, "UTF-8"), 0) && StrPut(KEY, &pbSecret, "UTF-8"), cbSecret--
DllCall("bcrypt\BCryptGenerateSymmetricKey", "ptr", ALG_HANDLE, "ptr*", KEY_HANDLE, "ptr", &KEY_OBJECT, "uint", OBJECT_LENGTH, "ptr", &pbSecret, "uint", cbSecret, "uint", 0)
VarSetCapacity(pbInput, len, 0)
DllCall("msvcrt\memcpy", "ptr", &pbInput, "ptr", &string, "ptr", len)
VarSetCapacity(pbIV, BLOCK_LENGTH, 0)
DllCall("msvcrt\memcpy", "ptr", &pbIV, "ptr", &iv, "ptr", BLOCK_LENGTH)
DllCall("bcrypt\BCryptDecrypt", "ptr", KEY_HANDLE, "ptr", &pbInput, "uint", len, "ptr", 0, "ptr", &pbIV, "uint", BLOCK_LENGTH, "ptr", 0, "uint", 0, "uint*", CIPHER_LENGTH, "uint", BCRYPT_BLOCK_PADDING)
VarSetCapacity(CIPHER_DATA, CIPHER_LENGTH, 0)
CIPHER_LENGTH := BCryptDecrypt(KEY_HANDLE, string, len, IV, BLOCK_LENGTH, CIPHER_DATA)
DllCall("bcrypt.dll\BCryptDestroyKey", "ptr", KEY_HANDLE)
DllCall("bcrypt\BCryptCloseAlgorithmProvider", "ptr", ALG_HANDLE, "uint", 0)
return StrGet(&CIPHER_DATA, CIPHER_LENGTH /= 2, "utf-16")
}
BCryptDecrypt(BCRYPT_KEY_HANDLE, ByRef STRING, cbInput, IV, cbIV, ByRef pbOutput)
{
global
if (NT_STATUS := DllCall("bcrypt\BCryptDecrypt", "ptr", BCRYPT_KEY_HANDLE
, "ptr", &pbInput
, "uint", cbInput
, "ptr", 0
, "ptr", &pbIV
, "uint", cbIV
, "ptr", &pbOutput
, "uint", CIPHER_LENGTH
, "uint*", CIPHER_LENGTH
, "uint", BCRYPT_BLOCK_PADDING) != 0)
throw Exception("BCryptDecrypt: " NT_STATUS, -1)
return CIPHER_LENGTH
}
Expected: f1461877468516263ea376f8588c8bc0c1413ca7712f9d4d5e624b95efda69c5
For some reason in Code 1 the output is shorter, it's the same hash but with missing characters.
On Code 1: CIPHER_LENGTH = 112 Incorrect
On Code 2: CIPHER_LENGTH = 128 Correct
I don't know what's the problem there. I simply moved the DllCall inside the function and replaced the parameters with the real variables.
Thanks in advance.
Re: CNG (Cryptography API: Next Generation)
it looks like the hashes are returned as a string.. but if we want to extend this lib to support public/private key signatures, we need the raw pointer (pbHash) and length (cbHash) values.. wonder if those should be returned ByRef..
Re: CNG (Cryptography API: Next Generation)
Update:
Almost finished with the rewriting of the class.
String Encryption / Decryption works so far. Output and Input can be Base64, Hex and Hexraw. Will also add address as output.
Almost finished with the rewriting of the class.
String Encryption / Decryption works so far. Output and Input can be Base64, Hex and Hexraw. Will also add address as output.
Code: Select all
Tested Encryption Modes and compared to online tools:
String: abcdefghijklmnop
Key: 1234567890123456
IV: 1234567890123456
AES: /K1xW9c7XLBIj4QPO614iYgkP6qA8mq6P5BuTJlpxHY=
AES + ECB: /K1xW9c7XLBIj4QPO614iQUBh6DN5amHLLqwkatz5VM=
AES + CBC: /K1xW9c7XLBIj4QPO614iYgkP6qA8mq6P5BuTJlpxHY=
AES + CBC + IV: Nn9CFFuC+/O84cV1NiwLYoyd25Z9nmWv16dIFKzf2b4=
AES + CFB: ubiN18vgxzKBhLW8KTbOg+Q58WBFqUOIxJ7h4wM+rZo=
AES + CFB + IV: FKUzKP7ugBs+5nsv1if+oOFtnUmtoktyxF+i+7qLxW8=
DES: lNRDa8O1tpMGxRfbSbuOmWecXPe5GjQY
DES + ECB: lNRDa8O1tpO7mzmIt78IUP65WbfUZC/L
DES + CBC: lNRDa8O1tpMGxRfbSbuOmWecXPe5GjQY
RC2: 403xbnkYjoJLMcGIwOQJqhE4Mhc4HfkE
RC4: QdLw1UGDq+F6q3SI5ZqwiQ==
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: CNG (Cryptography API: Next Generation)
Update:
Github updated
Initial Forum Post updated
2nd and 3rd Forum Post (examples) updated.
Feel free to test the rewritten post and report bugs or issues here.
Function I used to create Files with random bytes for testings
That might have cost me a few nerves (german saying)
Github updated
Initial Forum Post updated
2nd and 3rd Forum Post (examples) updated.
Feel free to test the rewritten post and report bugs or issues here.
Function I used to create Files with random bytes for testings
Code: Select all
CreateRandomBytesFile("test_2MB", 2097152)
CreateRandomBytesFile(file, bytes) {
if (f := FileOpen(file, "w", "utf-8")) {
f.Pos(0)
while(f.Length < bytes) {
Random, rand, 0, 255
f.Write(Chr(rand))
}
f.Close()
return true
}
return false
}
That might have cost me a few nerves (german saying)
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: CNG (Cryptography API: Next Generation)
Could this possibly be used to replicate TLS v1.2 or v1.3 protocol over socket connections?
« AHK Portable Installer » | « CallTipsForAll » | « TheArkive AHK v1 Scripts » | « TheArkive AHK v2 Scrpts » | « TheArkive on GitHub »
Re: CNG (Cryptography API: Next Generation)
Hi!
I'm having issues trying to replicate a SHA1 value, what can be wrong? Thanks in advance
Expected: 96b1be00bda9c81cfc4a58f0ad9ff12f5ece03ef
References:
I'm having issues trying to replicate a SHA1 value, what can be wrong? Thanks in advance
Code: Select all
key := "48656c6c6f21deadbeef"
data := "000000000273ef07"
hmac := bcrypt_sha1_hmac(data, key)
; -> 387da26a70023b017fa0e8f57999ef6cd1a818fb
References:
- https://caligatio.github.io/jsSHA/
- https://i.imgur.com/eNxO5zR.png
Last edited by user16749 on 02 Jan 2021, 07:25, edited 1 time in total.
Re: CNG (Cryptography API: Next Generation)
Hello, the result matches for me. I get 387da26a70023b017fa0e8f57999ef6cd1a818fb on the script and the webpage, where did you get the expected value from?
Try this website: https://www.freeformatter.com/hmac-generator.html#ad-output
Try this website: https://www.freeformatter.com/hmac-generator.html#ad-output
Re: CNG (Cryptography API: Next Generation)
Yes I get the same result as you but is wrong. Check the references I provided (just updated the image as imgur took it down). In the past I've used jsSHA and seems ok, never had an interoperability issue. Now the part I'm trying to do in AHK must match the one made with jsSHA (I didn't write the JS part, just consuming it).
Re: CNG (Cryptography API: Next Generation)
Hi, the result is not wrong. If you use hmac with sha1 the correct result is: 387da26a70023b017fa0e8f57999ef6cd1a818fb. Where did you get this "96b1be00bda9c81cfc4a58f0ad9ff12f5ece03ef" from?user16749 wrote: ↑02 Jan 2021, 07:29Yes I get the same result as you but is wrong. Check the references I provided (just updated the image as imgur took it down). In the past I've used jsSHA and seems ok, never had an interoperability issue. Now the part I'm trying to do in AHK must match the one made with jsSHA (I didn't write the JS part, just consuming it).
https://caligatio.github.io/jsSHA/
https://www.freeformatter.com/hmac-generator.html
https://codebeautify.org/hmac-generator
All these sites, even the script output 387da26a70023b017fa0e8f57999ef6cd1a818fb which is the correct result.
Edit: Now I see your image, you selected "hex" and it's not hex input, it's text.
Re: CNG (Cryptography API: Next Generation)
Yes it has to be hex, those are bytes not text. And I guess that's the issue with AHK implementation.. I've tried all the possible combinations with `0x##` and I get different hashes but never the expected.
Re: CNG (Cryptography API: Next Generation)
updated the class
MsgBox % Crypt.Hash.HMAC("SHA1", "000000000273ef07", "48656c6c6f21deadbeef", "hex") returns now 96b1be00bda9c81cfc4a58f0ad9ff12f5ece03ef
MsgBox % Crypt.Hash.HMAC("SHA1", 0x000000000273ef07, 0x48656c6c6f21deadbeef, "hex") is also possible
MsgBox % Crypt.Hash.HMAC("SHA1", "000000000273ef07", "48656c6c6f21deadbeef", "hex") returns now 96b1be00bda9c81cfc4a58f0ad9ff12f5ece03ef
MsgBox % Crypt.Hash.HMAC("SHA1", 0x000000000273ef07, 0x48656c6c6f21deadbeef, "hex") is also possible
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
-
- Posts: 137
- Joined: 01 Jul 2017, 03:04
Re: CNG (Cryptography API: Next Generation)
Code: Select all
Encrypt := Crypt.Encrypt.String("AES", "CBC", "abcdefghijklmnop abcdefghijklmnop", "1234567890123456", "1234567890123456")
MsgBox % Crypt.Decrypt.String("AES", "CBC", Encrypt, "1234567890123456", "123")
-
- Posts: 137
- Joined: 01 Jul 2017, 03:04
Re: CNG (Cryptography API: Next Generation)
I'll try to ask my question in a different way. Why do you need a second key if you can easily recover data without it?
Code: Select all
text =
(
abcdefghijklmnop
abcdefghijklmnop
abcdefghijklmnop
abcdefghijklmnop
abcdefghijklmnop
abcdefghijklmnop
abcdefghijklmnop
abcdefghijklmnop
)
Encrypt := Crypt.Encrypt.String("AES", "CBC", text, "1234567890123456", "qwerty")
MsgBox % Crypt.Decrypt.String("AES", "CBC", Encrypt, "1234567890123456", "")
Re: CNG (Cryptography API: Next Generation)
Hello, it's not a second key, it's an Initialization vector. You can read more about it here: https://en.wikipedia.org/wiki/Initialization_vectorserzh82saratov wrote: ↑06 Jan 2021, 08:00I'll try to ask my question in a different way. Why do you need a second key if you can easily recover data without it?Code: Select all
text = ( abcdefghijklmnop abcdefghijklmnop abcdefghijklmnop abcdefghijklmnop abcdefghijklmnop abcdefghijklmnop abcdefghijklmnop abcdefghijklmnop ) Encrypt := Crypt.Encrypt.String("AES", "CBC", text, "1234567890123456", "qwerty") MsgBox % Crypt.Decrypt.String("AES", "CBC", Encrypt, "1234567890123456", "")