Rot13 and Rot5 are two ASCII rotation scheme that are made for alphabetic and digits respectively. The Rot13, namely, rotates the letter by 13 places, ‘A’ to ‘N’, ‘B’ to ‘M’ and so on. The Rot5, rotates the digits: ‘0’ to ‘5’, ‘1’ to ‘6’ and so on.
Why 13 and 5? because there are 26 alphetical letters and 10 digits, rotation half way gives the following two important characteristics.
t = R13(R13(t)) and t = R5(R5(t))
The Rot13 and Rot5 can be combined to encypt a given text string e.g. using this can easily protect the resource string in executable files from modification. The delphi implementation is shown below.
// Rot13+Rot5 function Rot13(const s: string): string; const rot13a: array ['A'..'Z'] of Char = 'NOPQRSTUVWXYZABCDEFGHIJKLM'; rot13b: array ['a'..'z'] of Char = 'nopqrstuvwxyzabcdefghijklm'; rot5: array ['0'..'9'] of Char = '5678901234'; var i: integer; begin Result := s; for i := 1 to Length(s) do begin if (s[i] in ['A'..'Z']) then begin Result[i] := rot13a[s[i]]; end else if (s[i] in ['a'..'z']) then begin Result[i] := rot13b[s[i]]; end else if (s[i] in ['0'..'9']) then begin Result[i] := rot5[s[i]]; // rot5 end; end; end;
Two lookup tables are made and this yields a straightforward implementation. Without tables, the rotation can also be computed simply using ord that returns the ASCII of a given character.
IF J >= 65 AND J <= 90 THEN J = ((J - 52) MOD 26) + 65 ELSEIF J >= 97 AND J <= 122 THEN J = ((J - 84) MOD 26) + 97 END IF
Rot13 + Rot5 is often called Rot18. There is an important variant that obfuscates the text over a large ASCII table. The Rot47 rotates 47, for example, ‘A’ mapped to ‘p’ and ‘a’ mapped to ‘2’.
The Pascal version of Rot47 can be implemented in the following simple function.
function Rot47(const s: string): string; var i, j: integer; begin Result := s; for i := 1 to Length(s) do begin j := Ord(s[i]); if (j in [33..126]) then begin Result[i] := Chr(33 + ((j + 14) mod 94)); end; end; end;
Both can be implemented easily using ‘tr’ command at Linux SHELL.
$ # Map upper case A-Z to N-ZA-M and lower case a-z to n-za-m $ echo "The Quick Brown Fox Jumps Over The Lazy Dog" | tr 'A-Za-z' 'N-ZA-Mn-za-m' Gur Dhvpx Oebja Sbk Whzcf Bire Gur Ynml Qbt $ tr 'A-Za-z' 'N-ZA-Mn-za-m' <<<"The Quick Brown Fox Jumps Over The Lazy Dog" Gur Dhvpx Oebja Sbk Whzcf Bire Gur Ynml Qbt $ echo "The Quick Brown Fox Jumps Over The Lazy Dog" | tr '\!-~' 'P-~\!-O' %96 "F:4< qC@H? u@I yF>AD ~G6C %96 {2KJ s@8 $ tr '\!-~' 'P-~\!-O' <<<"The Quick Brown Fox Jumps Over The Lazy Dog" %96 "F:4< qC@H? u@I yF>AD ~G6C %96 {2KJ s@8
It is obvious that Rot47 gives a better obfuscation than Rot18 because Rot47 applies to a larger look-up table.
With windows batch programming, a Rot18 implementation becomes interesting, because there is no inherent support of chr and ord functions that converts ASCII to character and vice versa. However, since there are only 26 + 26 + 10 = 62 possible cases, this can be solved by 62 if-s.
The batch script processes the given command line parameters using %*, and at the begining, the length of the text is computed. It rotates each character one by one using for /l loop. The multiple if-s translate the text to its rotated ones.
@echo off :: rot13.bat :: [email protected] :: https://helloacm.com :: 16-Sept-2012 setlocal enableextensions enabledelayedexpansion if [%1] neq [] goto start echo Rot13 ^& Rot5 echo Usage: %0 text goto :end :start set _len=0 set _str=%* :: Get the length of the sentence set _subs=%_str% :loop if not defined _subs goto :result ::remove the first char set _subs=%_subs:~1% set /a _len+=1 goto loop :result set /a _len-=1 (set s=) for /l %%g in (0,1,%_len%) do ( call :build %%g ) echo %s% goto :end :build :: get the next character call set _digit=%%_str:~%1,1%%% :: rot13 ^& rot5 if "!_digit!"=="a" ( (set s=!s!n) ) else if "!_digit!"=="b" ( (set s=!s!o) ) else if "!_digit!"=="c" ( (set s=!s!p) ) else if "!_digit!"=="d" ( (set s=!s!q) ) else if "!_digit!"=="e" ( (set s=!s!r) ) else if "!_digit!"=="f" ( (set s=!s!s) ) else if "!_digit!"=="g" ( (set s=!s!t) ) else if "!_digit!"=="h" ( (set s=!s!u) ) else if "!_digit!"=="i" ( (set s=!s!v) ) else if "!_digit!"=="j" ( (set s=!s!w) ) else if "!_digit!"=="k" ( (set s=!s!x) ) else if "!_digit!"=="l" ( (set s=!s!y) ) else if "!_digit!"=="m" ( (set s=!s!z) ) else if "!_digit!"=="n" ( (set s=!s!a) ) else if "!_digit!"=="o" ( (set s=!s!b) ) else if "!_digit!"=="p" ( (set s=!s!c) ) else if "!_digit!"=="q" ( (set s=!s!d) ) else if "!_digit!"=="r" ( (set s=!s!e) ) else if "!_digit!"=="s" ( (set s=!s!f) ) else if "!_digit!"=="t" ( (set s=!s!g) ) else if "!_digit!"=="u" ( (set s=!s!h) ) else if "!_digit!"=="v" ( (set s=!s!i) ) else if "!_digit!"=="w" ( (set s=!s!j) ) else if "!_digit!"=="x" ( (set s=!s!k) ) else if "!_digit!"=="y" ( (set s=!s!l) ) else if "!_digit!"=="z" ( (set s=!s!m) ) else if "!_digit!"=="A" ( (set s=!s!N) ) else if "!_digit!"=="B" ( (set s=!s!O) ) else if "!_digit!"=="C" ( (set s=!s!P) ) else if "!_digit!"=="D" ( (set s=!s!Q) ) else if "!_digit!"=="E" ( (set s=!s!R) ) else if "!_digit!"=="F" ( (set s=!s!S) ) else if "!_digit!"=="G" ( (set s=!s!T) ) else if "!_digit!"=="H" ( (set s=!s!U) ) else if "!_digit!"=="I" ( (set s=!s!V) ) else if "!_digit!"=="J" ( (set s=!s!W) ) else if "!_digit!"=="K" ( (set s=!s!X) ) else if "!_digit!"=="L" ( (set s=!s!U) ) else if "!_digit!"=="M" ( (set s=!s!Z) ) else if "!_digit!"=="N" ( (set s=!s!A) ) else if "!_digit!"=="O" ( (set s=!s!B) ) else if "!_digit!"=="P" ( (set s=!s!C) ) else if "!_digit!"=="Q" ( (set s=!s!D) ) else if "!_digit!"=="R" ( (set s=!s!E) ) else if "!_digit!"=="S" ( (set s=!s!F) ) else if "!_digit!"=="T" ( (set s=!s!G) ) else if "!_digit!"=="U" ( (set s=!s!H) ) else if "!_digit!"=="V" ( (set s=!s!I) ) else if "!_digit!"=="W" ( (set s=!s!J) ) else if "!_digit!"=="X" ( (set s=!s!K) ) else if "!_digit!"=="Y" ( (set s=!s!L) ) else if "!_digit!"=="Z" ( (set s=!s!M) ) else if "!_digit!"=="0" ( (set s=!s!5) ) else if "!_digit!"=="1" ( (set s=!s!6) ) else if "!_digit!"=="2" ( (set s=!s!7) ) else if "!_digit!"=="3" ( (set s=!s!8) ) else if "!_digit!"=="4" ( (set s=!s!9) ) else if "!_digit!"=="5" ( (set s=!s!0) ) else if "!_digit!"=="6" ( (set s=!s!1) ) else if "!_digit!"=="7" ( (set s=!s!2) ) else if "!_digit!"=="8" ( (set s=!s!3) ) else if "!_digit!"=="9" ( (set s=!s!4) ) else ( (set s=!s!!_digit!) ) :end endlocal
The source can be found at [github]. It is also noted that this batch script does not support pipeline command yet [improvements here]. For example, if you want something like ‘rot13.bat text | print.bat’, it will complain ‘The process tried to write to a nonexistent pipe’.
The shortest implementation found [here] in C, using 64-bytes only.
1 | main(a){while(a=~getchar())putchar(~a-1/(~(a|32)/13*2-11)*13);} |
main(a){while(a=~getchar())putchar(~a-1/(~(a|32)/13*2-11)*13);}
This does not use look-up tables but only mathematic integer computation based on ASCII.
–EOF (The Ultimate Computing & Technology Blog) —
loading...
Last Post: Another Batch Utility: Reverse the Given Text
Next Post: Enable Pipelines in Windows Batch Programming