 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Fri Dec 09, 2005 12:11 am Post subject: RC4 encryption to hex stream |
|
|
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 are a couple of variants 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 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,RC4Pass)
RC4Dec := RC4hex2txt(RC4Enc,RC4Pass)
MsgBox %RC4Data%`n`nEncrypted 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
Loop 256
{
a := A_Index - 1
StringMid C, Pass, Mod(a,StrLen(Pass))+1, 1
Key%a% := Asc(C)
sBox%a% = %a%
}
b = 0
Loop 256
{
a := A_Index - 1
b := b + sBox%a% + Key%a% & 255
T := sBox%a%
sBox%a% := sBox%b%
sBox%b% = %T%
}
i = 0
j = 0
Loop Parse, Data
{
i := i + 1 & 255
j := sBox%i% + j & 255
k := sBox%i% + sBox%j% & 255
C := (Asc(A_LoopField) ^ sBox%k%)+ 0x100
IfEqual C,0, SetEnv C, % sBox%k% + 0x100
StringRight C, C, 2
Result := Result C
}
SetFormat Integer, %Format%
Return Result
}
RC4hex2txt(Data,Pass)
{
ATrim = %A_AutoTrim%
AutoTrim Off
Loop 256
{
a := A_Index - 1
StringMid C, Pass, Mod(a,StrLen(Pass))+1, 1
Key%a% := Asc(C)
sBox%a% = %a%
}
b = 0
Loop 256
{
a := A_Index - 1
b := b + sBox%a% + Key%a% & 255
T := sBox%a%
sBox%a% := sBox%b%
sBox%b% = %T%
}
i = 0
j = 0
Loop Parse, Data
{
If (A_Index & 1)
C = 0x%A_LoopField%
Else {
i := i + 1 & 255
j := sBox%i% + j & 255
k := sBox%i% + sBox%j% & 255
C := (C A_LoopField) ^ sBox%k%
IfEqual C,0, SetEnv C, % sBox%k%
Result := Result Chr(C)
}
}
AutoTrim %ATrim%
Return Result
} |
With the changes in AutoHotKey Version 1.0.46.00, some speedup and simplifications are possible:
| Code: | ; Needs AutoHotKey Version 1.0.46.00 or later
#SingleInstance Force
#NoEnv
SetBatchLines -1
Process Priority,,High ; Run faster
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
T := sBox%a%
sBox%a% := sBox%b%
sBox%b% := T
}
Loop Parse, Data
{
i := A_Index & 255
j := sBox%i% + j & 255
k := sBox%i% + sBox%j% & 255
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
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
} |
This version of the RC4txt2hex function is slightly faster, but uses twice as much memory. Normally, it should not be a problem. | Code: | RC4txt2hex(Data,Pass) {
Format := A_FormatInteger
SetFormat Integer, Hex
b := 0, j := 0
VarSetCapacity(Result,StrLen(Data)*4)
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 Parse, Data
{
i := A_Index & 255
j := sBox%i% + j & 255
k := sBox%i% + sBox%j% & 255
Result .= Asc(A_LoopField)^sBox%k%
}
Result := RegExReplace(Result, "0x(.)(?=0x|$)", "0$1")
StringReplace Result, Result, 0x,,All
SetFormat Integer, %Format%
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()
Last edited by Laszlo on Thu Dec 21, 2006 8:28 pm; edited 4 times in total |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 5890
|
Posted: Fri Jul 14, 2006 8:47 am Post subject: |
|
|
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,  _________________ SKAN - Suresh Kumar A N |
|
| Back to top |
|
 |
Atomhrt
Joined: 02 Sep 2004 Posts: 128 Location: Sunnyvale
|
Posted: Fri Jul 14, 2006 4:48 pm Post subject: |
|
|
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! |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Fri Jul 14, 2006 5:10 pm Post subject: |
|
|
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. |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 5890
|
Posted: Tue Dec 19, 2006 2:51 pm Post subject: |
|
|
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,  _________________ SKAN - Suresh Kumar A N |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Tue Dec 19, 2006 9:35 pm Post subject: |
|
|
| 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. |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 5890
|
Posted: Wed Dec 20, 2006 6:49 am Post subject: |
|
|
| Laszlo wrote: | | I added a new version in the first post. It is shorter and should be somewhat faster. |
Thank you very much, Sir.
| 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,  _________________ SKAN - Suresh Kumar A N |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Wed Dec 20, 2006 4:42 pm Post subject: Re: RC4 encryption to hex stream |
|
|
| 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. _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2") |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Wed Dec 20, 2006 5:02 pm Post subject: Re: RC4 encryption to hex stream |
|
|
| 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. |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Wed Dec 20, 2006 5:38 pm Post subject: Re: RC4 encryption to hex stream |
|
|
| 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
} |
|
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Thu Dec 21, 2006 8:23 pm Post subject: |
|
|
...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. |
|
| Back to top |
|
 |
iason
Joined: 01 Nov 2005 Posts: 125
|
Posted: Sun Sep 30, 2007 4:16 pm Post subject: |
|
|
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 |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Sun Sep 30, 2007 4:32 pm Post subject: |
|
|
| If the input does not contain NUL characters (does not normally happen), it is safe in any langauge. |
|
| Back to top |
|
 |
iason
Joined: 01 Nov 2005 Posts: 125
|
Posted: Sun Sep 30, 2007 7:54 pm Post subject: |
|
|
| 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 |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Sun Sep 30, 2007 7:58 pm Post subject: |
|
|
| Yes, they are not in ANSI strings, only in binary data. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|