How is CryptAES() supposed to be used? Is this a bug? Topic is solved

Ask for help, how to use AHK_H, etc.
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

How is CryptAES() supposed to be used? Is this a bug?

01 Feb 2019, 12:36

Using latest version Ahk_h v1 from GitHub. W10 64 bits.

I have this script:

Code: Select all

; prep
VarSetCapacity(str, 128) ; Strlen*2 due to unicode
len := StrPut("testingstringthatcontains64characters123456885464562132132222452", &str)
fileappend % StrGet(&str) "`n", result.txt, UTF-16
; encrypt
loop, 100
{
	size := CryptAES(str, len*2, "asd", true) ; len*2 due to unicode
	fileappend % StrGet(&str) "`n", result.txt, UTF-16
	fileappend % size "`n", result.txt, UTF-16
}
; decrypt
CryptAES(str, size, "asd", false)
fileappend % StrGet(&str) "`n", result.txt, UTF-16

CryptAES(ByRef lp,sz,pw,e:=1,SID:=256){
	static AES_128:=0x660E,AES_192:=1+AES_128,AES_256:=1+AES_192,SHA1:=1+0x8003 ; MD5
	If !DllCall("Advapi32\CryptAcquireContext","Ptr*",hP,"Uint",0,"Uint",0,"Uint",24,"UInt",0xF0000000) ;PROV_RSA_AES, CRYPT_VERIFYCONTEXT
	|| !DllCall("Advapi32\CryptCreateHash","Ptr",hP,"Uint",SHA1,"Uint",0,"Uint",0,"Ptr*",H )
	|| !CryptHashData(H,&pw,StrLen(pw)*2,0)
	|| !CryptDeriveKey(hP,AES_%SID%,H,SID<<16,getvar(hK:=0))
	|| !CryptDestroyHash(H)
		return 0
	if e
		CryptEncrypt(hK,0,1,0,&lp,getvar(sz),sz+16)
	else
		CryptDecrypt(hK,0,1,0,&lp,getvar(sz))
	CryptDestroyKey(hK),CryptReleaseContext(hP,0)
	return sz
}
Problems I found:
1. It never reaches the 100 repetitions, the script closes itself after a random amount.
2. All results are different and when I try to decrypt them (reading it from another script) the output is not even close to the input.
3. Sometimes it outputs weird things like for example:
㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒�霢嶌气�娝ͳ�퍧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹�ਇଂ⺅裢旌흆鐐鷻郴㪶幡\??\G:\Desktop\test10.ahk
That's the path to my script.

For example:
Output from first script (without the loop, 100):

Code: Select all

testingstringthatcontains64characters123456885464562132132222452
㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒�霢嶌气�娝ͳ�퍧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹�ਇଂ⺅裢旌흆鐐鷻郴㪶幡
144
testingstringthatcontains64characters123456885464562132132222452
Now using the second line on that output (the encrypted string):

Code: Select all

VarSetCapacity(str, 128) ; Strlen*2 due to unicode
StrPut("㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒�霢嶌气�娝ͳ�퍧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹�ਇଂ⺅裢旌흆鐐鷻郴㪶幡", &str)
size = 144

; decrypt
CryptAES(str, size, 5 10 "asd", false)
fileappend % StrGet(&str) "`n", result.txt, UTF-16

CryptAES(ByRef lp,sz,pw,e:=1,SID:=256){
	static AES_128:=0x660E,AES_192:=1+AES_128,AES_256:=1+AES_192,SHA1:=1+0x8003 ; MD5
	If !DllCall("Advapi32\CryptAcquireContext","Ptr*",hP,"Uint",0,"Uint",0,"Uint",24,"UInt",0xF0000000) ;PROV_RSA_AES, CRYPT_VERIFYCONTEXT
	|| !DllCall("Advapi32\CryptCreateHash","Ptr",hP,"Uint",SHA1,"Uint",0,"Uint",0,"Ptr*",H )
	|| !CryptHashData(H,&pw,StrLen(pw)*2,0)
	|| !CryptDeriveKey(hP,AES_%SID%,H,SID<<16,getvar(hK:=0))
	|| !CryptDestroyHash(H)
		return 0
	if e
		CryptEncrypt(hK,0,1,0,&lp,getvar(sz),sz+16)
	else
		CryptDecrypt(hK,0,1,0,&lp,getvar(sz))
	CryptDestroyKey(hK),CryptReleaseContext(hP,0)
	return sz
}
The output is: testingstringthatcontain踑Ϟ䰸�ꇾ邼뽒킂釦ۡ輏␾틁ᵁ4萵68స54645621321峴녪猪ﳲ쇳ﵣ釛

Is this intended? If it is, how can I achieve the following?:

1. From Script1 using CryptAES() to encrypt an string and saving it to a txt.
2. From Script2 read the encrypted string saved on a txt and decrypt it using CryptAES()

Thanks in advance.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: How is CryptAES() supposed to be used? Is this a bug?

01 Feb 2019, 18:37

You forgot the terminating char in VarSetCapacity:

Code: Select all

; prep
VarSetCapacity(str, 130) ; Strlen*2 due to unicode + terminating char
len := StrPut("testingstringthatcontains64characters123456885464562132132222452", &str)
; encrypt
size := CryptAES(str, len*2, "asd", true) ; len*2 due to unicode
; decrypt
CryptAES(str, size, "asd", false)
MsgBox % StrGet(&str)

CryptAES(ByRef lp,sz,pw,e:=1,SID:=256){
	static AES_128:=0x660E,AES_192:=1+AES_128,AES_256:=1+AES_192,SHA1:=1+0x8003 ; MD5
	If !DllCall("Advapi32\CryptAcquireContext","Ptr*",hP,"Uint",0,"Uint",0,"Uint",24,"UInt",0xF0000000) ;PROV_RSA_AES, CRYPT_VERIFYCONTEXT
	|| !DllCall("Advapi32\CryptCreateHash","Ptr",hP,"Uint",SHA1,"Uint",0,"Uint",0,"Ptr*",H )
	|| !CryptHashData(H,&pw,StrLen(pw)*2,0)
	|| !CryptDeriveKey(hP,AES_%SID%,H,SID<<16,getvar(hK:=0))
	|| !CryptDestroyHash(H)
		return 0
	if e
		CryptEncrypt(hK,0,1,0,&lp,getvar(sz),sz+16)
	else
		CryptDecrypt(hK,0,1,0,&lp,getvar(sz))
	CryptDestroyKey(hK),CryptReleaseContext(hP,0)
	return sz
}
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: How is CryptAES() supposed to be used? Is this a bug?

01 Feb 2019, 20:26

Nop, same thing.

Result when running first script:

Code: Select all

testingstringthatcontains64characters123456885464562132132222452
㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒�霢嶌气�娝ͳ�퍧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹�ਇଂ⺅裢旌흆鐐鷻郴㪶幡
144
testingstringthatcontains64characters123456885464562132132222452
Still getting the weird results:
㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒�霢嶌气�娝ͳ�퍧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹�ਇଂ⺅裢旌흆鐐鷻郴㪶幡SOFTWARE\Microsoft\Cryptography\Defaults\Provider Types\Type 024

And when I try to decrypt this line: 㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒�霢嶌气�娝ͳ�퍧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹�ਇଂ⺅裢旌흆鐐鷻郴㪶幡
I get this:
testingstringthatcontain踑Ϟ䰸�ꇾ邼뽒킂釦ۡ輏␾틁ᵁ4萵68స54645621321峴녪猪ﳲ쇳ﵣ釛

This is the changed code:

Code: Select all

f1::
; prep
VarSetCapacity(str, 130) ; Strlen*2 due to unicode
len := StrPut("testingstringthatcontains64characters123456885464562132132222452", &str)
fileappend % StrGet(&str) "`n", result.txt, UTF-16
; encrypt
	size := CryptAES(str, len*2, "asd", true) ; len*2 due to unicode
	fileappend % StrGet(&str) "`n", result.txt, UTF-16
	fileappend % size "`n", result.txt, UTF-16
return

f2::
VarSetCapacity(str, 130) ; Strlen*2 due to unicode
StrPut("㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒򳼢嶌气􁸝ͳ􃭧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹𴸇ଂ⺅裢旌흆鐐鷻郴㪶幡", &str)
size = 144
; decrypt
CryptAES(str, size, "asd", false)
fileappend % StrGet(&str) "`n", result.txt, UTF-16
return
; AES_128_vf, AES_192_vf, AES_256_vf, SHA1_vf, hP_vf, ache_vf

CryptAES(ByRef lp,sz,pw,e:=1,SID:=256){
	static AES_128:=0x660E,AES_192:=1+AES_128,AES_256:=1+AES_192,SHA1:=1+0x8003 ; MD5
	If !DllCall("Advapi32\CryptAcquireContext","Ptr*",hP,"Uint",0,"Uint",0,"Uint",24,"UInt",0xF0000000) ;PROV_RSA_AES, CRYPT_VERIFYCONTEXT
	|| !DllCall("Advapi32\CryptCreateHash","Ptr",hP,"Uint",SHA1,"Uint",0,"Uint",0,"Ptr*",H )
	|| !CryptHashData(H,&pw,StrLen(pw)*2,0)
	|| !CryptDeriveKey(hP,AES_%SID%,H,SID<<16,getvar(hK:=0))
	|| !CryptDestroyHash(H)
		return 0
	if e
		CryptEncrypt(hK,0,1,0,&lp,getvar(sz),sz+16)
	else
		CryptDecrypt(hK,0,1,0,&lp,getvar(sz))
	CryptDestroyKey(hK),CryptReleaseContext(hP,0)
	return sz
}
When running a loop, 100 on the f1 part it crashes at random, and all results are different.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: How is CryptAES() supposed to be used? Is this a bug?

02 Feb 2019, 06:06

If you want to read it directly you will need to include terminating character, otherwise StrGet will also read the memory after end of string.
Also you forgot to change F2:: VarSetCapacity to correct size:

Code: Select all

f1::
; prep
string:="testingstringthatcontains64characters123456885464562132132222452"
VarSetCapacity(str, sz:=StrLen(string)*2+(A_IsUnicode?2:1)) ; Strlen*2 due to unicode
StrPut(string, &str)
; encrypt
	sz := CryptAES(str, sz, "asd", true) ; len*2 due to unicode
	MsgBox % StrGet(&str)
return

f2::
; decrypt
CryptAES(str, sz, "asd", false)
MsgBox % StrGet(&str)
return
So if you don't want to crypt terminating char, you have to tell StrGet how much to read, otherwise it might crash because it is accessing invalid memory:

Code: Select all

f1::
; prep
string:="testingstringthatcontains64characters123456885464562132132222452"
VarSetCapacity(str, (sz:=StrLen(string)*2)+(A_IsUnicode?2:1)) ; Strlen*2 due to unicode
StrPut(string, &str)
; encrypt
	sz := CryptAES(str, sz, "asd", true) ; len*2 due to unicode
	MsgBox % StrGet(&str,sz/(A_IsUnicode+1))
return

f2::
; decrypt
sz:=CryptAES(str, sz, "asd", false)
MsgBox % StrGet(&str,sz/(A_IsUnicode+1))
return
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: How is CryptAES() supposed to be used? Is this a bug?

02 Feb 2019, 09:43

Thanks for the answer, let me ask this to see if I got it right:

Code: Select all

f1::
; prep
string:="testingstringthatcontains64characters123456885464562132132222452" ;<-64 character strings
VarSetCapacity(str, (sz:=StrLen(string)*2)+(A_IsUnicode?2:1)) ; Strlen*2 due to unicode ;<- This means 64*2=128+2=130 because unicode
:VarSetCapacity(str, 130) ;<-This is the same as `that line right?
StrPut(string, &str)
; encrypt
	sz := CryptAES(str, sz, "asd", true) ; len*2 due to unicode
	;sz := CryptAES(str, 130, "asd", true) ; <- This is the same at ^that line right?
	MsgBox % StrGet(&str,sz/(A_IsUnicode+1))
	;MsgBox % StrGet(&str,sz/(A_IsUnicode+1)) <- This is the same at ^that line right?
return

f2::
msgbox % VarSetCapacity(str) ; 130
msgbox % size ; 144
msgbox % StrLen(StrGet(&str,size/2)) ; 72
msgbox % str
VarSetCapacity(str, 130) ; 130
size := 144
StrPut("㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒򳼢嶌气􁸝ͳ􃭧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹𴸇ଂ⺅裢旌흆鐐鷻郴㪶幡", &str)
msgbox % VarSetCapacity(str) ; 130
msgbox % size ; 144
msgbox % StrLen(StrGet(&str,size/2)) ; 72
msgbox % str ; same string
size:=CryptAES(str, size, "asd", false)
MsgBox % StrGet(&str,size/2)
return
The problem is where I use StrPut, for some reason the string is different but Idk where or how it is different. I checked the msgboxes to see if something changes but everything is the same before and after y do StrPut. You said something about a terminating character but to be honest Idk what that is hahaha. What should I change on that StrPut to make it work?
Tried doing this:
StrPut("㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒򳼢嶌气􁸝ͳ􃭧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹𴸇ଂ⺅裢旌흆鐐鷻郴㪶幡" Chr(0), &str)
Still didn't work.
Last edited by kyuuuri on 02 Feb 2019, 09:54, edited 1 time in total.
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: How is CryptAES() supposed to be used? Is this a bug?

02 Feb 2019, 09:48

The crash problem in the loop 100 comes from the StrGet or the fileappend command, nothing related to the CryptAES function.
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: How is CryptAES() supposed to be used? Is this a bug?

02 Feb 2019, 15:46

It is not StrGet or FileAppend, it is VarSetCapacity(str, 130), it should be VarSetCapacity(str, 144)!
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: How is CryptAES() supposed to be used? Is this a bug?

02 Feb 2019, 15:54

But the first string in the f1 part is a 64 characters string, doing 64*2 = 128 + 2 because terminator character in unicode = 130
For the f2 part I can't find the problem, I'm simulating the exact same as if I would have called f1 part first but for some reason the output is different, I know the problem is where I do the StrPut but I don't know what needs to be changed.
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: How is CryptAES() supposed to be used? Is this a bug?

02 Feb 2019, 16:12

To make it short, let me write the steps:
1. I open the script
2. I press F1
This piece of code is executed:

Code: Select all

f1::
string:="testingstringthatcontains64characters123456885464562132132222452"
VarSetCapacity(str, sz:=StrLen(string)*2+(A_IsUnicode?2:1)) ; Strlen*2 due to unicode
StrPut(string, &str)
; encrypt
sz := CryptAES(str, sz, "asd", true) ; len*2 due to unicode
fileappend % StrGet(&str, size/2) "`n", result.txt, UTF-16
MsgBox % StrGet(&str)
return
The output is:
㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒�霢嶌气�娝ͳ�퍧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹�ਇଂ⺅裢旌흆鐐鷻郴㪶幡PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
2. I Press F2
This piece of code is executed:

Code: Select all

f2::
; decrypt
CryptAES(str, sz, "asd", false)
MsgBox % StrGet(&str)
return
The output is:
testingstringthatcontains64characters123456885464562132132222452
3. Now I want to do it WITHOUT encrypting it first on the same script. I want to read the encrypted string from another place and then decrypt it, so I do this:

Code: Select all

f3::
VarSetCapacity(str, 130) ; 130
sz := 144
StrPut("㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒�霢嶌气�娝ͳ�퍧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹�ਇଂ⺅裢旌흆鐐鷻郴㪶幡", &str)
sz:=CryptAES(str, sz, "asd", false)
MsgBox % StrGet(&str,sz/2)
return
The output is:
testingstringthatcontain⸤ご疚鼉這鵺컢抌課כּ놈ꚾᄯ贰투␎56␋854645621321氖䊙ㆇ렕聴ϋৣ᳛
Now why do I write f3 like that?
Because when doing the following steps:
1. Open the script
2. Press F1
this piece of code is executed (the same as before BUT with msgbox telling me each thing I care about)

Code: Select all

f1::
string:="testingstringthatcontains64characters123456885464562132132222452"
VarSetCapacity(str, sz:=StrLen(string)*2+(A_IsUnicode?2:1)) ; Strlen*2 due to unicode
msgbox % VarSetCapacity(str) ; outputs 130
StrPut(string, &str)
msgbox % VarSetCapacity(str) ; outputs 130
; encrypt
sz := CryptAES(str, sz, "asd", true) ; len*2 due to unicode
msgbox % sz ; outputs 144
fileappend % StrGet(&str, size/2) "`n", result.txt, UTF-16
MsgBox % StrGet(&str)
return
3. Then I press F2
This piece of code is executed: (the same as before BUT with msgbox telling me each thing I care about)

Code: Select all

f2::
; decrypt
msgbox % VarSetCapacity(str) ; outputs 130
msgbox % sz ; outputs 144
CryptAES(str, sz, "asd", false)
MsgBox % StrGet(&str)
return
So at the moment of decryption WHERE THE RESULTS ARE OKAY the capacity of "str" is 130 and the size of "sz" is 144.
Now if we go back to this part:

Code: Select all

f3::
VarSetCapacity(str, 130) ; 130
sz := 144
StrPut("㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒�霢嶌气�娝ͳ�퍧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹�ਇଂ⺅裢旌흆鐐鷻郴㪶幡", &str)
sz:=CryptAES(str, sz, "asd", false)
MsgBox % StrGet(&str,sz/2)
return
"Str" has a capacity of 130 like on f5, "sz" is 144 like on f5 BUT the output is:
testingstringthatcontain⸤ご疚鼉這鵺컢抌課כּ놈ꚾᄯ贰투␎56␋854645621321氖䊙ㆇ렕聴ϋৣ᳛
Where is the error? VarSetCapacity and Size are the same as on f5 and f2.
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: How is CryptAES() supposed to be used? Is this a bug?

02 Feb 2019, 16:28

I think the problem is that when the encrypted string is written on the .txt or when I copy paste it some characters are not the same, how can I solve this?
HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: How is CryptAES() supposed to be used? Is this a bug?  Topic is solved

02 Feb 2019, 20:47

The problem is that you StrPut more than you VarSetCapacity!
The string you put is larger than 130!!!!

Code: Select all

VarSetCapacity(str, 130) ; must be 144 excl. terminating char
sz := 144
StrPut("㜀ꌑ襥ᛉ﹉垍챭嚟芐提잵䶝ꪋ㡖鮒נ憏蕤흧⥑ᦝ薒�霢嶌气�娝ͳ�퍧:덐㪹뢦䤘˽ૡ˨⽭鼏물颷墿ᙥ뱲⡄㠯甘娹�ਇଂ⺅裢旌흆鐐鷻郴㪶幡", &str)

Return to “Ask for Help”

Who is online

Users browsing this forum: No registered users and 14 guests