AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

AES Encrypt/Decrypt of A File in WXP or Higher
Goto page Previous  1, 2
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Guest






PostPosted: Tue May 20, 2008 4:08 am    Post subject: Reply with quote

After reading the post below, I tried to write this one. HTH.
http://www.autohotkey.com/forum/topic31420.html&sid=7338d160f7bf3e9194c9335275e974dd

Code:
sTextOriginl := "These are a few tests of AES Encryption/Decryption!"
sPassword  := "AutoHotkey"

SID := 128   ; 128bit AES
nSize := Text_AES(sTextEncrypt, &sTextOriginl, StrLen(sTextOriginl), sPassword, SID, True)   ; Encryption
MsgBox % sTextEncrypt
nSize := Text_AES(sTextDecrypt, &sTextEncrypt, nSize, sPassword, SID, False)   ; Decryption
MsgBox % sTextDecrypt

SID := 192   ; 192bit AES
nSize := Text_AES(sTextEncrypt, &sTextOriginl, StrLen(sTextOriginl), sPassword, SID, True)   ; Encryption
MsgBox % sTextEncrypt
nSize := Text_AES(sTextDecrypt, &sTextEncrypt, nSize, sPassword, SID, False)   ; Decryption
MsgBox % sTextDecrypt

SID := 256   ; 256bit AES
nSize := Text_AES(sTextEncrypt, &sTextOriginl, StrLen(sTextOriginl), sPassword, SID, True)   ; Encryption
MsgBox % sTextEncrypt
nSize := Text_AES(sTextDecrypt, &sTextEncrypt, nSize, sPassword, SID, False)   ; Decryption
MsgBox % sTextDecrypt
Return

Text_AES(ByRef sResult, pData, nSize, sPassword, SID = 256, bEncrypt = True)
{
   VarSetCapacity(sResult, bEncrypt ? nSize+16 : nSize)
   DllCall("RtlMoveMemory", "Uint", &sResult, "Uint", pData, "Uint", nSize)
   nSize := Crypt_AES(&sResult, nSize, sPassword, SID, bEncrypt)
   NumPut(0, sResult, nSize, "char"), VarSetCapacity(sResult,-1)
   Return   nSize
}
Back to top
manonstreet



Joined: 30 Aug 2010
Posts: 9

PostPosted: Mon Sep 06, 2010 8:22 pm    Post subject: Reply with quote

olfen wrote:
Sorry, I think I was wrong on CryptGenKey: It generates a session key\password and no IV.
CryptSetKeyParam can be passed a pointer to an IV, which we can choose\create ourselfes. IV and key are two seperate things, both needed when not using the cipher in ECB mode.
If not provided IV defaults to 0, as you mentioned before.

As you have written before, we can probably call CryptGenRandom to get our 16 byte IV and pass the pointer to the buffer to CryptSetKeyParam.


This is exactly correct. I can successfully set the IV with 16 bytes of randomly generated data, but the first block of text does not decrypt successfully.

Code:

nSize := Text_AES(sTextEncrypt, &sTextOriginl, StrLen(sTextOriginl), sPassword, SID, True)   ; Encryption
MsgBox % sTextEncrypt
nSize := Text_AES(sTextDecrypt, &sTextEncrypt, nSize, sPassword, SID, False)   ; Decryption
MsgBox % sTextDecrypt


Crypt_SetRandomIV(ByRef hProv, ByRef hKey)
{
  KP_IV := 1   
  dwBlockLen := 16 ; 128 bit (16 byte) block length for AES   
  VarSetCapacity(pbIV, dwBlockLen, 0) ; initialization vector
  DllCall("advapi32\CryptGenRandom", "UInt", hProv, "UInt", dwBlockLen, "Char", &pbIV) ; Generate random data into pbIV
  DllCall("advapi32\CryptSetKeyParam", "UInt", hKey, "UInt", KP_IV, "Char", &pbIV, "UInt", 0)
}


I then modified the Crypt_AES function and added:
Code:
Crypt_SetRandomIV(hProv, hKey)

inside of the If bEncrypt block. Anyone know why the decrypt is not functioning correctly?

I could modify my function to fetch the block size first if necessary, but I figured it wasn't necessary as AES 128/192/256 all use a 128 bit block size so I just hard coded it to 16 bytes.
Back to top
View user's profile Send private message
manonstreet



Joined: 30 Aug 2010
Posts: 9

PostPosted: Wed Sep 08, 2010 12:57 am    Post subject: Reply with quote

Nevermind. It helps if you use the same randomly generated IV to decrypt, and not a new random IV. Embarassed
Back to top
View user's profile Send private message
shajul



Joined: 15 Sep 2006
Posts: 564

PostPosted: Thu Dec 16, 2010 6:53 am    Post subject: AHK_L Version Reply with quote

.

Last edited by shajul on Mon Dec 20, 2010 11:58 am; edited 3 times in total
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Thu Dec 16, 2010 10:51 am    Post subject: Reply with quote

shajul wrote:
Here's the code. No need for File.ahk also..
Good. BTW, I think you better make clear what builds it targets. I can see it doesn't support currently 64bit AHKL, however, are you gonna support ANSI build or not?

It's good to know that you used RawRead/RawWrite. OTOH, I think these parts can be improved, I may post the codes when times come.

Code:
DllCall("advapi32\CryptHashData", "Uint", hHash, "Uint", &sPassword, "Uint", StrLen(sPassword), "Uint", 0)
The only troublesome one is this one. Almost all crypto APIs treat the data as binary, so, they expect the length of the data in bytes, not in characters. So, with the UNICODE build, the code will actually use only the first half of the sPassword. It better be StrLen(sPassword) * 2 with the UNICODE build.

However, there still remains a problem if you're gonna support the ANSI build too. The encrypted file with the UNICODE build won't be decrypted with the ANSI build, and vice versa, even if using (apparently) the same password. So, need to decide on this.
1) Drop the support for the ANSI build.
2) Make the sPassword part compatible for both ANSI and UNICODE builds. There are various options here again.

Quote:
Also, check out the improvement in the native zip routine (removed the sleep, better checking if file passed is zipped)here..
Finally, that's nice.
Back to top
View user's profile Send private message
shajul



Joined: 15 Sep 2006
Posts: 564

PostPosted: Mon Dec 20, 2010 11:24 am    Post subject: Reply with quote

AHK_L version that is compatible with both Ansi and Unicode, so that any file encrypted with Unicode version should be decrypted with Ansi version and vice-versa.

Also, this should work with 64 bit builds also (untested), though i have not incorporated handling of large unsigned integers in x64 (i dont know if this is needed).

@Sean: Here's the code updated. Thanks for the pointers. Please review critically if something still sucks..

Code:
sFileOriginl   := A_ScriptFullPath
sPassword   := "AutoHotkey"

SID := 256   ; 128 for 128bit, 192 for 192bit AES
sFileEncrypt := A_ScriptDir . "\encrypt" . SID . ".bin"
sFileDecrypt := A_ScriptDir . "\decrypt" . SID . ".ahk"

StrPutVar(Password, sPassword, "UTF-8") ;Change encoding to be consistent in Ansi or Unicode builds

File_AES(sFileOriginl, sFileEncrypt, sPassword, SID, True)   ; Encryption
File_AES(sFileEncrypt, sFileDecrypt, sPassword, SID, False)   ; Decryption

File_AES(sFileFr, sFileTo, sPassword, SID = 256, bEncrypt = True)
{
   hFileFr := FileOpen(sFileFr,"r -r")
   if not hFileFr
      Return   "File not found!"
   nSize := hFileFr.Length
   VarSetCapacity(sData, nSize + (bEncrypt ? 16 : 0))
   hFileFr.Seek(0)
   hFileFr.RawRead(sData, nSize)
   hFileFr.Close()
   hFileTo := FileOpen(sFileTo,"w -r")
   if not hFileTo
      Return   "File not created/opened!"
   nSize := Crypt_AES(&sData, nSize, sPassword, SID, bEncrypt)
   hFileTo.RawWrite(sData, nSize)
   hFileTo.Close()
      Return   nSize
}

Crypt_AES(pData, nSize, sPassword, SID = 256, bEncrypt = True)
{
   CALG_AES_256 := 1 + CALG_AES_192 := 1 + CALG_AES_128 := 0x660E
   CALG_SHA1 := 1 + CALG_MD5 := 0x8003
   DllCall("advapi32\CryptAcquireContext", "UPtr*", hProv, "UPtr", 0, "UPtr", 0, "UPtr", 24, "UPtr", 0xF0000000)
   DllCall("advapi32\CryptCreateHash", "UPtr", hProv, "UPtr", CALG_SHA1, "UPtr", 0, "UPtr", 0, "UPtr*", hHash)
   DllCall("advapi32\CryptHashData", "UPtr", hHash
   , "UPtr", &sPassword
   , "UPtr", StrLen(sPassword)*2, "UPtr", 0)
   DllCall("advapi32\CryptDeriveKey", "UPtr", hProv, "UPtr", CALG_AES_%SID%, "UPtr", hHash, "UPtr", SID<<16, "UPtr*", hKey)
   DllCall("advapi32\CryptDestroyHash", "UPtr", hHash)
   bEncrypt
   ? DllCall("advapi32\CryptEncrypt", "UPtr", hKey, "UPtr", 0, "UPtr", True, "UPtr", 0, "UPtr", pData, "UPtr*", nSize, "UPtr", nSize+16)
   : DllCall("advapi32\CryptDecrypt", "UPtr", hKey, "UPtr", 0, "UPtr", True, "UPtr", 0, "UPtr", pData, "UPtr*", nSize)
   DllCall("advapi32\CryptDestroyKey", "UPtr", hKey)
   DllCall("advapi32\CryptReleaseContext", "UPtr", hProv, "UPtr", 0)
   Return   nSize
}

StrPutVar(string, ByRef var, encoding)
{
    VarSetCapacity( var, StrPut(string, encoding) * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
    return StrPut(string, &var, encoding)
}
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Mon Dec 20, 2010 1:12 pm    Post subject: Reply with quote

shajul wrote:
Code:
StrPutVar(Password, sPassword, "UTF-8") ;Change encoding to be consistent in Ansi or Unicode builds
This part may not be what you expected. In fact, it's not safe for either ANSI or UNICODE AHK_L, even can crash both versions of AHK_L in some codepages. My preference was/is dropping the support for ANSI AHK_L as I personally think that the very ANSI AHK_L should be abandoned as soon as possible before it deepens the confusion of the users.

And, I can see you just replaced int with ptr. Fortunately there will be no problem with this very code, this can be problematic, especially with out parameters, for example, nSize in this code. Anyway, blindly replacing int with ptr is not a good practice IMO.
Back to top
View user's profile Send private message
shajul



Joined: 15 Sep 2006
Posts: 564

PostPosted: Mon Dec 20, 2010 4:03 pm    Post subject: Reply with quote

Sean wrote:

And, I can see you just replaced int with ptr.


i did that because i thought it'll support 64 bit. Would it be better to use UInt64 after determining A_PtrSize?
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Tue Dec 21, 2010 12:48 am    Post subject: Reply with quote

shajul wrote:
i did that because i thought it'll support 64 bit. Would it be better to use UInt64 after determining A_PtrSize?
No, using Ptr is a good thing, as a matter of fact that's the whole purpose of the birth of the Ptr type. What I was concerned was that you had also used it even with other types. For example, nSize parameter should remain as a UInt type in both 32bit/64bit AHK_L. Fortunately, this type mismatch mostly doesn't matter with in only parameters, however, can be problematic with (in-)out parameters.
Back to top
View user's profile Send private message
shajul



Joined: 15 Sep 2006
Posts: 564

PostPosted: Tue Dec 21, 2010 4:54 am    Post subject: Reply with quote

I am learning a bit by bit Smile thanks a lot.

Finally, here is the code with Ansi support dropped and (i hope) x64 support retained. I have replaced both in-out parameters with UInt's again..

Code:
sFileOriginl   := A_ScriptFullPath
sPassword   := "AutoHotkey"

SID := 256   ; 128 for 128bit, 192 for 192bit AES
sFileEncrypt := A_ScriptDir . "\encrypt" . SID . ".bin"
sFileDecrypt := A_ScriptDir . "\decrypt" . SID . ".ahk"

File_AES(sFileOriginl, sFileEncrypt, sPassword, SID, True)   ; Encryption
File_AES(sFileEncrypt, sFileDecrypt, sPassword, SID, False)   ; Decryption

File_AES(sFileFr, sFileTo, sPassword, SID = 256, bEncrypt = True)
{
   hFileFr := FileOpen(sFileFr,"r -r")
   if not hFileFr
      Return   "File not found!"
   nSize := hFileFr.Length
   VarSetCapacity(sData, nSize + (bEncrypt ? 16 : 0))
   hFileFr.Seek(0)
   hFileFr.RawRead(sData, nSize)
   hFileFr.Close()
   hFileTo := FileOpen(sFileTo,"w -r")
   if not hFileTo
      Return   "File not created/opened!"
   nSize := Crypt_AES(&sData, nSize, sPassword, SID, bEncrypt)
   hFileTo.RawWrite(sData, nSize)
   hFileTo.Close()
      Return   nSize
}

Crypt_AES(pData, nSize, sPassword, SID = 256, bEncrypt = True)
{
   CALG_AES_256 := 1 + CALG_AES_192 := 1 + CALG_AES_128 := 0x660E
   CALG_SHA1 := 1 + CALG_MD5 := 0x8003
   DllCall("advapi32\CryptAcquireContext", "UPtr*", hProv, "UPtr", 0, "UPtr", 0, "UPtr", 24, "UPtr", 0xF0000000)
   DllCall("advapi32\CryptCreateHash", "UPtr", hProv, "UPtr", CALG_SHA1, "UPtr", 0, "UPtr", 0, "UPtr*", hHash)
   DllCall("advapi32\CryptHashData", "UPtr", hHash
   , "UPtr", &sPassword
   , "UPtr", (A_IsUnicode ? StrLen(sPassword)*2 : StrLen(sPassword)), "UPtr", 0)
   DllCall("advapi32\CryptDeriveKey", "UPtr", hProv, "UPtr", CALG_AES_%SID%, "UPtr", hHash, "UPtr", SID<<16, "UPtr*", hKey)
   DllCall("advapi32\CryptDestroyHash", "UPtr", hHash)
   bEncrypt
   ? DllCall("advapi32\CryptEncrypt", "UPtr", hKey, "UPtr", 0, "UPtr", True, "UPtr", 0
    , (A_PtrSize = 8 ? "UInt64" : "UInt"), pData, (A_PtrSize = 8 ? "UInt64P" : "UIntP"), nSize, "UPtr", nSize+16)
   : DllCall("advapi32\CryptDecrypt", "UPtr", hKey, "UPtr", 0, "UPtr", True, "UPtr", 0
    , (A_PtrSize = 8 ? "UInt64" : "UInt"), pData, (A_PtrSize = 8 ? "UInt64P" : "UIntP"), nSize)
   DllCall("advapi32\CryptDestroyKey", "UPtr", hKey)
   DllCall("advapi32\CryptReleaseContext", "UPtr", hProv, "UPtr", 0)
   Return   nSize
}


This is the MSDN reference i googled..
Quote:
BOOL WINAPI CryptEncrypt(
__in HCRYPTKEY hKey,
__in HCRYPTHASH hHash,
__in BOOL Final,
__in DWORD dwFlags,
__inout BYTE *pbData,
__inout DWORD *pdwDataLen,
__in DWORD dwBufLen
);


In this reference, even pbData is a pointer. I dont understand why our DllCall should not be "UIntP" instead of "UInt" in your original code? But it still works, btw.
Back to top
View user's profile Send private message Visit poster's website Yahoo Messenger
n-l-i-d
Guest





PostPosted: Wed Feb 16, 2011 6:27 am    Post subject: Reply with quote

I'm having issues with encryption using the Crypt_AES() function with AHK Basic.

If I use the text to be encrypted/decrypted directly in the script, it works, however if I instead load the encrypted text from file, it stops working?

Why?

Code:
orginput := "this is a test"
orgpass = test

orgsize := StrLen(orginput)

encsize := Crypt_AES(&orginput, orgsize, orgpass, 256, 1)

MsgBox % encsize "`n`n" orginput

newersize := Crypt_AES(&orginput, encsize, orgpass, 256, 0)

StringLeft, orginput, orginput, % orgsize

MsgBox % orgsize "`n`n" orginput

; --- Now the same with the encrypted data saved into a file...

FileRead, encdata, encdata.dat

;encsize := Crypt_AES(&encdata, orgsize, orgpass, 256, 1)

;MsgBox % encsize "`n`n" encdata

newersize := Crypt_AES(&encdata, encsize, orgpass, 256, 0)

StringLeft, encdata, encdata, % orgsize

MsgBox % orgsize "`n`n" encdata

Crypt_AES(pData, nSize, sPassword, SID = 256, bEncrypt = True)
{
   CALG_AES_256 := 1 + CALG_AES_192 := 1 + CALG_AES_128 := 0x660E
   CALG_SHA1 := 1 + CALG_MD5 := 0x8003
   DllCall("advapi32\CryptAcquireContextA", "UintP", hProv, "Uint", 0, "Uint", 0, "Uint", 24, "Uint", 0xF0000000)
   DllCall("advapi32\CryptCreateHash", "Uint", hProv, "Uint", CALG_SHA1, "Uint", 0, "Uint", 0, "UintP", hHash)
   DllCall("advapi32\CryptHashData", "Uint", hHash, "Uint", &sPassword, "Uint", StrLen(sPassword), "Uint", 0)
   DllCall("advapi32\CryptDeriveKey", "Uint", hProv, "Uint", CALG_AES_%SID%, "Uint", hHash, "Uint", SID<<16, "UintP", hKey)
   DllCall("advapi32\CryptDestroyHash", "Uint", hHash)
   If   bEncrypt
      DllCall("advapi32\CryptEncrypt", "Uint", hKey, "Uint", 0, "Uint", True, "Uint", 0, "Uint", pData, "UintP", nSize, "Uint", nSize+16)
   Else   DllCall("advapi32\CryptDecrypt", "Uint", hKey, "Uint", 0, "Uint", True, "Uint", 0, "Uint", pData, "UintP", nSize)
   DllCall("advapi32\CryptDestroyKey", "Uint", hKey)
   DllCall("advapi32\CryptReleaseContext", "Uint", hProv, "Uint", 0)
   Return   nSize
}



Confused
Back to top
guest3456



Joined: 10 Mar 2011
Posts: 308

PostPosted: Sat Mar 12, 2011 2:02 am    Post subject: Reply with quote

is it possible to do RSA public key with this?
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group