home *** CD-ROM | disk | FTP | other *** search
/ The Hacker's Encyclopedia 1998 / hackers_encyclopedia.iso / zines / a_m / lodhtj03.006 < prev    next >
Encoding:
Text File  |  2003-06-11  |  27.3 KB  |  654 lines

  1. The LOD/H Technical Journal, Issue #3: File 06 of 11
  2.  
  3.           |||||||||||||||||||||||||||||||||||||||||||||||||||
  4. +-+-+-+-+-+-+/                             X+-+-+-+-+-+-+
  5.  X  L  X    Secure Data Encryption with Cellular Automatons        /  L  /
  6.    X  O  X                                 /    O  /
  7.      X    D  X                  by               /  D  /
  8.        +-+-+-+                             +-+-+-+
  9.      X  L  X          The Mentor               /  L  /
  10.        X  O  X                         /    O  /
  11.          X    H  X    A Legion of Doom Presentation!       /  H  /
  12.  
  13.            +-+-+-+                     +-+-+-+
  14.         X_X_X_X_________________________________/_/_/_/
  15.  
  16.  
  17.      One of the key issues that concerns anyone who has sensitive or illegal
  18. information on their computer system is preventing unauthorized access to this
  19. information.  Even if you hit a key that deletes everything on the hard disk
  20. when you see that four-door sedan pull up in the driveway, any idiot with
  21. Norton's Utilities (IBM) or Copy II+ (Apple) can recover anything that's on
  22. your drive with minimal effort.  A delete command only changes a flag in the
  23. VTOC (volume table of contents), it doesn't actually *remove* the file from
  24. your system.
  25.      There are two methods to ensure that your data can't be read by a sector
  26. editor or recovered by NU.  The first is to overwrite everything with a NULL
  27. (FF) or anything else for that matter.    I've seen one batch file that does a
  28. global delete, creates a file that says 'EAT HOT DEATH', and then begins
  29. copying it until disk space is full.  Unfortunately, you can't always guarantee
  30. that you will be able to get to your computer before someone else does.
  31.       The second method is to encrypt your data.  Most people have visions of
  32. data encryption being some sort of arcane process akin to summoning demons or
  33. talking with Dead Cow Cult members (two closely related process- es.)  In
  34. practice, it isn't that difficult.  This file is intended to show some very
  35. short programs that will encrypt data beyond the ability of any- thing short of
  36. a dedicated mainframe to crack.
  37.  
  38.      How to use:  The code examples I provide will be in MicroSoft's
  39. AmigaBASIC.  It is fairly generic and you should be able to convert it over to
  40. IBM, //e,c,gs, Mac, ST, C64, or any flavor of mainframe you like.  For those of
  41. you setting up systems on Packet-Switched Networks (such as the LOD/H system
  42. one of our members is implementing) data encryption should be considered
  43. absolutely necessary to maintain security.
  44.       The terseness of the routines make them easy to insert in a bulletin
  45. board also, although conversion into C or Assembly would be necessary for
  46. decent speed.
  47.  
  48.       Intro to Cryptography:  Long before computers were around, there was a
  49. need for data security.  Everyone used lemon juice as 'invisible ink' when they
  50. were a kid, heating it over a candle to bring it out.  And everyone has seen
  51. the substitution code where "A" = 1, B = "2", "Z" = 26, etc...
  52.       The easiest form of encryption involves a variation of the previous.
  53. First of all, don't think of A = 1 as a substitution, think of it as a
  54. remapping.  Let's say we have a language made up of the five vowels, and we
  55. wanted to remap them to the numbers 1-5.  Our map would look like this:
  56. "AEIOU12345" and our mapping function would be f(c) = POSITION(c) + x where c =
  57. the letter to map and x is the key (in this case 5.)  So every time we needed
  58. to encrypt a letter, we would take its position in the map, add 5 to it, and
  59. come up with the character to substitute.  For the entire alphabet, the mapping
  60. function would be f(c) = POS(c) + 26 for the map "A..Z,1..26".
  61.        Your map should be composed of all the characters that will be used for
  62. encryption.  In a text only encrypter, this will consist of all the printable
  63. characters your machine can use.  The same method can be used to encrypt binary
  64. files, but it's not as clear as text only for a teaching example.
  65.        The problem with this simple form of encryption is that your average C64
  66. could crack it in a matter of minutes.    Enter into the next level of
  67. cryptography, random numbers.
  68.        During World War II the Allied Forces created a system to generate
  69. random electric noise, recorded this noise onto a wax cylinder, and scram- bled
  70. radio transmissions by mixing the seemingly random noise with the voice
  71. transmission.  The soldiers in the field needed an imprint of the same cylinder
  72. to be able to understand the message.  Think of the wax cy- linder as a
  73. 'filter' for the crypted message.
  74.        A random number generator can be easily used to encrypt data providing
  75. you realize the following-  a random number generator on a computer is not
  76. really random.    If you initialize the generator with the same seed value on two
  77. seperate occasions, it will return the same sequence of psuedo- random
  78. numbers.  Most BASIC's use the RANDOMIZE <seed> command to start the generator
  79. off.  If you leave off the seed, they get a seed from the system clock or some
  80. other fairly random source, providing a much truer random selection.  But by
  81. declaring the seed yourself, you can be sure that you will be able to reference
  82. this same string of numbers, a string that is very hard to figure out without
  83. the key (seed.)
  84.     Program Listing 1 is an example of a BASIC encrypt/decrypt system that
  85. uses the built-in random number generator include on the machine (or language
  86. implementation.)
  87.  
  88. Program Listing 1
  89. -----------------
  90.  
  91. REM ************************************************************************
  92. REM
  93. REM  Ok, this is an example of very basic encryption.  It takes the input
  94. REM  string and the input key and processes them using the machine's built
  95. REM  in random number generator.  This version is written in AmigaBASIC 1.2.
  96. REM  It can be compacted quite a bit by writting it in C, but it's an easy
  97. REM  algorithm to crack.
  98. REM
  99. REM ************************************************************************
  100.  
  101. INPUT "String to be encoded"; C$
  102. INPUT "Key Please! ";K
  103.  
  104.  
  105. REM ************************************************************************
  106. REM
  107. REM  When you use the RANDOMIZE command, it seeds the random number gener-
  108. REM  ator with the key K.  *EVERY* time you seed the generator with the same
  109. REM  value, you will get the same sequence of psuedo-random numbers.  Since
  110. REM  the built in random-number generator uses a linear algorithm to gener-
  111. REM  ate the sequence, it's easy (relatively) to crack.
  112. REM
  113. REM ************************************************************************
  114.  
  115. RANDOMIZE K
  116.  
  117. REM ************************************************************************
  118. REM
  119. REM  The only difference between encoding and decoding is which way you
  120. REM  move in your Q$ array space.  Encoding takes the original and shifts
  121. REM  to the right, decoding takes the codes value and shifts to the left.
  122. REM
  123. REM ************************************************************************
  124.  
  125. REREAD:
  126.   INPUT "Encode or Decode ? ";A$
  127.   A$=LEFT$(A$,1)
  128.   IF A$="E" OR A$="e" THEN
  129.     A=1
  130.     GOTO HEAD
  131.   END IF
  132.   IF A$="D" OR A$="d" THEN
  133.      A=-1
  134.   ELSE
  135.      GOTO REREAD
  136.   END IF
  137.  
  138. REM ************************************************************************
  139. REM
  140. REM  Q$ contains all the characters that can be encoded.  Every encoded
  141. REM  character will be mapped to a character in this array.  I haven't
  142. REM  included any non-standard characters, so you will have to customize
  143. REM  it to your particular keyboard/system.  I've included an error check
  144. REM  that will abort the encryption if it encounters a character that isn't
  145. REM  in Q$.  I have to use the STRING$ command to insert the spacebar and
  146. REM  the quote into the string.  It could also be done with a ASC(##) in
  147. REM  many basics.  You could expand this to include any non-printable
  148. REM  characters you'd like so you could do non-text files.
  149. REM
  150. REM ************************************************************************
  151.  
  152. HEAD:
  153.   SPACE = 32
  154.   QUOTE = 34
  155.   Q$="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  156.   Q$=Q$+"1234567890!@#$%^&*()-=_+[]$;:'.,<>/?X|
  157.                            "
  158.   Q$=Q$+STRING$(1,SPACE)+STRING$(1,QUOTE)
  159.   QSIZ = LEN(Q$)
  160.  
  161. REM ************************************************************************
  162. REM
  163. REM  This is the main loop.  L = length of the string to encrypt.  In this
  164. REM  example, I am only encrypting a single string.  Most people who will
  165. REM  actually use this will change the FOR loop to run until an EOF is
  166. REM  encountered in the input file.  Since the syntax for that will vary
  167. REM  widely from system to system, I'll leave it out.
  168. REM
  169. REM ************************************************************************
  170.  
  171. L=LEN(C$)
  172. FOR I = 1 TO L
  173.  
  174. REM /* Finds the character I in the input string */
  175.   X$ = MID$(C$,I,1)
  176.  
  177. REM /* Finds the integer location of the character in Q$
  178. REM    returns variable POZ */
  179.   GOSUB LOKPOZ
  180.  
  181. REM /* RND returns a random # between 0 and 1.    Multiply it by the
  182. REM    size of array Q$ and you get the number of positions to move
  183. REM    when encoding or decoding. */
  184.   POZMV = (RND * QSIZ)
  185.  
  186. REM /* If you are encoding, you will shift to the right using addition.
  187. REM    you take the modula base QSIZ to keep the new character within
  188. REM    the bounds of Q$. */
  189.   IF A = 1 THEN
  190.     NUPOZ = (POZ + POZMV) MOD QSIZ
  191.   ELSE
  192. REM /* Otherwise, you subtract, which takes a bit more math to keep
  193. REM    up with.  Once you have the distance to shift, you must
  194. REM    convert it to a positive integer and then subtract two to
  195. REM    account for the head & tail of the array. */
  196.     NUPOZ = (POZ - POZMV) MOD QSIZ
  197.     NUPOZ = NUPOZ -2
  198.     IF NUPOZ < 1 THEN
  199.       NUPOZ = QSIZ - ABS(NUPOZ)
  200.     END IF
  201.   END IF
  202.  
  203. REM /* Now you assign the new character in array Q$ to Y$, and append
  204. REM    it to your converted string */
  205.   IF NUPOZ < 1 THEN
  206.     NUPOZ = QSIZ - ABS(NUPOZ)
  207.   END IF
  208.   Y$ = MID$(Q$,NUPOZ,1)
  209.   D$ = D$ + Y$
  210. NEXT I
  211.  
  212. PRINT  "Original = ";C$
  213. PRINT  "Modified = ";D$
  214. END
  215.  
  216. REM /* This finds character X$ in array Q$ and returns an integer
  217. REM    value of the location.  Called from the main loop. */
  218. LOKPOZ:
  219.   FOUND = 0
  220.   POZ = 1
  221.   TOP:
  222.     IF FOUND = 1 THEN
  223.       RETURN
  224.     ELSE
  225.       TMP$ = MID$(Q$,POZ,1)
  226.       IF X$ = TMP$ THEN
  227.     FOUND = 1
  228.       END IF
  229.       POZ = POZ + 1
  230.       IF POZ > QSIZ THEN
  231.     PRINT  "Error: Character '";X$"' not in array Q."
  232.     END
  233.       END IF
  234.     END IF
  235.   GOTO TOP
  236.  
  237. REM **********************************************************************
  238.  
  239. End of Program Listing 1
  240.  
  241.     This method, while extremely simple, tight, and fast, is not fool-
  242. proof.    Most computers use the following algorithm for generating pseudo-
  243. random number sequences: x(t+1) = ax(t) + b
  244.     x(t+1) = next random number
  245.     x(t) = previous random number
  246.     a & b are constants that will cause a fairly even distribution
  247.  
  248.     For example, if you were using a three-bit system (8 possible postive
  249. integers) you might make a = 3 & b = 7 (there's a reason behind using prime
  250. numbers that is beyond the scope of this file.)  If you seed the argument with
  251. RANDOMIZE 5 you would get the following:
  252. First x: x = 3*5 + 7 | Since we're restricting ourselves to three bits, and
  253.      22 won't fit in three bits, we'd need to perform a modula 8 on the
  254.      number. (Modulo divides x by eight and keeps the remainder as the
  255.      new value of x.)  So  MOD(22,8) is equal to 6 (16 + 6 = 22).
  256.  
  257.      Ok, let's do some simple mapping using our vowel set and the above
  258. three-bit random number generator.  Let's say that the message reads "AAEOU"
  259. Our first random number was 6.    Our map looks like "AEIOU12345".  POS(A) + 6
  260. gives us 2 as the character.
  261. Second x: x = 3*6 + 7 | MOD (25,8) = 1 | POS(A) + 1 gives us E.
  262. Third  x: x = 3*1 + 7 | MOD (10,8) = 2 | POS(E) + 2 gives us O.
  263. Fourth x: x = 3*2 + 7 | MOD (13,8) = 5 | POS(O) + 5 gives us 4.
  264. Fifth  x: x = 3*5 + 7 | MOD (22,8) = 6 | POS(U) + 6 wraps around the map to A.
  265.  
  266.      So our original "AAEOU" is crytped into "2E04A".  This may at first
  267. seem difficult to crack since 'A' mapped into a '2' on one pass and an 'E' on
  268. the other, thus preventing a freuquency analysis from breaking the code.
  269.     Unfortunately, if someone knows the random number algorithm, they can
  270. easily hack out the key.  Since most of the people using this will be using it
  271. on a pc, it would be trivial to get another pc to hack it out.    And even if you
  272. protect your random number algorithm, it is still a straight linear algebra
  273. problem that an AT could work on over a weekend and probably figure it out,
  274. especially if there is a fairly small map to work with.
  275.  
  276.       Solution: What we need to do is combine the random mapping with a
  277. random number generator that is tougher to figure out.    Enter cellular
  278. automatons.
  279.       CA's were first invented in the 1940's when John von Neumann (he of
  280. the famous bottleneck) started to explore the mathmatic implications of very
  281. simple machines.  CA's are made of geometric patterns of cells that change
  282. their state at each tick of a clock according to a fixed rule.    Early work
  283. provided automatons that could imitate a basic computer.  Since the CA's are
  284. inherently parallel (the entire geometry is updated each clock tick) and easy
  285. to put on a chip, there is speculation that the next generation of parallel
  286. processing computers will use CA's as a base rather than the Turing machine
  287. model.
  288.        You have probably seen a CA at work and not realized it if you've
  289. ever seen the computer graphic simulation 'LIFE' developed by John Conway at
  290. MIT to model real organisms.  The rule for automaton reproduction was incr-
  291. edibly simple: If a cell has two or three neighbors, no change in the cell.
  292. Fewer or more neighbors, it starves or is overcrowded to death, and repro-
  293. duction occurs when a blank space has exactly three neighbors.
  294.     Using these simple rules, incredibly complex patterns can be produced.
  295. Anything that can produce complex and varied results from a small algorithm is
  296. a good target for a random number application.    Enter Steven Wolfram from the
  297. Institute of Advanced Studies in Princeton, NJ.
  298.     Wolfram has been doing research on one-dimensional cellular machines,
  299. which have the advantage of being able to work with both todays machines and
  300. future parallel machines.  Wolfram has developed an automaton that is a one
  301. dimensional circular array modified by the rule:
  302.  
  303.     a(x,t) = a(x-1,t-1) XOR (a(x,t-1) OR a(x+1,t-1)) MOD k
  304.  
  305.     Where x is the position in the array and t is the time,
  306.     k is the number of available characters (k = LEN(Q$)),
  307.     and a is the one-dimensional array.
  308.  
  309.     This rule has several interesting properties.  The problem we had with
  310. linear algorithms was that simple algebra could be used to analyze the
  311. evolution of the algorithm (the patterns produced.)  All that you have to do is
  312. figure out how *one* cell evolves, then apply that pattern across the entire
  313. array.    In the above case, there is no way of analyzing the array at time t
  314. without loading the initial conditions and running the whole thing.
  315.     The second thing to note is that there are k to the power of w (where w
  316. is the width (number of cells) in array a) possible states the machine can be
  317. in, and not all of these states have a predecessor that generates it.  These
  318. states are called 'Garden of Eden' states, and can only occur if they are set
  319. as an ititial condition.
  320.      As a result, this rule is neither a one-to-one mathmatical mapping,
  321. nor is it and onto mapping of the set of arrays into itself.  In laymans'
  322. terms, this means that for any given array state it is impossible to tell what
  323. (if any) previous state generated it by mere pattern analysis.
  324.      While this isn't a file on breaking codes- about the only way to crack
  325. this one that's been discovered is to load *every* k**w state into memory and
  326. page through them searching for a pattern.  This method can be defeated easily
  327. by setting w to more than 30 cells (assuming k=256, all the ASCII characters.)
  328. If you are using my array Q$, you might want to set w to 40 or more.  Since 256
  329. to the 30th power is about a zillion bits, roughly equal to the largest memory
  330. bank in existence, there isn't much chance of anyone breaking it.  For the
  331. truly paranoid, set w to 50 and sleep easy at night.
  332.  
  333.      Anyway, back to the algorithm...
  334.  
  335.     Each of the cells is filled on one of the k integers from 0 to k-1,
  336. giving each cell k possible states.  Wolfram found that the string of bits
  337. occupying the 0 position (a(0,1), a(0,2), a(0,3)...) forms a random sequence
  338. that passes all statistical tests, sometimes with better results than standard
  339. DES algorithms.
  340.     Let's break this down and see what it's doing.  First of all, we will
  341. need two arrays.  Each array is set up thus:
  342.  
  343.             Array for Time One
  344.     |------|       |------|       |------|        |------|
  345.   |---->|a(0,1)|------>|a(1,1)|------>|a(2,1)|----->|a(3,1)|-----|
  346.   |    |------|       |------|       |------|        |------|     |
  347.   |--------------------------------------------------------------|
  348.  
  349.             Array for Time Two
  350.     |------|       |------|       |------|        |------|
  351.   |---->|a(0,2)|------>|a(1,2)|------>|a(2,2)|----->|a(3,2)|-----|
  352.   |    |------|       |------|       |------|        |------|     |
  353.   |--------------------------------------------------------------|
  354.  
  355.     The reason we need two arrays is so you can update the array without
  356. destroying anything in it.  In other words, you start out with array 1 active,
  357. then you update the array into array 2 and change the active array to 2.  On
  358. the next clock tick you will update the active array (now 2) into the inactive
  359. one (now 1) and set the active array back to 1.  You keep swapping like this.
  360. Logically, you only have one array- the active one.
  361.      To initialize the array, the ASCII values of each character in the key
  362. are plugged into the first LEN(KEY$) spaces in the array.  If you want to use a
  363. short key, modify the code to fill the *entire* array with values of the key
  364. (keep repeating a loop from 1 to W pulling characters out of K).  Since the key
  365. can be anything printable, use something 10-20 characters long that you can
  366. remember- "HACK TO LIVE, LIVE TO HACK" is one of my favorites.  Anyway, if you
  367. use a short (less than 10) key in this program, the distri- bution will be
  368. skewed for the first W MOD LEN(KEY$) itereations of the automaton, but will
  369. smooth out nicely after that.
  370.       After the array is filled, it operates exactly like the first program
  371. *except* when it need a random number of positions to move.  Then it drops
  372. down, updates each cell in the automaton, and then reads the value in A(0,time)
  373. as the random number to shift by.
  374.       Let's look at the modified encryption code.
  375.  
  376. REM ************************************************************************
  377. REM
  378. REM  This is an modification of Program 1 that doesn't use a machine
  379. REM  specific random number generator, but instead uses a cellular automaton
  380. REM  algorithm.  W is the width of the actual automaton.  A is dimensioned
  381. REM  at 32 to avoid having to reference element 0 of the array, which is
  382. REM  legal on some systems and illegal on the others.  This way it can
  383. REM  be implemented on anything.  Y is set for time 1, Y1 for time 2.
  384. REM  These correspond to the second dimension in array A.
  385. REM
  386. REM ************************************************************************
  387.  
  388. W = 30
  389. DIM A(32,2)
  390. Y = 1
  391. Y1 = 2
  392.  
  393. REM ************************************************************************
  394. REM
  395. REM  Once again, you can set this up to use files instead of strings. And
  396. REM  note that, unlike the first example, the key doesn't have to be
  397. REM  numeric.
  398. REM
  399. REM ************************************************************************
  400.  
  401. INPUT "String to be encoded"; C$
  402. INPUT "Key Please! (Can be alpha-numeric) ";K$
  403.  
  404.  
  405. REM ************************************************************************
  406. REM
  407. REM  This is where K$ is broken down into a series of characters and their
  408. REM  ASCII value shoved sequentially into array A.
  409. REM
  410. REM ************************************************************************
  411.  
  412. FOR I = 1 TO LEN(K$)
  413.   T$ = MID$(K$,I,1)
  414.   A(I,Y1) = ASC(T$)
  415. NEXT I
  416.  
  417.  
  418. REM ************************************************************************
  419. REM
  420. REM  The only difference between encoding and decoding is which way you
  421. REM  move in your Q$ array space.  Encoding takes the original and shifts
  422. REM  to the right, decoding takes the codes value and shifts to the left.
  423. REM
  424. REM ************************************************************************
  425.  
  426. REREAD:
  427.   INPUT "Encode or Decode ? ";A$
  428.   A$=LEFT$(A$,1)
  429.   IF A$="E" OR A$="e" THEN
  430.     A=1
  431.     GOTO HEAD
  432.   END IF
  433.   IF A$="D" OR A$="d" THEN
  434.      A=-1
  435.   ELSE
  436.      GOTO REREAD
  437.   END IF
  438.  
  439. REM ************************************************************************
  440. REM
  441. REM  Q$ contains all the characters that can be encoded.  Every encoded
  442. REM  character will be mapped to a character in this array.  I haven't
  443. REM  included any non-standard characters, so you will have to customize
  444. REM  it to your particular keyboard/system.  I've included an error check
  445. REM  that will abort the encryption if it encounters a character that isn't
  446. REM  in Q$.  I have to use the STRING$ command to insert the spacebar and
  447. REM  the quote into the string.  It could also be done with a ASC(##) in
  448. REM  many basics.  You could expand this to include any non-printable
  449. REM  characters you'd like so you could do non-text files.
  450. REM
  451. REM ************************************************************************
  452.  
  453. HEAD:
  454.   SPACE = 32
  455.   QUOTE = 34
  456.   Q$="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  457.   Q$=Q$+"1234567890!@#$%^&*()-=_+[]$;:'.><,/?X|"
  458.   Q$=Q$+STRING$(1,SPACE)+STRING$(1,QUOTE)
  459.   QSIZ = LEN(Q$)
  460.  
  461.  
  462. REM ************************************************************************
  463. REM
  464. REM  This is the main loop.  L = length of the string to encrypt.  In this
  465. REM  example, I am only encrypting a single string.  Most people who will
  466. REM  actually use this will change the FOR loop to run until an EOF is
  467. REM  encountered in the input file.  Since the syntax for that will vary
  468. REM  widely from system to system, I'll leave it out.
  469. REM
  470. REM ************************************************************************
  471.  
  472. L=LEN(C$)
  473. FOR H = 1 TO L
  474.  
  475. REM /* Finds the character I in the input string */
  476.   X$ = MID$(C$,H,1)
  477.  
  478. REM /* Finds the integer location of the character in Q$
  479. REM    returns variable POZ */
  480.   GOSUB LOKPOZ
  481.  
  482. REM /* CELLULAR updates the cells in the automaton, switches the active
  483. REM    time value, and returns X as the number of positions to shift. */
  484.   GOSUB CELLULAR
  485.  
  486. REM /* If you are encoding, you will shift to the right using addition.
  487. REM    you take the modula base QSIZ to keep the new character within
  488. REM    the bounds of Q$. */
  489.   IF A = 1 THEN
  490.     NUPOZ = (POZ + X) MOD QSIZ
  491.   ELSE
  492.  
  493. REM /* Otherwise, you subtract, which takes a bit more math to keep
  494. REM    up with.  Once you have the distance to shift, you must
  495. REM    convert it to a positive integer and then subtract two to
  496. REM    account for the head & tail of the array. */
  497.     NUPOZ = (POZ - X) MOD QSIZ
  498.     NUPOZ = NUPOZ - 2
  499.       IF NUPOZ < 1 THEN
  500.     NUPOZ = QSIZ - ABS(NUPOZ)
  501.       END IF
  502.     END IF
  503.  
  504. REM /* Now you assign the new character in array Q$ to Y$, and append
  505. REM    it to your converted string */
  506.   IF NUPOZ < 1 THEN
  507.     NUPOZ = QSIZ - ABS(NUPOZ)
  508.   END IF
  509.   Y$ = MID$(Q$,NUPOZ,1)
  510.   D$ = D$ + Y$
  511. NEXT H
  512.  
  513. PRINT  "Original = ";C$
  514. PRINT  "Modified = ";D$
  515. END
  516.  
  517. REM /* This finds character X$ in array Q$ and returns an integer
  518. REM    value of the location.  Called from the main loop. */
  519. LOKPOZ:
  520.   FOUND = 0
  521.   POZ = 1
  522.   TOP:
  523.     IF FOUND = 1 THEN
  524.       RETURN
  525.     ELSE
  526.       TMP$ = MID$(Q$,POZ,1)
  527.       IF X$ = TMP$ THEN
  528.     FOUND = 1
  529.       END IF
  530.       POZ = POZ + 1
  531.       IF POZ > QSIZ THEN
  532.     PRINT  "Error: Character '";X$"' not in array Q."
  533.     END
  534.       END IF
  535.     END IF
  536.   GOTO TOP
  537.  
  538. REM ***********************************************************************
  539. REM
  540. REM  This is the cellular automaton
  541. REM
  542. REM ***********************************************************************
  543.  
  544. CELLULAR:
  545.  
  546. REM /* Goes through the loop updating into the inactive time (1 or 2 dep-
  547. REM    ending on how Y and Y1 are assigned) */
  548.   FOR I = 1 TO W
  549.     A(I,Y) = A(I-1,Y1) XOR (A(I,Y1) OR A(I+1,Y1))
  550.   NEXT I
  551.  
  552. REM /* Updates the ends of the array (logical positions 0 and 31) that
  553. REM    are used in calculating other fields. */
  554.   A(0,Y) = A(W+1,Y1) XOR (A(0,Y1) OR A(1,Y1))
  555.   A(W+1,Y) = A(W,Y1) XOR (A(W+1,Y1) OR A(0,Y1))
  556.  
  557. REM /* Assigns the first cell to X as a random number */
  558.   X = A(1,Y)
  559.  
  560. REM /* Flips the active time */
  561.   TMP = Y
  562.   Y = Y1
  563.   Y1 = TMP
  564.  
  565. RETURN
  566.  
  567.      Ok, let's trace through a *small* example.  Assume our earlier
  568. map of "AEIOU12345" and an automaton of width 5.  For a key, we'll use
  569. "A15".
  570.  
  571. 1) Assign ASC(A) to a(1,1), ASC(1) to a(2,1), ASC(5) to a(3,1).
  572.    ("0" will represent an empty cell in this example.)
  573.    A(time 1) = 0 65 49 53 0 0 0
  574.    (Remember that an array of width 5 is going to have 7 actual elements)
  575.  
  576. 2) Now then, we want to encrypt the string "EE3"
  577.    First, we locate where E is in our map. LOKPOZ("E") = 2
  578.  
  579. 3) Now then, we update the automaton.
  580.    a(1,2) = 0 XOR (65 OR 49)
  581.    a(2,2) = 65 XOR (49 OR 53)
  582.    a(3,2) = 49 XOR (53 OR 0)
  583.    a(4,2) = 53 XOR (0 OR 0)
  584.    a(5,2) = 0 XOR (0 OR 0)
  585.  
  586.    Since this isn't a tutorial on binary numbers and boolean algebra, you'll
  587.    have to trust me on this one...
  588.  
  589.    a(1,2) = 113
  590.    a(2,2) = 116
  591.    a(3,2) = 4
  592.    a(4,2) = 53
  593.    a(5,2) = 0
  594.  
  595. 4) Now we update the ends.
  596.    a(0,2) = 0 XOR (0 OR 65)
  597.    a(6,2) = 0 XOR (0 OR 0)
  598.  
  599.    Again...
  600.    a(0,2) = 65
  601.    a(6,2) = 0
  602.  
  603. 5) Now we switch the active time from 1 to 2, and our new automaton is
  604.    a(time 2) = 65 113 116 4 53 0 0
  605.  
  606. 6) We then pull off a(1,2) as the number to shift by.
  607.  
  608. 7) Postion 2 + 113 (we're encoding, so we add) is 5 (modulo arithmatic.)
  609.  
  610. 8) "E" is encoded into "U".
  611.  
  612. 9) We repeat this two more times (you don't really want me to step through
  613.    it all, do you?) and end up with the encrypted version.
  614.  
  615.      Well, that's going to pretty much wrap this file up.  If you are
  616. interested in more files of this nature, let me know.  If you find this totally
  617. confusing, but want to learn more, call The Phoenix Project at 512/441-3088
  618. (300/1200/2400, 24 hours a day).  Our friendly and helpful LOD/H staff will be
  619. glad to assist you.  Other people who you might want to talk to about
  620. encryption include Dr. Cypher, Tuc, and Prime Suspect.
  621.      Also, if you are interested in seeing the above algorithm applied in
  622. other languages let me know.  If there's enough of a demand I'll release C,
  623. Modula-2, and ADA versions.
  624.  
  625.        This has been a Legion of Doom/Legion of Hackers presentation!
  626.  
  627.                   The Mentor
  628.                  LOD/H
  629.  
  630. *****************************************************************************
  631. References and Acknowledgments:
  632.  
  633. "How to Generate Cryptographically Strong Sequences of Pseudo-Random Bits";
  634. M. Blum & S. Micali; SIAM Journal of Computing, vol. 13, p. 850 (1984)
  635.  
  636. "Functions of Random Variables"; John Freund & Ronald Walpole;
  637. Mathmatical Statistics, 4th Edition; Prentice-Hall Inc., NJ; pp. 240-71
  638.  
  639. "Building an Encryption System"; Peter Wayner
  640. Computer Language, Vol. 4, Num. 12, p. 67 (Dec. 1987 Issue)
  641.  
  642. "Random Sequence Generation by Cellular Automata"; Institute for Advanced
  643. Study; Advances in Applied Mathmatics;
  644.  
  645. "Breaking Pseudo-Random Number Based Cryptographic Algorithms"; M. Vahle &
  646. L. Tolendino;  CRYPTOLOGIA, Oct 1982, p. 319
  647.  
  648. Also my thanks to: TUC, The Leftist, Prime Suspect, and Dr. Cypher, who all
  649.      contributed to this one way or another.
  650.  
  651. ***************************************************************************
  652.  
  653.  
  654.