AutoHotkey Community

It is currently May 27th, 2012, 8:01 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 37 posts ]  Go to page 1, 2, 3  Next
Author Message
PostPosted: December 9th, 2005, 12:11 am 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
There are problems with RC4 in binary mode, as Rajat posted: the encrypted text can contain non-printable characters. If you write it in a file and read back, different characters could map to the same one, others just get lost. An occasional NUL character is treated as a string terminator. You have to convert the ciphertext, for example, to a stream of hex digits and convert it back to binary before decryption. Still there are difficulties, like the length of a binary buffer has to be kept in a separate variable. To make life easier, here is a variant of Rajat's RC4 script. RC4txt2hex takes a text string, encrypts it with a pass phrase and returns the result as a stream of hex digits. RC4hex2txt does the opposite, allowing the decryption of a hex stream created beforehand. The hex string can be freely manipulated with the standard functions of AHK or written to a text file or edit with any text editor, there are no problems with special characters.

Of course you can use AES or TEA, the Tiny Encryption Algorithm, instead: this, or that. It is considered more secure, but for personal use there should be no security concerns with either of them.
Code:
Process Priority,,High                 ; Run faster
SetBatchLines -1

RC4Pass = Version 1.0.40.09`nwww.autohotkey.com`n©2003-2005 Chris Mallett, portions ©AutoIt Team

RC4Data = AutoHotkey unleashes the full potential of your keyboard, joystick, and mouse. For example, in addition to the typical Control, Alt, and Shift modifiers, you can use the Windows key and the Capslock key as modifiers.

RC4Enc := RC4txt2hex(RC4Data "`n" RC4Data "`n" RC4Data "`n" RC4Data "`n" RC4Data,RC4Pass)
RC4Dec := RC4hex2txt(RC4Enc,RC4Pass)
MsgBox %RC4Data%`n`nEncrypted 5-times with pass:`n`n%RC4Pass%`n`nto`n`n%RC4Enc%`n`nDecypted to`n`n%RC4Dec%

ExitApp

RC4txt2hex(Data,Pass) {
   Format := A_FormatInteger
   SetFormat Integer, Hex
   b := 0, j := 0
   VarSetCapacity(Result,StrLen(Data)*2)
   Loop 256
      a := A_Index - 1
     ,Key%a% := Asc(SubStr(Pass, Mod(a,StrLen(Pass))+1, 1))
     ,sBox%a% := a
   Loop 256
      a := A_Index - 1
     ,b := b + sBox%a% + Key%a%  & 255
     ,sBox%a% := (sBox%b%+0, sBox%b% := sBox%a%) ; SWAP(a,b)
   Loop Parse, Data
      i := A_Index & 255
     ,j := sBox%i% + j  & 255
     ,k := sBox%i% + sBox%j%  & 255
     ,sBox%i% := (sBox%j%+0, sBox%j% := sBox%i%) ; SWAP(i,j)
     ,Result .= SubStr(Asc(A_LoopField)^sBox%k%, -1, 2)
   StringReplace Result, Result, x, 0, All
   SetFormat Integer, %Format%
   Return Result
}

RC4hex2txt(Data,Pass) {
   b := 0, j := 0, x := "0x"
   VarSetCapacity(Result,StrLen(Data)//2)
   Loop 256
      a := A_Index - 1
     ,Key%a% := Asc(SubStr(Pass, Mod(a,StrLen(Pass))+1, 1))
     ,sBox%a% := a
   Loop 256
      a := A_Index - 1
     ,b := b + sBox%a% + Key%a%  & 255
     ,sBox%a% := (sBox%b%+0, sBox%b% := sBox%a%) ; SWAP(a,b)
   Loop % StrLen(Data)//2
      i := A_Index  & 255
     ,j := sBox%i% + j  & 255
     ,k := sBox%i% + sBox%j%  & 255
     ,sBox%i% := (sBox%j%+0, sBox%j% := sBox%i%) ; SWAP(i,j)
     ,Result .= Chr((x . SubStr(Data,2*A_Index-1,2)) ^ sBox%k%)
   Return Result
}


Edit: 20061219 - New version for AutoHotKey Version 1.0.46.00
Edit: 20061220 - AutoTrim handling is not needed in the new AHK versions, removed (thanks PhiLho)
Edit: 20061221 - Removed dummy Abs()
Edit: 20100420 - Removed old versions, added missing swaps (based on the 1-liner of temp01) and used continuation lines for a slight speedup


Last edited by Laszlo on April 20th, 2010, 6:37 pm, edited 6 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 14th, 2006, 8:47 am 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
Dear Laszlo, :)

I wanted to store my Username+Password for my multiple GMail accounts as a single encrypted file.
I tried your RC4 functions, and

It is working great!!!

Thank you very much. :)

Regards, :)

_________________
URLGet - Internet Explorer based Downloader
StartEx - Portable Shortcut Link


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 14th, 2006, 4:48 pm 
Offline

Joined: September 2nd, 2004, 1:08 am
Posts: 124
Location: Sunnyvale
This is nice, thanks! A thought...

It would be nice to hide the length of the input string by generating a output hex string that is actually longer than the input string. One way to do this is have a byte in the output string that contains the actual size of the input sting in the output string.

_________________
I am he of whom he speaks!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 14th, 2006, 5:10 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Do you mean, that the public length of the password leaks? It is true, but it is not a concern with good enough passwords. You should never use shorter than 8 characters, with shifts, symbols, etc. There are 95^8 = ~6.6/10^15 candidates to try for a blind key search. If the attacker does not know the length, he has to try all the shorter passwords, too, 1+95+95^2...+95^8 = ~6.7*10^15 possibilities, practically the same.

Of course, if the password is chosen poorly, a dictionary attack might succeed, regardless of the encryption method.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 19th, 2006, 2:51 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
Dear Laszlo, :)

I have been using the code without even taking a look at it ( all these days. )
Someday, I would like to study this code and so, would like the title post to be intact...

However, with SubStr() & Comma Seperated Values (and maybe RegEx), can this code be shortened and increased in performance ?

Regards, :)

_________________
URLGet - Internet Explorer based Downloader
StartEx - Portable Shortcut Link


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 19th, 2006, 9:35 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Goyyah wrote:
with SubStr() & Comma Seperated Values (and maybe RegEx), can this code be shortened and increased in performance ?
I added a new version in the first post. It is shorter and should be somewhat faster. I did not put long assignments into one line, to maintain legibility, but you could.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 20th, 2006, 6:49 am 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
Laszlo wrote:
I added a new version in the first post. It is shorter and should be somewhat faster.


Thank you very much, Sir. :D

Laszlo wrote:
I did not put long assignments into one line, to maintain legibility, but you could.


The algorithm is already hard for me to grasp. Once understood, the number of lines is what I would try to reduce.
I will have to study and compare both the versions side by side.

These pair of functions are among the finest available in the forum...

Thanks again and Regards, :)

_________________
URLGet - Internet Explorer based Downloader
StartEx - Portable Shortcut Link


Report this post
Top
 Profile  
Reply with quote  
PostPosted: December 20th, 2006, 4:42 pm 
Offline

Joined: December 27th, 2005, 1:46 pm
Posts: 6837
Location: France (near Paris)
Laszlo wrote:
With the changes in AutoHotKey Version 1.0.46.00, some speedup and simplifications are possible:
Impressive. I played a bit with the code, never able to make it faster... ;-)
It shows:
1) Your code is highly optimized. Nothing new here...
2) Chris' code is well optimized too, SubStr is fast!

Two minor remarks:
- I always found strange that & has a lower priority than + (even the C language makers stated it was a design error), so I tend to write: b := (b + sBox%a% + Key%a%) & 255
Of course, you code (and style) is valid.
- In RC4hex2txt, you don't have to play with AutoTrim, since you only use expression concatenation.

_________________
Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")


Report this post
Top
 Profile  
Reply with quote  
PostPosted: December 20th, 2006, 5:02 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
PhiLho wrote:
you don't have to play with AutoTrim, since you only use expression concatenation.
Thanks, I removed it. It just remained there from earlier versions, when it was necessary.


Report this post
Top
 Profile  
Reply with quote  
PostPosted: December 20th, 2006, 5:38 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
PhiLho wrote:
code is highly optimized
There are still some speedups possible. For example, when we compute k, the sum sBox%i% + sBox%j% cannot be larger than 510 (255+255), so if we duplicate the sBox array, this larger index still finds the right entry. This way we can remove the mask operation (& 255). It means a couple of percents acceleration for longer texts. (At short texts it is offset by the need for copying 255 array elements. I did not copy this to the first post, because in typical applications it does not brings you much.)
Code:
RC4txt2hex(Data,Pass) {
   Format := A_FormatInteger
   SetFormat Integer, Hex
   b := 0, j := 0
   VarSetCapacity(Result,StrLen(Data)*2)
   Loop 256 {
      a := A_Index - 1
      Key%a% := Asc(SubStr(Pass, Mod(a,StrLen(Pass))+1, 1))
      sBox%a% := a
   }
   Loop 256 {
      a := A_Index - 1
      b := b + sBox%a% + Key%a%  & 255
      T := sBox%a%
      sBox%a% := sBox%b%
      sBox%b% := T
   }
   Loop 255 {
      i := A_Index - 1
      k := i + 256
      sBox%k% := sBox%i%
   }
   Loop Parse, Data
   {
      i := A_Index & 255
      j := sBox%i% + j  & 255
      k := sBox%i% + sBox%j%
      Result .= SubStr(Asc(A_LoopField)^sBox%k%, -1, 2)
   }
   StringReplace Result, Result, x, 0, All
   SetFormat Integer, %Format%
   Return Result
}

RC4hex2txt(Data,Pass) {
   b := 0, j := 0
   VarSetCapacity(Result,StrLen(Data)//2)
   Loop 256 {
      a := A_Index - 1
      Key%a% := Asc(SubStr(Pass, Mod(a,StrLen(Pass))+1, 1))
      sBox%a% := a
   }
   Loop 256 {
      a := A_Index - 1
      b := b + sBox%a% + Key%a%  & 255
      T := sBox%a%
      sBox%a% := sBox%b%
      sBox%b% := T
   }
   Loop 255 {
      i := A_Index - 1
      k := i + 256
      sBox%k% := sBox%i%
   }
   Loop % StrLen(Data)//2 {
      i := A_Index  & 255
      j := sBox%i% + j  & 255
      k := sBox%i% + sBox%j%
      Result .= Chr(Abs("0x" SubStr(Data,2*A_Index-1,2)) ^ sBox%k%)
   }
   Return Result
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 21st, 2006, 8:23 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
...to get a fraction of a percent speedup, we can exploit a peculiarity of AHK v 1.0.46.xx: expressions containing literal strings are evaluated less deeply than the ones with variables. In the function RC4hex2txt we need to prepend "0x" to the pair of hex digits processed. If we do it the obvious way: ("0x" . SubStr(Data,2*i-1,2)), we get a string, which cannot be part of an arithmetic expression. There are several workarounds, like passing this expression to a function, which does not change its numerical value, like Abs(), or Ceil(). We can force the evaluation with a dummy assignment, like (x := "0x" . SubStr(Data,2*i-1,2)), but the simplest and fastest (so far) solution is to store the string "0x" in the variable x, and use (x . SubStr(Data,2*A_Index-1,2)). Interestingly, AHK evaluates this expression numerically.
Code:
RC4hex2txt(Data,Pass) {
   b := 0, j := 0, x := "0x"
   VarSetCapacity(Result,StrLen(Data)//2)
   Loop 256 {
      a := A_Index - 1
      Key%a% := Asc(SubStr(Pass, Mod(a,StrLen(Pass))+1, 1))
      sBox%a% := a
   }
   Loop 256 {
      a := A_Index - 1
      b := b + sBox%a% + Key%a%  & 255
      T := sBox%a%
      sBox%a% := sBox%b%
      sBox%b% := T
   }
   Loop % StrLen(Data)//2 {
      i := A_Index  & 255
      j := sBox%i% + j  & 255
      k := sBox%i% + sBox%j%  & 255
      Result .= Chr((x . SubStr(Data,2*A_Index-1,2)) ^ sBox%k%)
   }
   Return Result
}

Since it has no drawback, I updated the first post with this trick.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 30th, 2007, 4:16 pm 
Offline

Joined: November 1st, 2005, 4:44 am
Posts: 135
Laszlo, thank You very much Sir again for another bit of very useful code!

A very straight forward question:
Is this safe to use in (my) bilingual system? (I want to hide information in .ini files, hidden from prying eyes.)

_________________
help to be helped


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 30th, 2007, 4:32 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
If the input does not contain NUL characters (does not normally happen), it is safe in any langauge.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 30th, 2007, 7:54 pm 
Offline

Joined: November 1st, 2005, 4:44 am
Posts: 135
Laszlo wrote:
...(does not normally happen)...

This declaration eases my worry, since being clueless i don't well know what a NUL character is - searched Wiki etc. and did not understand much about NUL/NULL chars etc, i just suspect and hope that they are are absent in ordinary strings such as mine.

Thanks again!

_________________
help to be helped


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 30th, 2007, 7:58 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Yes, they are not in ANSI strings, only in binary data.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 37 posts ]  Go to page 1, 2, 3  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 10 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group