[I have to apologize right off the bat here: I cannot write documentation for
the life of me.]
- You can run a test of rotNN.py by starting it from the command
line.
$ python rotNN.py
This will fire up a whole slew of test cases demonstrating the
different functions available from rotNN.py. These cases probably
are the best source of information about this library.
But, what the heck, here goes...
RotNN.py is a library that allows you to do a 'rotation' of ascii
characters of any number that you want, provided it is less than or equal to
the total number of available characters (26 for rotation, 94 for srotation
and wrotation).
The usual use for something like this is known as rot13 (which is
the default number for .rotation). Rot13 is an old way of obfuscating text
so that it is both unreadable and easily unscrambled at the same time. You
would want something like this in a USENET post that gives away a movie
ending, for instance. By rot13-ing the text, you can keep it away from those
who would rather not know and at the same time make it accessible to those
would enjoy having things spoiled for them.
A quick demonstration...
You know, at the ending of the movie where Colonel Halpablatt is
revealed to be both the Dark Undertaker, the Detective and Betty Sue's father
at the same time?! Boy, was I surprised! And to think, by seeing this
preview showing, I know all this stuff before it hits the general public!
Post this to a movie newsgroup and risk getting your house firebombed.
However, if you would post something like this...
For my thoughts on the ending of ROCKY XXV, rot13 the following:
Lbh xabj, ng gur raqvat bs gur zbivr jurer Pbybary Unycnoyngg vf
erirnyrq gb or obgu gur Qnex Haqregnxre, gur Qrgrpgvir naq Orggl Fhr'f sngure
ng gur fnzr gvzr?! Obl, jnf V fhecevfrq! Naq gb guvax, ol frrvat guvf
cerivrj fubjvat, V xabj nyy guvf fghss orsber vg uvgf gur trareny choyvp!
No one could say that you ruined it prematurely for them.
Now, rot13 may be the standard .rotation, but you can also do
rotations by any amount that you want. Let's look at the usage...
rotnn.rotate (string [, option_number])
rotnn.unrotate (string [, optional_number])
rotnn.srotate (string [, optional_number])
rotnn.sunrotate (string [, optional_number])
rotnn.wrotate (string [, optional_number])
rotnn.wunrotate (string [, optional_number])
The optional number is the NN in rotNN. By default it's 13 for rotate
and srotate and 47 for wrotate.
Why 47, you ask? Rot13 had a special property whereby you could
decrypt a rot13-ed message by re-rot13-ing it. It's the same deal with
wrotate. (But not with srotate! You always have to .sunrotate those!) A
wrotate47 of a wrotate47-ed message will return you the same message. Love
that symmetry.
The (s|w)unrotate functions are there for when you rotate by something
other than the symmetrical numbers (13 and 47). I suppose one could do the
math and figure out the next number that you would have to rotate by to return
to the original text, but it's much easier to do an unrotate by the SAME
number that you rotated with. A "rotnn.srotate(string, 42)" will be undone
by a "rotnn.sunrotate(string, 42)".
And let me guess: "Why srotate and wrotate?". Rot13 originally only
works upon A-Z and a-z. It leave punctuation, spacing and whatnot alone.
Fine for some things, not fine for others. Srotate works upon the entire
printable character set (at least for UNIX -- Use one of the others, YMMV),
including punctuation and spaces. It leaves carriage returns and other
unprintables alone. Wrotate does the same with a minor exception: it doesn't
rotate spaces. What does this mean? Well, for one, if you have a file that
contains quite a few spaces as delimiters (or other such stuff - Python
source files, for another), srotating it is either messy or really obvious
as to it's intent (or both). Wrotate works like a charm in this instance.
See the following examples for s and wrotate usage.
Rotnn.srotating (by 30) the LICENSE file gives us this...
t$12(.->PLOJ>d$!14 18>OWWW
a./81(&'3>FaG>OWWOJ>OWWW>d1$$>q.%36 1$>d.4-# 3(.-J>g-"L
SW>r$,/+$>n+ "$J>q4(3$>QQNJ>`.23.-J>k_>>NPOOOKOQNU>>sq_
c5$18.-$>(2>/$1,(33$#>3.>"./8> -#>#(231(!43$>5$1! 3(,>"./($2
.%>3'(2>+("$-2$>#."4,$-3J>!43>"' -&(-&>(3>(2>-.3> ++.6$#L
yr'(2>(2>3'$>%(123>1$+$ 2$#>5$12(.->.%>3'$>j$22$1>enjL>>g3> +2.>".4-32
> 2>3'$>24""$22.1>.%>3'$>els>j(!1 18>n4!+(">j("$-2$J>5$12(.->PJ>'$-"$
>3'$>5$12(.->-4,!$1>PLOL{
...and so on and so forth. Kewl, eh? Watch what wrotate does to the
same file...
t%23)/. PLOJ d%"25!29 OWWW
a/092)'(4 FaG OWWOJ OWWW d2%% q/&47!2% d/5.$!4)/.J g.#L
SW r%-0,% n,!#%J q5)4% QQNJ `/34/.J k_ NPOOOKOQNU sq_
c6%29/.% )3 0%2-)44%$ 4/ #/09 !.$ $)342)"54% 6%2"!4)- #/0)%3
/& 4()3 ,)#%.3% $/#5-%.4J "54 #(!.').' )4 )3 ./4 !,,/7%$L
yr()3 )3 4(% &)234 2%,%!3%$ 6%23)/. /& 4(% j%33%2 enjL g4 !,3/ #/5.43
!3 4(% 35##%33/2 /& 4(% els j)"2!29 n5",)# j)#%.3%J 6%23)/. PJ (%.#%
4(% 6%23)/. .5-"%2 PLOL{
It's a little hard to see (Way to go Adam -- give 'em a cruddy
example...), but wrotate retains the original spacing of the file - possibly
a big clue to someone trying to guess what you did to it.
However, watch what happens when we srotate the rotnn source...
AAAAAAAAAAAAAAAAAAAAAAAA%*#4!.+56O#22'0&AI%*4I14&!%*#4ALA#/1706JJ
AAAAAAAAAAAAAAAA'.+(AIIZRN#/1706JA]^A14&!%*#4A]^AZQJ[
AAAAAAAAAAAAAAAAAAAAAAAA%*#4!.+56O#22'0&AI%*4IWVALAI#/1706ANAIZRANA14&!%*#4JJJJ
AAAAAAAAAAAAAAAA'.+(AIIRSTN#/1706JA]^A14&!%*#4A]^ARSSJ[
AAAAAAAAAAAAAAAAAAAAAAAA%*#4!.+56O#22'0&AI%*4IZXALAI#/1706ANAIRSTANA14&!%*#4JJJJ
AAAAAAAAAAAAAAAA'.5'[
AAAAAAAAAAAAAAAAAAAAAAAA%*#4!.+56O#22'0&AI%*4I14&!%*#4JJ
Ewww, look at those A's! Wouldn't take long for someone to figure out
what's going on here. Let's wrotate it instead...
&+$5"/,67O$33(1' I&+5I25'"&+$5 L $02817JJ
(/,) IIZRN$02817J ]^ 25'"&+$5 ]^ ZQJ[
&+$5"/,67O$33(1' I&+5IWV L I$02817 N IZR N 25'"&+$5JJJJ
(/,) IIRSTN$02817J ]^ 25'"&+$5 ]^ RSSJ[
&+$5"/,67O$33(1' I&+5IZX L I$02817 N IRST N 25'"&+$5JJJJ
(/6([
&+$5"/,67O$33(1' I&+5I25'"&+$5JJ
Ahh, much better. Without the A's giving away your rotation value, it's
suddenly much harder to decrypt.
And a final caveat: (s|w)rotation isn't really that tough of encryption.
If the NSA is coming after you, you'd be a fool to use something like this.
It does, however, serve as an excellent obfuscation agent. For instance,
I wrote a proxy pass-around that would let you access blocked sites from
a trusted site. The URLs looked soemthing like this:
http://www.foo.com/cgi/sa?fuzzybunnies.com:8080
It would take one glance at a log file to have the administrator
figure out what the filter couldn't. However, after wrotating the address,
the logs would be filled with something like...
http://www.foo.com/cgi/sa?)8==<%811,(6O&20[YQYQ
Lotsa luck figuring that one out by looking at it, Mr. Administrator!
I hope you enjoy this code.
rotnn.py - A character rotation library
Copyright (C) 2000 - Adam Gurno
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA