wraithdu Posted February 19, 2013 Share Posted February 19, 2013 This is my implementation of CipherSaber-2 ( http://ciphersaber.gurus.org/ ). CipherSaber is a version of RC4 that adds a 10 byte random IV to each piece of encoded data. CipherSaber-2 augments this with a configurable number of key setup rounds ( http://ciphersaber.gurus.org/faq.html#cs2 ). I decided to do the actual encryption / decryption in machine code so it is fast enough to be used on moderately sized files. The key setup is still done in AutoIt. I prefer this routine to AutoIt's _StringEncrypt because the output is the same size as the input, regardless of key rounds or encryption rounds. Note: If you visit the site to learn more or run the official test cases, a bunch of the links incorrectly point to a .com domain. Just change those to .org and they will work properly. expandcollapse popup#include-once #include <Memory.au3> OnAutoItExitRegister("__CS_Cleanup") Global $__g_CS_pCode = 0 ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CipherSaber ; Description ...: Encrypt / decrypt a chunk of binary data. ; Syntax ........: _CipherSaber( $bData, $sKey [, $iKeyRounds = 20 [, $doEncrypt = True ]] ) ; Parameters ....: $bData - Chunk of binary data. ; $sKey - User key, string <= 246 characters, will be truncated if too long. ; $iKeyRounds - [optional] Number of rounds during key setup. Default is 20. ; $doEncrypt - [optional] Whether to encrypt or decrypt. Default is True. ; Return values .: The encrypted / decrypted binary data. ; Author ........: Erik Pilsits ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: http://ciphersaber.gurus.org/ ; Example .......: No ; =============================================================================================================================== Func _CipherSaber($bData, $sKey, $iKeyRounds = 20, $doEncrypt = True) Local $IV = Default If Not $doEncrypt Then $IV = BinaryMid($bData, 1, 10) ; ; RC4 has max key length of 256 bytes ; user key has max length of 246 bytes to allow for 10 bytes of random IV Local $state = __CS_KeySetup(StringLeft($sKey, 246), $IV, $iKeyRounds) Local $sOut = Binary("") If $doEncrypt Then $sOut = $IV Else $bData = BinaryMid($bData, 11) EndIf ; Return $sOut & __CS_Cipher($bData, $state) EndFunc ;==>_CipherSaber ; #FUNCTION# ==================================================================================================================== ; Name ..........: _CipherSaber_File ; Description ...: Encrypt / decrypt a file. ; Syntax ........: _CipherSaber_File( $fileIn, $fileOut, $sKey [, $iKeyRounds = 20 [, $doEncrypt = True ]] ) ; Parameters ....: $fileIn - Path to the input file. ; $fileOut - Path to the output file. ; $sKey - User key, string <= 246 characters, will be truncated if too long. ; $iKeyRounds - [optional] Number of rounds during key setup. Default is 20. ; $doEncrypt - [optional] Whether to encrypt or decrypt. Default is True. ; Return values .: Success - 1 ; Failure - 0 and sets @error ; | 1 - Error opening input file for readin ; | 2 - Error opening output file for writing ; Author ........: Erik Pilsits ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: No ; =============================================================================================================================== Func _CipherSaber_File($fileIn, $fileOut, $sKey, $iKeyRounds = 20, $doEncrypt = True) Local $hIn = FileOpen($fileIn, 16) If $hIn = -1 Then Return SetError(1, 0, 0) Local $hOut = FileOpen($fileOut, 2+8+16) If $hOut = -1 Then FileClose($hIn) Return SetError(2, 0, 0) EndIf ; Local $IV = Default If Not $doEncrypt Then $IV = FileRead($hIn, 10) ; Local $state = __CS_KeySetup(StringLeft($sKey, 246), $IV, $iKeyRounds) If $doEncrypt Then FileWrite($hOut, $IV) ; Local $bData While 1 $bData = FileRead($hIn, 1024^2*2) If @error Then ExitLoop FileWrite($hOut, __CS_Cipher($bData, $state)) WEnd ; FileClose($hIn) FileClose($hOut) ; Return 1 EndFunc ;==>_CipherSaber_File #region INTERNAL FUNCTIONS Func __CS_KeySetup($sKey, ByRef $IV, $iKeyRounds) Local $key = StringToBinary($sKey) Local $i, $j, $n ; If $IV = Default Then ; encrypt ; create 10 bytes random data for IV $IV = "" For $i = 1 To 10 $IV &= Hex(Random(0, 255, 1), 2) Next $IV = Binary("0x" & $IV) EndIf $key &= $IV ; ; key setup ; use struct for key+IV because they are faster than BinaryMid Local $state[256], $keylen = BinaryLen($key) Local $tKey = DllStructCreate("byte[" & $keylen & "]") DllStructSetData($tKey, 1, $key) ; For $i = 0 To 255 $state[$i] = $i Next ; $j = 0 For $k = 1 To $iKeyRounds For $i = 0 To 255 $j = Mod($j + $state[$i] + DllStructGetData($tKey, 1, Mod($i, $keylen) + 1), 256) $n = $state[$i] $state[$i] = $state[$j] $state[$j] = $n Next Next ; create state struct from array Local $tState = DllStructCreate("byte[256]") For $i = 0 To 255 DllStructSetData($tState, 1, $state[$i], $i+1) Next Return $tState EndFunc ;==>__CS_KeySetup Func __CS_Cipher(Const ByRef $bData, ByRef $tState) ; initialize machine code If Not $__g_CS_pCode Then Local $bCode If @AutoItX64 Then $bCode = Binary("0x5557565385D27E508D42FF4531C931ED488D7401018D55010FB6EA4863C54C01C00FB618440FB6D34501D14181E1FF0000004D63D94D01C3410FB613881041881B440210450FB6D2430FB6041030014883C1014839F175BD5B5E5F5DC3") Else $bCode = Binary("0x5557565383EC0C8B5424248B4C242885D27E598B44242031DB31ED891C2401C2895424088D55010FB6EA8D14290FB61A0FB6F3885C24078B1C2401F381E3FF00000089DF01CF891C240FB61F881A0FB65C2407881F0FB61201F20FB6F20FB61431301083C0013B44240875B883C40C5B5E5F5DC20C00") EndIf $__g_CS_pCode = _MemVirtualAlloc(0, BinaryLen($bCode), $MEM_COMMIT, $PAGE_EXECUTE_READWRITE) DllStructSetData(DllStructCreate("byte[" & BinaryLen($bCode) & "]", $__g_CS_pCode), 1, $bCode) EndIf ; set data to struct Local $i = 0, $j = 0, $n, $len = BinaryLen($bData) Local $tData = DllStructCreate("byte[" & $len & "]") DllStructSetData($tData, 1, $bData) ; call cipher DllCallAddress("none", $__g_CS_pCode, "struct*", $tData, "int", $len, "struct*", $tState) ; ;~ For $k = 1 To $len ;~ $i = Mod($i + 1, 256) ;~ $j = Mod($j + $state[$i], 256) ;~ $n = $state[$i] ;~ $state[$i] = $state[$j] ;~ $state[$j] = $n ;~ $n = Mod($state[$i] + $state[$j], 256) ;~ DllStructSetData($tData, 1, BitXOR($state[$n], Int(DllStructGetData($tData, 1, $k))), $k) ;~ Next ; Return DllStructGetData($tData, 1) EndFunc ;==>__CS_Cipher Func __CS_Cleanup() If $__g_CS_pCode Then _MemVirtualFree($__g_CS_pCode, 0, $MEM_RELEASE) EndFunc ;==>__CS_Cleanup #endregion INTERNAL FUNCTIONS cipher.c void __stdcall cipher(unsigned char src[], int srcSize, unsigned char state[256]) { int c = 0, i = 0, j = 0, n = 0; for (c = 0; c < srcSize; c++) { i = (i + 1) % 256; j = (j + state[i]) % 256; n = state[i]; state[i] = state[j]; state[j] = n; src[c] = state[((state[i] + state[j]) % 256)] ^ src[c]; } } Example #include <_CipherSaber.au3> ; NOTE: the IV is random data, so the encrypted data is different each time $p = "mypassword" ; string $s = "Some string to encrypt" $e = _CipherSaber(StringToBinary($s), $p) ConsoleWrite("encrypted: " & $e & @CRLF) ; $e is already binary data, default number of key rounds is 20, set flag to decrypt ; returned decrypted data is also binary $d = _CipherSaber($e, $p, 20, False) ConsoleWrite("decrypted: " & BinaryToString($d) & @CRLF) ConsoleWrite("---------------------" & @CRLF) ; file $f = @DesktopDir & "\in.txt" $o = @DesktopDir & "\enc.txt" $o2 = @DesktopDir & "\dec.txt" FileWrite($f, "Some sensitive file") ConsoleWrite("original file: " & Binary(FileRead($f)) & @CRLF) _CipherSaber_File($f, $o, $p) ConsoleWrite("encrypted file: " & Binary(FileRead($o)) & @CRLF) ; default key rounds 20, flag to decrypt _CipherSaber_File($o, $o2, $p, 20, False) ConsoleWrite("decrypted file: " & Binary(FileRead($o2)) & @CRLF) ; cleanup FileDelete($f) FileDelete($o) FileDelete($o2) 1010Bits1010 1 Link to comment Share on other sites More sharing options...
corz Posted March 17, 2013 Share Posted March 17, 2013 (edited) "In George Lucas' Star Wars trilogy, Jedi Knights were expected to make their own light sabers. The message was clear: a warrior confronted by a powerful empire bent on totalitarian control must be self-reliant. As we face a real threat of a ban on the distribution of strong cryptography, in the United States and possibly world-wide, we should emulate the Jedi masters by learning how to build strong cryptography programs all by ourselves. If this can be done, strong cryptography will become impossible to suppress."Looks great wraithdu, but it's hardly building your own Light Saber! The main feature of Cipher Saber is, "it's designed to be simple enough that even novice programmers can memorize the algorithm and implement it from scratch". Relying on outside sources, like DLL files, simply defeats the purpose.Try something like this, instead..expandcollapse popup; CipherSaber stream-cipher ; Designed by Arnold Reinhold ; ; CipherSaber (1 and 2) encryption and decryption with base64 encoding ; For more info on CS algorithm go to http://ciphersaber.gurus.org/ ; Based on Emilis Dambauskas' PHP script: http://www.phpclasses.org/browse/file/3689.html ; Which was based on Ian Gulliver's perl script: http://www.xs4all.nl/~cg/ciphersaber/ (DEAD) ; ; Pure AutoIt version by cor @ corz.org 2012 - Open Source ; ; base64 encrypt.. func CSEncrypt($str, $key, $csl=20) $r_num = StringMid(MakeRandomXString(), 1, 10) return _Base64Encode($r_num & AICipherSaber($str, $key, $r_num, $csl)) endfunc ; base64 decrypt.. func CSDecrypt($str, $key, $csl=20) $str = BinaryToString(_Base64Decode($str)) $r_num = StringMid($str, 1, 10) $str = StringMid($str, 11) return AICipherSaber($str, $key, $r_num, $csl) endfunc ; binary encrypt.. func CSbinEncrypt($str, $key, $csl=20) $r_num = StringMid(MakeRandomXString(), 1, 10) return $r_num & AICipherSaber($str, $key, $r_num, $csl) endfunc ; binary decrypt.. func CSbinDecrypt($str, $key, $csl=20) $str = BinaryToString($str) $r_num = StringMid($str, 1, 10) $str = StringMid($str, 11) return AICipherSaber($str, $key, $r_num, $csl) endfunc ; CipherSaber Algorithm.. func AICipherSaber($d, $p, $rnum, $csl=20) $p &= $rnum local $S[256] for $i = 0 to 255 $S[$i] = $i next local $j = 0, $t = StringLen($p) local $kkk[256] for $i = 0 to 255 $kkk[$i] = Asc(StringMid($p, $j+1, 1)) $j = Mod(($j + 1), $t) next $j = 0; for $kk = 0 to $csl-1 ; CS2 loops for $i = 0 to 255 $j = BitAND(($j + $S[$i] + $kkk[$i]), 0xff) $t = $S[$i] $S[$i] = $S[$j] $S[$j] = $t next next $i = 0 $j = 0 local $ii = 0 local $ret = '' $dlen = StringLen($d) for $ii = 0 to $dlen-1 $c = StringMid($d, $ii+1, 1) $i = BitAND(($i + 1), 0xff) $j = BitAND(($j + $S[$i]), 0xff) $t = $S[$i] $S[$i] = $S[$j] $S[$j] = $t $t = BitAND(($S[$i] + $S[$j]), 0xff) $ret &= Chr(BitXOR($S[$t], Asc($c))) next return $ret endfunc ; used internally.. ; works great, but could be improved! func MakeRandomXString() SRandom(@MSEC*@MSEC*@MIN) local $a[32] local $x = 0 while $a[31] = "" $tmp = chr(Random(48, 71, 1)) if StringIsXDigit($tmp) then $a[$x] = Asc($tmp) $x += 1 endif wend return StringFromASCIIArray($a) endfuncIf you want to use the Base64() versions, you will find plenty of implementations of Base64() kicking around the forums. I recommend the pure AutoIt versions by blindwig.Here's a demo:; decrypt a file.. $key = "MyKeyString" $encrypted = FileRead("C:\path\to\encrypted.file") FileWrite("C:\path\to\decrypted.file", CSbinDecrypt($encrypted, $key)) ; basic variable encrpyt/decrpyt test: $String = "Secret**FE*K**String" $key = "me@myplace.org" ; Binary.. ConsoleWrite("BINARY: " & "->" & @LF) $encrypted = CSbinEncrypt($String, $key) ConsoleWrite("encrypted: " & "->" & BinaryToString(StringStripWS($encrypted, 8)) & @LF) $decrypted = CSbinDecrypt($encrypted, $key) ConsoleWrite("decrypted: " & "->" & $decrypted & "<-" & @LF) ; Base64.. ConsoleWrite(@LF) ConsoleWrite("Base64: " & "->" & @LF) $encrypted = CSEncrypt($String, $key) ConsoleWrite("encrypted: " & "->" & $encrypted & @LF) $decrypted = CSDecrypt($encrypted, $key) ConsoleWrite(@LF) ConsoleWrite("decrypted: " & "->" & $decrypted & "<-" & @LF)You can grab an include with everything ready-to-go (and without the formatting destroyed!), here.Have fun!;o) Cor Edited March 17, 2013 by corz nothing is foolproof to the sufficiently talented fool.. Link to comment Share on other sites More sharing options...
trancexx Posted March 17, 2013 Share Posted March 17, 2013 (edited) ^^ I'm sure wraithdu would have written it that way if he'd wanted to. But the thing is he obviously can see limitation of the language he uses. That's why for critical parts of the code he used special technique to go around AutoIt's execution speed issues. That can be classified as rational action by individual with ability to think outside the box. BTW, his code is self-sufficient, just as yours is, with no purpose defeated. Edited March 17, 2013 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
wraithdu Posted March 18, 2013 Author Share Posted March 18, 2013 I can't add much to what trancexx has said, as usual, she's spot on. But you can hardly say I'm 'relying' on something I wrote myself. I'm using machine code because it's super fast for the intensive parts of this algorithm. Even you cautioned people on your site to 'Have fun, but don't try it on any HUGE files!'. Well, while I wouldn't use this to encrypt gigabytes worth of data, you can certainly use my version to encrypt megabytes at a reasonable rate. I wrote everything originally in AutoIt, and the AutoIt source for the machine code is there in the comment. Feel free to swap it out if you want to be masochistically purist, but I wouldn't recommend using it for files at that point. Link to comment Share on other sites More sharing options...
jchd Posted March 18, 2013 Share Posted March 18, 2013 May I point out that all this is now completely irrelevant in today's world and 10-years outdated? Recommendations that a secret symmetric key be changed every 1000 or so uses is a strong hint that it's fairly broken in the first place, not to mention that PGP is the standard way to exchange keys, or that it lacks almost every basic feature a strong encryption program needs for daily use by laymen. Implementing such simple bare-bones ciphers is at most a very good learning exercise but their widespread use can prove dangerous if non-tech people blindly trust them to be safe in their routine use cases. I'm merely expressing my opinion, not trying to anyhow denigrate work done by posters. This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
wraithdu Posted March 18, 2013 Author Share Posted March 18, 2013 (edited) I'll leave it the authors of RC4 and CS-2 to defend the strength of their ciphers (CS-2 gets around the Arcfour / WEP vulnerability by introducing a custom number of key setup rounds, FYI, so it is not necessary to change keys every 1000 messages). I think it is a worthy replacement for AutoIt's _StringEncrypt, which is what I use it for, especially since _StringEncrypt increases the length of the message every additional round. Edited March 18, 2013 by wraithdu Link to comment Share on other sites More sharing options...
jchd Posted March 18, 2013 Share Posted March 18, 2013 I didn't talk about the strength or weakness of the underlying algorithm. _StringEncrypt is very dangerous and replacing it with something stronger is good. What I questionned is that people may be misled (I don't mean by you) into thinking that such techniques can solve all their secrecy issues. This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now