Jump to content

[AutoIT-Forum] Encryption: Saving the key from one session to the next


CE101
 Share

Recommended Posts

I need some advice on how to save an ecryption key from one session to the next.

This may be a very stupid question based on my misunderstanding of encryption. If that's the case, my apologies.

I have an Excel file in which there are some columns I would like to encrypt.

I've already experimented with the relavent _Crypt functions and see how it works. In the following example I derive a key, ecrypt some data with that key and then decrypt it with the same key.

#include <Debug.au3>    
_DebugSetup ("Debugger") 
#include <Crypt.au3>

; Syntax for Crypt functions
;   _Crypt_DeriveKey($vPassword,           $iALG_ID [, $iHash_ALG_ID = $CALG_MD5 ] )
;   _Crypt_EncryptData($vData, $vCryptKey, $iALG_ID[, $fFinal = True])
;   _Crypt_DecryptData($vData, $vCryptKey, $iALG_ID[, $fFinal = True])


; Using $hKey1, encrypt some data and then decrypt it 
;   and verify that the decrypted data ($var4) is the same as the original data ($var1)  
$var1 = "ABCDEF"
_Crypt_Startup()
$hKey1 =_Crypt_DeriveKey("SomePassword",  $CALG_RC4)
$var2  =_Crypt_EncryptData($var1, $hKey1, $CALG_RC4) 
_Crypt_DestroyKey($hKey1)
_Crypt_Shutdown()
$var3 = _Crypt_DecryptData($var2, $hKey1, $CALG_RC4) 
$var4 = BinaryToString($var3)


; Here I'm curious to see whether a second key will be the same as the first, if the same parameters were used for both 
_Crypt_Startup()
$hKey2 =_Crypt_DeriveKey("SomePassword",  $CALG_RC4)
_Crypt_DestroyKey($hKey2)
_Crypt_Shutdown()


    _DebugOut("*** Encryption..." ) 
    _DebugReportVar("$hKey1", $hKey1)
    _DebugReportVar("$hKey2", $hKey2)
    _DebugReportVar("Original................... $var1",  $var1)
    _DebugReportVar("Encrypted.................. $var2",  $var2)
    _DebugReportVar("Decrypted.................. $var3",  $var3)
    _DebugReportVar("BinaryToString($var3)...... $var4",  $var4)


If $var1 <> $var4   Then
    _DebugOut("Test failed...   $var1 <> $var4")
EndIf
If $hKey1 <> $hKey2   Then
    _DebugOut(" $hKey1 <> $hKey2  ... That's the way it should be")
Else 
    _DebugOut(" $hKey1 = $hKey2   ... This is a problem. Keys should be unique")
EndIf

; At this point the debug results will look something like this
        ;~ @@ Debug(36) : {Ptr} -> $hKey1  = 0x008EF8A0
        ;~ @@ Debug(50) : {Ptr} -> $hKey2  = 0x008EDEA0
        ;~ @@ Debug(37) : {String:6} -> $var1 = "ABCDEF"
        ;~ @@ Debug(38) : {Binary:6} -> $var2 = 0x17985CC39A1C
        ;~ @@ Debug(39) : {Binary:6} -> $var3 = 0x414243444546
        ;~ @@ Debug(40) : {String:6} -> $var4 = "ABCDEF"

The question now is how do I save the key that was used to encrypt the data to be used another day to decrypt that same data.

How do I save the key for future use. The variable $hKey1 is only a pointer (Ptr) to the location of the actual key. So by saving the pointer you are not saving the actual key. You are only saving the address at which the key is stored. However once the script finishes, the memory is released and the address has no more significance.

In summary, how can I decrypt data that was encrypted in an earlier session.

Any suggestions would be greatly appreciated. Sample code would be even better.

Edited by CE101
Link to comment
Share on other sites

To William(Saywell) and omikron48:

Thank you for responding.

Omikron48 is correct. DeriveKey will not generate the same key on every call, even though the same password has been used , as demonstrated in the following code.

#include <Debug.au3>    
_DebugSetup ("Debugger") 
#include <Crypt.au3>

; Syntax for Crypt functions
;   _Crypt_DeriveKey($vPassword,           $iALG_ID [, $iHash_ALG_ID = $CALG_MD5 ] )
;   _Crypt_EncryptData($vData, $vCryptKey, $iALG_ID[, $fFinal = True])
;   _Crypt_DecryptData($vData, $vCryptKey, $iALG_ID[, $fFinal = True])


; Using $hKey1, encrypt some data and then decrypt it 
;   and verify that the decrypted data ($var4) is the same as the original data ($var1)  
$var1 = "ABCDEF"
_Crypt_Startup()
$hKey1 =_Crypt_DeriveKey("SomePassword",  $CALG_RC4)
$var2  =_Crypt_EncryptData($var1, $hKey1, $CALG_RC4) 
_Crypt_DestroyKey($hKey1)
_Crypt_Shutdown()
$var3 = _Crypt_DecryptData($var2, $hKey1, $CALG_RC4) 
$var4 = BinaryToString($var3)


; Generate a second key ($hKey2) using the same criteria as the first and with this new key decrypt the original data 
;   and verify that the decrypted data ($var6) is the same as the original data ($var1)  
_Crypt_Startup()
$hKey2 =_Crypt_DeriveKey("SomePassword",  $CALG_RC4)
_Crypt_DestroyKey($hKey2)
_Crypt_Shutdown()
$var5 = _Crypt_DecryptData($var2, $hKey2, $CALG_RC4) 
$var6 = BinaryToString($var5)


    _DebugOut("*** Encryption..." ) 
    _DebugReportVar("$hKey1", $hKey1)
    _DebugReportVar("$hKey2", $hKey2)
    _DebugReportVar("Original................... $var1",  $var1)
    _DebugReportVar("Encrypted.................. $var2",  $var2)
    _DebugReportVar("Decrypted with $hKey1...... $var3",  $var3)
    _DebugReportVar("BinaryToString($var3)...... $var4",  $var4)
    _DebugReportVar("Decrypted with $hKey2...... $var5",  $var5)
    _DebugReportVar("BinaryToString($var5)...... $var6",  $var6)

If $var1 <> $var4   Then
    _DebugOut("Test failed...   $var1 <> $var4")
EndIf
If $var1 <> $var6   Then
    _DebugOut("Test failed...   $var1 <> $var6")
EndIf
If $hKey1 <> $hKey2   Then
    _DebugOut(" $hKey1 <> $hKey2  ... That's the way it should be")
Else 
    _DebugOut(" $hKey1 = $hKey2   ... This is a problem. Keys should be unique")
EndIf

; At this point the debug results will look something like this
            ;~ *** Encryption...
            ;~ @@ Debug(42) : {Ptr} -> $hKey1 = 0x008EF8A0
            ;~ @@ Debug(43) : {Ptr} -> $hKey2 = 0x008EDEA0
            ;~ @@ Debug(44) : {String:6} -> Original................... $var1 = "ABCDEF"
            ;~ @@ Debug(45) : {Binary:6} -> Encrypted.................. $var2 = 0x17985CC39A1C
            ;~ @@ Debug(46) : {Binary:6} -> Decrypted with $hKey1...... $var3 = 0x414243444546
            ;~ @@ Debug(47) : {String:6} -> BinaryToString($var3)...... $var4 = "ABCDEF"
            ;~ @@ Debug(48) : {Binary:6} -> Decrypted with $hKey2...... $var5 = 0x9AF4ED071F96
            ;~ @@ Debug(49) : {String:6} -> BinaryToString($var5)...... $var6 = "šôí –"
            ;~ Test failed...   $var1 <> $var6
Link to comment
Share on other sites

Just from a quick glance at MSDN (linked to from the AutoIt Help File), the session key is stored as a handle to another area. To quote the page regarding these keys:

The HCRYPTKEY data type is used to represent handles to cryptographic keys. These handles are used to indicate to the CSP module which key is being used in a specific operation. The CSP module does not enable direct access to the key values. Instead, the user performs functions by using the key value through the key handle.

Storing the handles obviously won't work then. However, a page back shows this:

The CryptDeriveKey function generates cryptographic session keys derived from a base data value. This function guarantees that when the same cryptographic service provider (CSP) and algorithms are used, the keys generated from the same base data are identical. The base data can be a password or any other user data.

The emphasis was added by me, but as you can see, it should just work the same, when generated the same. I haven't looked at the source to Crypt.au3 yet, to see how it's calling the dll, but I would start there and see what other options you need.

Link to comment
Share on other sites

The problems occur since you do not use the functions correctly. If you create your own $hKey, you have to use $CALC_USERKEY in the call to EncryptData. Otherwise, _Crypt_EnCryptData creates the $hKey itself (using the binary representation of the handle you specified). This results in different keys since the "password" ist different each time.

Correct usage would be:

#include <Debug.au3>
_DebugSetup ("Debugger")
#include <Crypt.au3>

; Syntax for Crypt functions
;   _Crypt_DeriveKey($vPassword,           $iALG_ID [, $iHash_ALG_ID = $CALG_MD5 ] )
;   _Crypt_EncryptData($vData, $vCryptKey, $iALG_ID[, $fFinal = True])
;   _Crypt_DecryptData($vData, $vCryptKey, $iALG_ID[, $fFinal = True])


; Using $hKey1, encrypt some data and then decrypt it
;   and verify that the decrypted data ($var4) is the same as the original data ($var1)

$sString = "ABCDEF"
$bBinaryString = StringToBinary($sString)
_Crypt_Startup()
$hKey1 =_Crypt_DeriveKey("SomePassword",  $CALG_RC4)
$bBinaryEncrypted  = _Crypt_EncryptData($bBinaryString, $hKey1, $CALG_USERKEY)
_Crypt_DestroyKey($hKey1)
_Crypt_Shutdown()



; Generate a second key ($hKey2) using the same criteria as the first and with this new key decrypt the original data
;   and verify that the decrypted data ($var6) is the same as the original data ($var1)
_Crypt_Startup()
$hKey2 = _Crypt_DeriveKey("SomePassword",  $CALG_RC4)
$bBinaryDecrypted = _Crypt_DecryptData($bBinaryEncrypted, $hKey2, $CALG_USERKEY)
_Crypt_DestroyKey($hKey2)
_Crypt_Shutdown()
$sStringDecrypted = BinaryToString($bBinaryDecrypted)

    _DebugOut("*** Encryption..." )
    _DebugReportVar("Original................... $sString         ",  $sString)
    _DebugReportVar("Binary..................... $bBinaryString   ",  $bBinaryString)
    _DebugReportVar("Encrypted.................. $bBinaryEncrypted",  $bBinaryEncrypted)
    _DebugReportVar("Decrypted with $hKey2...... $bBinaryDecrypted",  $bBinaryDecrypted)
    _DebugReportVar("BinaryToString($var5)...... $sStringDecrypted",  $sStringDecrypted)

Or

#include <Debug.au3>
_DebugSetup ("Debugger")
#include <Crypt.au3>


; Using $hKey1, encrypt some data and then decrypt it
;   and verify that the decrypted data ($var4) is the same as the original data ($var1)
$sString = "ABCDEF"
$bBinaryString = StringToBinary($sString)
$bBinaryEncrypted  = _Crypt_EncryptData($bBinaryString, "SomePassword", $CALG_RC4)


; Generate a second key ($hKey2) using the same criteria as the first and with this new key decrypt the original data
;   and verify that the decrypted data ($var6) is the same as the original data ($var1)
$bBinaryDecrypted = _Crypt_DecryptData($bBinaryEncrypted, "SomePassword", $CALG_RC4)
$sStringDecrypted = BinaryToString($bBinaryDecrypted)

    _DebugOut("*** Encryption..." )
    _DebugReportVar("Original................... $sString         ",  $sString)
    _DebugReportVar("Binary..................... $bBinaryString   ",  $bBinaryString)
    _DebugReportVar("Encrypted.................. $bBinaryEncrypted",  $bBinaryEncrypted)
    _DebugReportVar("Decrypted with $hKey2...... $bBinaryDecrypted",  $bBinaryDecrypted)
    _DebugReportVar("BinaryToString($var5)...... $sStringDecrypted",  $sStringDecrypted)

Or

; Using $hKey1, encrypt some data and then decrypt it
;   and verify that the decrypted data ($var4) is the same as the original data ($var1)
$sString = "ABCDEF"
$bBinaryString = StringToBinary($sString)
_Crypt_Startup()
$hKey1 =_Crypt_DeriveKey("SomePassword",  $CALG_RC4)
$bBinaryEncrypted  = _Crypt_EncryptData($bBinaryString, $hKey1, $CALG_USERKEY)
_Crypt_DestroyKey($hKey1)
_Crypt_Shutdown()

; Generate a second key ($hKey2) using the same criteria as the first and with this new key decrypt the original data
;   and verify that the decrypted data ($var6) is the same as the original data ($var1)
$bBinaryDecrypted = _Crypt_DecryptData($bBinaryEncrypted, "SomePassword", $CALG_RC4)
$sStringDecrypted = BinaryToString($bBinaryDecrypted)

    _DebugOut("*** Encryption..." )
    _DebugReportVar("Original................... $sString         ",  $sString)
    _DebugReportVar("Binary..................... $bBinaryString   ",  $bBinaryString)
    _DebugReportVar("Encrypted.................. $bBinaryEncrypted",  $bBinaryEncrypted)
    _DebugReportVar("Decrypted with $hKey2...... $bBinaryDecrypted",  $bBinaryDecrypted)
    _DebugReportVar("BinaryToString($var5)...... $sStringDecrypted",  $sStringDecrypted)

or ... There are many different ways.

To speed up the calls, you can call _Crypt_Startup() once at the beginning of the script and on exit (e.g. OnAutoItExitRegister) call _Crypt_Shutdown().

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

To ProgAndy: Thank you for the three examples! One would have been sufficient. But three is fantastic!

Problem solved.

To SkinnyWhiteGuy: Thank you for the MSDN information. I haven't checked that DLL stuff because it seems I already have a solution. However thanks to you I now know where to look in the future.

You guys are great!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...