blob: d0da590cede1de4f66ae8f73d6a2756f549446ea [file] [log] [blame]
Guido van Rossum50098201992-07-31 15:10:13 +00001/***********************************************************
Guido van Rossumf6971e21994-08-30 12:25:20 +00002Copyright 1994 by Lance Ellinghouse,
3Cathedral City, California Republic, United States of America.
Guido van Rossum50098201992-07-31 15:10:13 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
Guido van Rossumf6971e21994-08-30 12:25:20 +000011supporting documentation, and that the name of Lance Ellinghouse
12not be used in advertising or publicity pertaining to distribution
13of the software without specific, written prior permission.
Guido van Rossum50098201992-07-31 15:10:13 +000014
Guido van Rossumf6971e21994-08-30 12:25:20 +000015LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
Guido van Rossum50098201992-07-31 15:10:13 +000016THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
Guido van Rossumf6971e21994-08-30 12:25:20 +000017FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE BE LIABLE FOR ANY SPECIAL,
18INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
19FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum50098201992-07-31 15:10:13 +000022
23******************************************************************/
24
25/* This creates an encryption and decryption engine I am calling
26 a rotor due to the original design was a harware rotor with
27 contacts used in Germany during WWII.
28
29Rotor Module:
30
31- rotor.newrotor('key') -> rotorobject (default of 6 rotors)
32- rotor.newrotor('key', num_rotors) -> rotorobject
33
34Rotor Objects:
35
Guido van Rossum7b2c03f1992-08-02 09:00:06 +000036- ro.setkey('string') -> None (resets the key as defined in newrotor().
Guido van Rossum50098201992-07-31 15:10:13 +000037- ro.encrypt('string') -> encrypted string
38- ro.decrypt('encrypted string') -> unencrypted string
39
Guido van Rossum7b2c03f1992-08-02 09:00:06 +000040- ro.encryptmore('string') -> encrypted string
41- ro.decryptmore('encrypted string') -> unencrypted string
42
43NOTE: the {en,de}cryptmore() methods use the setup that was
44 established via the {en,de}crypt calls. They will NOT
45 re-initalize the rotors unless: 1) They have not been
46 initalized with {en,de}crypt since the last setkey() call;
47 2) {en,de}crypt has not been called for this rotor yet.
48
Guido van Rossum50098201992-07-31 15:10:13 +000049NOTE: you MUST use the SAME key in rotor.newrotor()
50 if you wish to decrypt an encrypted string.
51 Also, the encrypted string is NOT 0-127 ASCII.
52 It is considered BINARY data.
53
54*/
55
56/* Rotor objects */
57
Guido van Rossum602099a1994-09-14 13:32:22 +000058#include "Python.h"
Guido van Rossuma320fd31995-03-09 12:14:15 +000059#include "mymath.h"
Guido van Rossuma597dde1995-01-10 20:56:29 +000060
Guido van Rossum7b2c03f1992-08-02 09:00:06 +000061#define TRUE 1
62#define FALSE 0
Guido van Rossum50098201992-07-31 15:10:13 +000063
64typedef struct {
Guido van Rossum7b1e9741994-08-29 10:46:42 +000065 PyObject_HEAD
Guido van Rossum50098201992-07-31 15:10:13 +000066 int seed[3];
67 short key[5];
Guido van Rossum7b2c03f1992-08-02 09:00:06 +000068 int isinited;
Guido van Rossum50098201992-07-31 15:10:13 +000069 int size;
70 int size_mask;
71 int rotors;
Barry Warsawaeb207c1996-12-23 23:36:24 +000072 unsigned char *e_rotor; /* [num_rotors][size] */
73 unsigned char *d_rotor; /* [num_rotors][size] */
74 unsigned char *positions; /* [num_rotors] */
75 unsigned char *advances; /* [num_rotors] */
76} Rotorobj;
Guido van Rossum50098201992-07-31 15:10:13 +000077
Barry Warsawaeb207c1996-12-23 23:36:24 +000078staticforward PyTypeObject Rotor_Type;
Guido van Rossum50098201992-07-31 15:10:13 +000079
Barry Warsawaeb207c1996-12-23 23:36:24 +000080#define is_rotor(v) ((v)->ob_type == &Rotor_Type)
Guido van Rossum50098201992-07-31 15:10:13 +000081
82/*
83 This defines the necessary routines to manage rotor objects
84*/
85
Barry Warsawaeb207c1996-12-23 23:36:24 +000086static void
87set_seed(r)
88 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +000089{
90 r->seed[0] = r->key[0];
91 r->seed[1] = r->key[1];
92 r->seed[2] = r->key[2];
Guido van Rossum7b2c03f1992-08-02 09:00:06 +000093 r->isinited = FALSE;
Guido van Rossum50098201992-07-31 15:10:13 +000094}
95
96/* Return the next random number in the range [0.0 .. 1.0) */
Barry Warsawaeb207c1996-12-23 23:36:24 +000097static float
98r_random(r)
99 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000100{
101 int x, y, z;
102 float val, term;
103
104 x = r->seed[0];
105 y = r->seed[1];
106 z = r->seed[2];
107
108 x = 171 * (x % 177) - 2 * (x/177);
109 y = 172 * (y % 176) - 35 * (y/176);
110 z = 170 * (z % 178) - 63 * (z/178);
111
112 if (x < 0) x = x + 30269;
113 if (y < 0) y = y + 30307;
114 if (z < 0) z = z + 30323;
115
116 r->seed[0] = x;
117 r->seed[1] = y;
118 r->seed[2] = z;
119
120 term = (float)(
Barry Warsawaeb207c1996-12-23 23:36:24 +0000121 (((float)x)/(float)30269.0) +
122 (((float)y)/(float)30307.0) +
123 (((float)z)/(float)30323.0)
124 );
Guido van Rossum50098201992-07-31 15:10:13 +0000125 val = term - (float)floor((double)term);
126
Barry Warsawaeb207c1996-12-23 23:36:24 +0000127 if (val >= 1.0)
128 val = 0.0;
Guido van Rossum50098201992-07-31 15:10:13 +0000129
130 return val;
131}
132
Barry Warsawaeb207c1996-12-23 23:36:24 +0000133static short
134r_rand(r, s)
135 Rotorobj *r;
136 short s;
Guido van Rossum50098201992-07-31 15:10:13 +0000137{
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000138 /*short tmp = (short)((int)(r_random(r) * (float)32768.0) % 32768);*/
Guido van Rossum50098201992-07-31 15:10:13 +0000139 short tmp = (short)((short)(r_random(r) * (float)s) % s);
140 return tmp;
141}
142
Barry Warsawaeb207c1996-12-23 23:36:24 +0000143static void
144set_key(r, key)
145 Rotorobj *r;
146 char *key;
Guido van Rossum50098201992-07-31 15:10:13 +0000147{
Guido van Rossume77a7571993-11-03 15:01:26 +0000148#ifdef BUGGY_CODE_BW_COMPAT
149 /* See comments below */
Guido van Rossum50098201992-07-31 15:10:13 +0000150 int k1=995, k2=576, k3=767, k4=671, k5=463;
Guido van Rossume77a7571993-11-03 15:01:26 +0000151#else
152 unsigned long k1=995, k2=576, k3=767, k4=671, k5=463;
153#endif
Guido van Rossum50098201992-07-31 15:10:13 +0000154 int i;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000155 int len = strlen(key);
156 for (i = 0; i < len; i++) {
Guido van Rossum06676261993-11-01 16:20:18 +0000157#ifdef BUGGY_CODE_BW_COMPAT
158 /* This is the code as it was originally released.
159 It causes warnings on many systems and can generate
160 different results as well. If you have files
161 encrypted using an older version you may want to
162 #define BUGGY_CODE_BW_COMPAT so as to be able to
163 decrypt them... */
Guido van Rossum50098201992-07-31 15:10:13 +0000164 k1 = (((k1<<3 | k1<<-13) + key[i]) & 65535);
165 k2 = (((k2<<3 | k2<<-13) ^ key[i]) & 65535);
166 k3 = (((k3<<3 | k3<<-13) - key[i]) & 65535);
167 k4 = ((key[i] - (k4<<3 | k4<<-13)) & 65535);
168 k5 = (((k5<<3 | k5<<-13) ^ ~key[i]) & 65535);
Guido van Rossum06676261993-11-01 16:20:18 +0000169#else
170 /* This code should be more portable */
171 k1 = (((k1<<3 | k1>>13) + key[i]) & 65535);
172 k2 = (((k2<<3 | k2>>13) ^ key[i]) & 65535);
173 k3 = (((k3<<3 | k3>>13) - key[i]) & 65535);
174 k4 = ((key[i] - (k4<<3 | k4>>13)) & 65535);
175 k5 = (((k5<<3 | k5>>13) ^ ~key[i]) & 65535);
176#endif
Guido van Rossum50098201992-07-31 15:10:13 +0000177 }
178 r->key[0] = (short)k1;
179 r->key[1] = (short)(k2|1);
180 r->key[2] = (short)k3;
181 r->key[3] = (short)k4;
182 r->key[4] = (short)k5;
183
184 set_seed(r);
185}
186
187/* These define the interface to a rotor object */
Barry Warsawaeb207c1996-12-23 23:36:24 +0000188static Rotorobj *
189rotorobj_new(num_rotors, key)
Guido van Rossum50098201992-07-31 15:10:13 +0000190 int num_rotors;
191 char *key;
192{
Barry Warsawaeb207c1996-12-23 23:36:24 +0000193 Rotorobj *xp;
194
195 xp = PyObject_NEW(Rotorobj, &Rotor_Type);
Guido van Rossum50098201992-07-31 15:10:13 +0000196 if (xp == NULL)
197 return NULL;
Guido van Rossume6e9fe181992-07-31 15:11:01 +0000198 set_key(xp, key);
Guido van Rossum50098201992-07-31 15:10:13 +0000199
200 xp->size = 256;
201 xp->size_mask = xp->size - 1;
202 xp->size_mask = 0;
203 xp->rotors = num_rotors;
Guido van Rossume6e9fe181992-07-31 15:11:01 +0000204 xp->e_rotor = NULL;
205 xp->d_rotor = NULL;
206 xp->positions = NULL;
207 xp->advances = NULL;
Guido van Rossum50098201992-07-31 15:10:13 +0000208
Barry Warsawaeb207c1996-12-23 23:36:24 +0000209 if (!(xp->e_rotor = PyMem_NEW(unsigned char, num_rotors * xp->size)))
210 goto finally;
211 if (!(xp->d_rotor = PyMem_NEW(unsigned char, num_rotors * xp->size)))
212 goto finally;
213 if (!(xp->positions = PyMem_NEW(unsigned char, num_rotors)))
214 goto finally;
215 if (!(xp->advances = PyMem_NEW(unsigned char, num_rotors)))
216 goto finally;
217
Guido van Rossum50098201992-07-31 15:10:13 +0000218 return xp;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000219
220 finally:
221 PyMem_XDEL(xp->e_rotor);
222 PyMem_XDEL(xp->d_rotor);
223 PyMem_XDEL(xp->positions);
224 PyMem_XDEL(xp->advances);
Guido van Rossuma597dde1995-01-10 20:56:29 +0000225 Py_DECREF(xp);
Barry Warsawaeb207c1996-12-23 23:36:24 +0000226 return (Rotorobj*)PyErr_NoMemory();
Guido van Rossum50098201992-07-31 15:10:13 +0000227}
228
229/* These routines impliment the rotor itself */
230
Barry Warsawaeb207c1996-12-23 23:36:24 +0000231/* Here is a fairly sofisticated {en,de}cryption system. It is based
232 on the idea of a "rotor" machine. A bunch of rotors, each with a
233 different permutation of the alphabet, rotate around a different amount
234 after encrypting one character. The current state of the rotors is
235 used to encrypt one character.
Guido van Rossum50098201992-07-31 15:10:13 +0000236
Barry Warsawaeb207c1996-12-23 23:36:24 +0000237 The code is smart enought to tell if your alphabet has a number of
238 characters equal to a power of two. If it does, it uses logical
239 operations, if not it uses div and mod (both require a division).
Guido van Rossum50098201992-07-31 15:10:13 +0000240
Barry Warsawaeb207c1996-12-23 23:36:24 +0000241 You will need to make two changes to the code 1) convert to c, and
242 customize for an alphabet of 255 chars 2) add a filter at the begining,
243 and end, which subtracts one on the way in, and adds one on the way
244 out.
Guido van Rossum50098201992-07-31 15:10:13 +0000245
Barry Warsawaeb207c1996-12-23 23:36:24 +0000246 You might wish to do some timing studies. Another viable alternative
247 is to "byte stuff" the encrypted data of a normal (perhaps this one)
248 encryption routine.
Guido van Rossum50098201992-07-31 15:10:13 +0000249
Barry Warsawaeb207c1996-12-23 23:36:24 +0000250 j'
Guido van Rossum50098201992-07-31 15:10:13 +0000251*/
252
253/*(defun RTR-make-id-rotor (rotor)
254 "Set ROTOR to the identity permutation"
255 (let ((j 0))
256 (while (< j RTR-size)
257 (aset rotor j j)
258 (setq j (+ 1 j)))
Barry Warsawaeb207c1996-12-23 23:36:24 +0000259 rotor))
260*/
261static void
262RTR_make_id_rotor(r, rtr)
263 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000264 unsigned char *rtr;
265{
266 register int j;
267 register int size = r->size;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000268 for (j = 0; j < size; j++) {
Guido van Rossum50098201992-07-31 15:10:13 +0000269 rtr[j] = (unsigned char)j;
270 }
271}
272
273
274/*(defvar RTR-e-rotors
275 (let ((rv (make-vector RTR-number-of-rotors 0))
276 (i 0)
277 tr)
278 (while (< i RTR-number-of-rotors)
279 (setq tr (make-vector RTR-size 0))
280 (RTR-make-id-rotor tr)
281 (aset rv i tr)
282 (setq i (+ 1 i)))
283 rv)
Barry Warsawaeb207c1996-12-23 23:36:24 +0000284 "The current set of encryption rotors")
285*/
286static void
287RTR_e_rotors(r)
288 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000289{
290 int i;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000291 for (i = 0; i < r->rotors; i++) {
292 RTR_make_id_rotor(r, &(r->e_rotor[(i*r->size)]));
Guido van Rossum50098201992-07-31 15:10:13 +0000293 }
294}
295
296/*(defvar RTR-d-rotors
297 (let ((rv (make-vector RTR-number-of-rotors 0))
298 (i 0)
299 tr)
300 (while (< i RTR-number-of-rotors)
301 (setq tr (make-vector RTR-size 0))
302 (setq j 0)
303 (while (< j RTR-size)
304 (aset tr j j)
305 (setq j (+ 1 j)))
306 (aset rv i tr)
307 (setq i (+ 1 i)))
308 rv)
Barry Warsawaeb207c1996-12-23 23:36:24 +0000309 "The current set of decryption rotors")
310*/
311static void
312RTR_d_rotors(r)
313 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000314{
315 register int i, j;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000316 for (i = 0; i < r->rotors; i++) {
317 for (j = 0; j < r->size; j++) {
Guido van Rossum50098201992-07-31 15:10:13 +0000318 r->d_rotor[((i*r->size)+j)] = (unsigned char)j;
319 }
320 }
321}
322
323/*(defvar RTR-positions (make-vector RTR-number-of-rotors 1)
Barry Warsawaeb207c1996-12-23 23:36:24 +0000324 "The positions of the rotors at this time")
325*/
326static void
327RTR_positions(r)
328 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000329{
330 int i;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000331 for (i = 0; i < r->rotors; i++) {
Guido van Rossum50098201992-07-31 15:10:13 +0000332 r->positions[i] = 1;
333 }
334}
335
336/*(defvar RTR-advances (make-vector RTR-number-of-rotors 1)
Barry Warsawaeb207c1996-12-23 23:36:24 +0000337 "The number of positions to advance the rotors at a time")
338*/
339static void
340RTR_advances(r)
341 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000342{
343 int i;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000344 for (i = 0; i < r->rotors; i++) {
Guido van Rossum50098201992-07-31 15:10:13 +0000345 r->advances[i] = 1;
346 }
347}
348
349/*(defun RTR-permute-rotor (e d)
350 "Permute the E rotor, and make the D rotor its inverse"
Barry Warsawaeb207c1996-12-23 23:36:24 +0000351 ;; see Knuth for explaination of algorithm.
Guido van Rossum50098201992-07-31 15:10:13 +0000352 (RTR-make-id-rotor e)
353 (let ((i RTR-size)
354 q j)
355 (while (<= 2 i)
356 (setq q (fair16 i)) ; a little tricky, decrement here
357 (setq i (- i 1)) ; since we have origin 0 array's
358 (setq j (aref e q))
359 (aset e q (aref e i))
360 (aset e i j)
361 (aset d j i))
362 (aset e 0 (aref e 0)) ; don't forget e[0] and d[0]
Barry Warsawaeb207c1996-12-23 23:36:24 +0000363 (aset d (aref e 0) 0)))
364*/
365static void
366RTR_permute_rotor(r, e, d)
367 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000368 unsigned char *e;
369 unsigned char *d;
370{
371 short i = r->size;
372 short q;
373 unsigned char j;
374 RTR_make_id_rotor(r,e);
375 while (2 <= i) {
376 q = r_rand(r,i);
377 i--;
378 j = e[q];
379 e[q] = (unsigned char)e[i];
380 e[i] = (unsigned char)j;
381 d[j] = (unsigned char)i;
382 }
383 e[0] = (unsigned char)e[0];
384 d[(e[0])] = (unsigned char)0;
385}
386
387/*(defun RTR-init (key)
388 "Given KEY (a list of 5 16 bit numbers), initialize the rotor machine.
389Set the advancement, position, and permutation of the rotors"
390 (R16-set-state key)
391 (let (i)
392 (setq i 0)
393 (while (< i RTR-number-of-rotors)
394 (aset RTR-positions i (fair16 RTR-size))
395 (aset RTR-advances i (+ 1 (* 2 (fair16 (/ RTR-size 2)))))
396 (message "Initializing rotor %d..." i)
397 (RTR-permute-rotor (aref RTR-e-rotors i) (aref RTR-d-rotors i))
Barry Warsawaeb207c1996-12-23 23:36:24 +0000398 (setq i (+ 1 i)))))
399*/
400static void
401RTR_init(r)
402 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000403{
404 int i;
405 set_seed(r);
406 RTR_positions(r);
407 RTR_advances(r);
408 RTR_e_rotors(r);
409 RTR_d_rotors(r);
Barry Warsawaeb207c1996-12-23 23:36:24 +0000410 for (i = 0; i < r->rotors; i++) {
Guido van Rossum50098201992-07-31 15:10:13 +0000411 r->positions[i] = r_rand(r,r->size);
412 r->advances[i] = (1+(2*(r_rand(r,r->size/2))));
Barry Warsawaeb207c1996-12-23 23:36:24 +0000413 RTR_permute_rotor(r,
414 &(r->e_rotor[(i*r->size)]),
415 &(r->d_rotor[(i*r->size)]));
Guido van Rossum50098201992-07-31 15:10:13 +0000416 }
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000417 r->isinited = TRUE;
Guido van Rossum50098201992-07-31 15:10:13 +0000418}
419
420/*(defun RTR-advance ()
421 "Change the RTR-positions vector, using the RTR-advances vector"
422 (let ((i 0)
423 (temp 0))
424 (if RTR-size-mask
425 (while (< i RTR-number-of-rotors)
426 (setq temp (+ (aref RTR-positions i) (aref RTR-advances i)))
427 (aset RTR-positions i (logand temp RTR-size-mask))
428 (if (and (>= temp RTR-size)
429 (< i (- RTR-number-of-rotors 1)))
430 (aset RTR-positions (+ i 1)
431 (+ 1 (aref RTR-positions (+ i 1)))))
432 (setq i (+ i 1)))
433 (while (< i RTR-number-of-rotors)
434 (setq temp (+ (aref RTR-positions i) (aref RTR-advances i)))
435 (aset RTR-positions i (% temp RTR-size))
436 (if (and (>= temp RTR-size)
437 (< i (- RTR-number-of-rotors 1)))
438 (aset RTR-positions (+ i 1)
439 (+ 1 (aref RTR-positions (+ i 1)))))
Barry Warsawaeb207c1996-12-23 23:36:24 +0000440 (setq i (+ i 1))))))
441*/
442static void
443RTR_advance(r)
444 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000445{
446 register int i=0, temp=0;
447 if (r->size_mask) {
Barry Warsawaeb207c1996-12-23 23:36:24 +0000448 while (i < r->rotors) {
Guido van Rossum50098201992-07-31 15:10:13 +0000449 temp = r->positions[i] + r->advances[i];
450 r->positions[i] = temp & r->size_mask;
451 if ((temp >= r->size) && (i < (r->rotors - 1))) {
452 r->positions[(i+1)] = 1 + r->positions[(i+1)];
453 }
454 i++;
455 }
456 } else {
Barry Warsawaeb207c1996-12-23 23:36:24 +0000457 while (i < r->rotors) {
Guido van Rossum50098201992-07-31 15:10:13 +0000458 temp = r->positions[i] + r->advances[i];
459 r->positions[i] = temp%r->size;
460 if ((temp >= r->size) && (i < (r->rotors - 1))) {
461 r->positions[(i+1)] = 1 + r->positions[(i+1)];
462 }
463 i++;
464 }
465 }
466}
467
468/*(defun RTR-e-char (p)
469 "Encrypt the character P with the current rotor machine"
470 (let ((i 0))
471 (if RTR-size-mask
472 (while (< i RTR-number-of-rotors)
473 (setq p (aref (aref RTR-e-rotors i)
474 (logand (logxor (aref RTR-positions i)
475 p)
476 RTR-size-mask)))
477 (setq i (+ 1 i)))
478 (while (< i RTR-number-of-rotors)
479 (setq p (aref (aref RTR-e-rotors i)
480 (% (logxor (aref RTR-positions i)
481 p)
482 RTR-size)))
483 (setq i (+ 1 i))))
484 (RTR-advance)
Barry Warsawaeb207c1996-12-23 23:36:24 +0000485 p))
486*/
487static unsigned char
488RTR_e_char(r, p)
489 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000490 unsigned char p;
491{
492 register int i=0;
493 register unsigned char tp=p;
494 if (r->size_mask) {
495 while (i < r->rotors) {
Barry Warsawaeb207c1996-12-23 23:36:24 +0000496 tp = r->e_rotor[(i*r->size) +
497 (((r->positions[i] ^ tp) &
498 r->size_mask))];
Guido van Rossum50098201992-07-31 15:10:13 +0000499 i++;
500 }
501 } else {
502 while (i < r->rotors) {
Barry Warsawaeb207c1996-12-23 23:36:24 +0000503 tp = r->e_rotor[(i*r->size) +
504 (((r->positions[i] ^ tp) %
505 (unsigned int) r->size))];
Guido van Rossum50098201992-07-31 15:10:13 +0000506 i++;
507 }
508 }
509 RTR_advance(r);
510 return ((unsigned char)tp);
511}
512
513/*(defun RTR-d-char (c)
514 "Decrypt the character C with the current rotor machine"
515 (let ((i (- RTR-number-of-rotors 1)))
516 (if RTR-size-mask
517 (while (<= 0 i)
518 (setq c (logand (logxor (aref RTR-positions i)
519 (aref (aref RTR-d-rotors i)
520 c))
521 RTR-size-mask))
522 (setq i (- i 1)))
523 (while (<= 0 i)
524 (setq c (% (logxor (aref RTR-positions i)
525 (aref (aref RTR-d-rotors i)
526 c))
527 RTR-size))
528 (setq i (- i 1))))
529 (RTR-advance)
Barry Warsawaeb207c1996-12-23 23:36:24 +0000530 c))
531*/
532static unsigned char
533RTR_d_char(r, c)
534 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000535 unsigned char c;
536{
Barry Warsawaeb207c1996-12-23 23:36:24 +0000537 register int i = r->rotors - 1;
538 register unsigned char tc = c;
539
Guido van Rossum50098201992-07-31 15:10:13 +0000540 if (r->size_mask) {
541 while (0 <= i) {
Barry Warsawaeb207c1996-12-23 23:36:24 +0000542 tc = (r->positions[i] ^
543 r->d_rotor[(i*r->size)+tc]) & r->size_mask;
Guido van Rossum50098201992-07-31 15:10:13 +0000544 i--;
545 }
546 } else {
547 while (0 <= i) {
Barry Warsawaeb207c1996-12-23 23:36:24 +0000548 tc = (r->positions[i] ^
549 r->d_rotor[(i*r->size)+tc]) %
550 (unsigned int) r->size;
Guido van Rossum50098201992-07-31 15:10:13 +0000551 i--;
552 }
553 }
554 RTR_advance(r);
555 return(tc);
556}
557
558/*(defun RTR-e-region (beg end key)
559 "Perform a rotor encryption of the region from BEG to END by KEY"
560 (save-excursion
561 (let ((tenth (/ (- end beg) 10)))
562 (RTR-init key)
563 (goto-char beg)
564 ;; ### make it stop evry 10% or so to tell us
565 (while (< (point) end)
566 (let ((fc (following-char)))
567 (insert-char (RTR-e-char fc) 1)
Barry Warsawaeb207c1996-12-23 23:36:24 +0000568 (delete-char 1))))))
569*/
570static void
571RTR_e_region(r, beg, len, doinit)
572 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000573 unsigned char *beg;
574 int len;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000575 int doinit;
Guido van Rossum50098201992-07-31 15:10:13 +0000576{
577 register int i;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000578 if (doinit || r->isinited == FALSE)
579 RTR_init(r);
Barry Warsawaeb207c1996-12-23 23:36:24 +0000580 for (i = 0; i < len; i++) {
581 beg[i] = RTR_e_char(r, beg[i]);
Guido van Rossum50098201992-07-31 15:10:13 +0000582 }
583}
584
585/*(defun RTR-d-region (beg end key)
586 "Perform a rotor decryption of the region from BEG to END by KEY"
587 (save-excursion
588 (progn
589 (RTR-init key)
590 (goto-char beg)
591 (while (< (point) end)
592 (let ((fc (following-char)))
593 (insert-char (RTR-d-char fc) 1)
Barry Warsawaeb207c1996-12-23 23:36:24 +0000594 (delete-char 1))))))
595*/
596static void
597RTR_d_region(r, beg, len, doinit)
598 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000599 unsigned char *beg;
600 int len;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000601 int doinit;
Guido van Rossum50098201992-07-31 15:10:13 +0000602{
603 register int i;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000604 if (doinit || r->isinited == FALSE)
605 RTR_init(r);
Barry Warsawaeb207c1996-12-23 23:36:24 +0000606 for (i = 0; i < len; i++) {
607 beg[i] = RTR_d_char(r, beg[i]);
Guido van Rossum50098201992-07-31 15:10:13 +0000608 }
609}
610
611
612/*(defun RTR-key-string-to-ints (key)
613 "Convert a string into a list of 4 numbers"
614 (let ((k1 995)
615 (k2 576)
616 (k3 767)
617 (k4 671)
618 (k5 463)
619 (i 0))
620 (while (< i (length key))
621 (setq k1 (logand (+ (logior (lsh k1 3) (lsh k1 -13)) (aref key i)) 65535))
622 (setq k2 (logand (logxor (logior (lsh k2 3) (lsh k2 -13)) (aref key i)) 65535))
623 (setq k3 (logand (- (logior (lsh k3 3) (lsh k3 -13)) (aref key i)) 65535))
624 (setq k4 (logand (- (aref key i) (logior (lsh k4 3) (lsh k4 -13))) 65535))
625 (setq k5 (logand (logxor (logior (lsh k5 3) (lsh k5 -13)) (lognot (aref key i))) 65535))
626 (setq i (+ i 1)))
627 (list k1 (logior 1 k2) k3 k4 k5)))*/
628/* This is done in set_key() above */
629
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000630#if 0
Guido van Rossum50098201992-07-31 15:10:13 +0000631/*(defun encrypt-region (beg end key)
632 "Interactivly encrypt the region"
633 (interactive "r\nsKey:")
634 (RTR-e-region beg end (RTR-key-string-to-ints key)))*/
635static void encrypt_region(r, region, len)
Barry Warsawaeb207c1996-12-23 23:36:24 +0000636 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000637 unsigned char *region;
638 int len;
639{
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000640 RTR_e_region(r,region,len,TRUE);
Guido van Rossum50098201992-07-31 15:10:13 +0000641}
642
643/*(defun decrypt-region (beg end key)
644 "Interactivly decrypt the region"
645 (interactive "r\nsKey:")
646 (RTR-d-region beg end (RTR-key-string-to-ints key)))*/
647static void decrypt_region(r, region, len)
Barry Warsawaeb207c1996-12-23 23:36:24 +0000648 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000649 unsigned char *region;
650 int len;
651{
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000652 RTR_d_region(r,region,len,TRUE);
Guido van Rossum50098201992-07-31 15:10:13 +0000653}
Barry Warsawaeb207c1996-12-23 23:36:24 +0000654#endif /* 0 */
Guido van Rossum50098201992-07-31 15:10:13 +0000655
656/* Rotor methods */
657
658static void
Barry Warsawaeb207c1996-12-23 23:36:24 +0000659rotor_dealloc(xp)
660 Rotorobj *xp;
Guido van Rossum50098201992-07-31 15:10:13 +0000661{
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000662 PyMem_XDEL(xp->e_rotor);
663 PyMem_XDEL(xp->d_rotor);
664 PyMem_XDEL(xp->positions);
665 PyMem_XDEL(xp->advances);
666 PyMem_DEL(xp);
Guido van Rossum50098201992-07-31 15:10:13 +0000667}
668
Guido van Rossumf6971e21994-08-30 12:25:20 +0000669static PyObject *
Barry Warsawaeb207c1996-12-23 23:36:24 +0000670rotorobj_encrypt(self, args)
671 Rotorobj *self;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000672 PyObject * args;
Guido van Rossum50098201992-07-31 15:10:13 +0000673{
Barry Warsawaeb207c1996-12-23 23:36:24 +0000674 char *string = NULL;
Guido van Rossum50098201992-07-31 15:10:13 +0000675 int len = 0;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000676 PyObject *rtn = NULL;
Guido van Rossum50098201992-07-31 15:10:13 +0000677 char *tmp;
678
Barry Warsawaeb207c1996-12-23 23:36:24 +0000679 if (!PyArg_Parse(args, "s#", &string, &len))
Guido van Rossum50098201992-07-31 15:10:13 +0000680 return NULL;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000681 if (!(tmp = PyMem_NEW(char, len+5))) {
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000682 PyErr_NoMemory();
Guido van Rossum50098201992-07-31 15:10:13 +0000683 return NULL;
684 }
Barry Warsawaeb207c1996-12-23 23:36:24 +0000685 memset(tmp, '\0', len+1);
686 memcpy(tmp, string, len);
687 RTR_e_region(self, (unsigned char *)tmp, len, TRUE);
688 rtn = PyString_FromStringAndSize(tmp, len);
689 PyMem_DEL(tmp);
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000690 return(rtn);
691}
692
Guido van Rossumf6971e21994-08-30 12:25:20 +0000693static PyObject *
Barry Warsawaeb207c1996-12-23 23:36:24 +0000694rotorobj_encrypt_more(self, args)
695 Rotorobj *self;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000696 PyObject * args;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000697{
Barry Warsawaeb207c1996-12-23 23:36:24 +0000698 char *string = NULL;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000699 int len = 0;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000700 PyObject *rtn = NULL;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000701 char *tmp;
702
Barry Warsawaeb207c1996-12-23 23:36:24 +0000703 if (!PyArg_Parse(args, "s#", &string, &len))
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000704 return NULL;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000705 if (!(tmp = PyMem_NEW(char, len+5))) {
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000706 PyErr_NoMemory();
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000707 return NULL;
708 }
Barry Warsawaeb207c1996-12-23 23:36:24 +0000709 memset(tmp, '\0', len+1);
710 memcpy(tmp, string, len);
711 RTR_e_region(self, (unsigned char *)tmp, len, FALSE);
712 rtn = PyString_FromStringAndSize(tmp, len);
713 PyMem_DEL(tmp);
Guido van Rossum50098201992-07-31 15:10:13 +0000714 return(rtn);
715}
716
Guido van Rossumf6971e21994-08-30 12:25:20 +0000717static PyObject *
Barry Warsawaeb207c1996-12-23 23:36:24 +0000718rotorobj_decrypt(self, args)
719 Rotorobj *self;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000720 PyObject * args;
Guido van Rossum50098201992-07-31 15:10:13 +0000721{
Barry Warsawaeb207c1996-12-23 23:36:24 +0000722 char *string = NULL;
Guido van Rossum50098201992-07-31 15:10:13 +0000723 int len = 0;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000724 PyObject *rtn = NULL;
Guido van Rossum50098201992-07-31 15:10:13 +0000725 char *tmp;
726
Barry Warsawaeb207c1996-12-23 23:36:24 +0000727 if (!PyArg_Parse(args, "s#", &string, &len))
Guido van Rossum50098201992-07-31 15:10:13 +0000728 return NULL;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000729 if (!(tmp = PyMem_NEW(char, len+5))) {
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000730 PyErr_NoMemory();
Guido van Rossum50098201992-07-31 15:10:13 +0000731 return NULL;
732 }
Barry Warsawaeb207c1996-12-23 23:36:24 +0000733 memset(tmp, '\0', len+1);
734 memcpy(tmp, string, len);
735 RTR_d_region(self, (unsigned char *)tmp, len, TRUE);
736 rtn = PyString_FromStringAndSize(tmp, len);
737 PyMem_DEL(tmp);
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000738 return(rtn);
739}
740
Guido van Rossumf6971e21994-08-30 12:25:20 +0000741static PyObject *
Barry Warsawaeb207c1996-12-23 23:36:24 +0000742rotorobj_decrypt_more(self, args)
743 Rotorobj *self;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000744 PyObject * args;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000745{
Barry Warsawaeb207c1996-12-23 23:36:24 +0000746 char *string = NULL;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000747 int len = 0;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000748 PyObject *rtn = NULL;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000749 char *tmp;
750
Barry Warsawaeb207c1996-12-23 23:36:24 +0000751 if (!PyArg_Parse(args, "s#", &string, &len))
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000752 return NULL;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000753 if (!(tmp = PyMem_NEW(char, len+5))) {
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000754 PyErr_NoMemory();
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000755 return NULL;
756 }
Barry Warsawaeb207c1996-12-23 23:36:24 +0000757 memset(tmp, '\0', len+1);
758 memcpy(tmp, string, len);
759 RTR_d_region(self, (unsigned char *)tmp, len, FALSE);
760 rtn = PyString_FromStringAndSize(tmp, len);
761 PyMem_DEL(tmp);
Guido van Rossum50098201992-07-31 15:10:13 +0000762 return(rtn);
763}
764
Guido van Rossumf6971e21994-08-30 12:25:20 +0000765static PyObject *
Barry Warsawaeb207c1996-12-23 23:36:24 +0000766rotorobj_setkey(self, args)
767 Rotorobj *self;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000768 PyObject * args;
Guido van Rossum50098201992-07-31 15:10:13 +0000769{
Barry Warsawaeb207c1996-12-23 23:36:24 +0000770 char *string = NULL;
Guido van Rossum50098201992-07-31 15:10:13 +0000771
Barry Warsawaeb207c1996-12-23 23:36:24 +0000772 if (!PyArg_ParseTuple(args, "|s", &string))
773 return NULL;
774
775 if (string)
776 set_key(self, string);
777
Guido van Rossumf6971e21994-08-30 12:25:20 +0000778 Py_INCREF(Py_None);
779 return Py_None;
Guido van Rossum50098201992-07-31 15:10:13 +0000780}
781
Barry Warsawaeb207c1996-12-23 23:36:24 +0000782static struct PyMethodDef
783rotorobj_methods[] = {
784 {"encrypt", (PyCFunction)rotorobj_encrypt},
785 {"encryptmore", (PyCFunction)rotorobj_encrypt_more},
786 {"decrypt", (PyCFunction)rotorobj_decrypt},
787 {"decryptmore", (PyCFunction)rotorobj_decrypt_more},
788 {"setkey", (PyCFunction)rotorobj_setkey, 1},
Guido van Rossum50098201992-07-31 15:10:13 +0000789 {NULL, NULL} /* sentinel */
790};
791
792
793/* Return a rotor object's named attribute. */
Guido van Rossumf6971e21994-08-30 12:25:20 +0000794static PyObject *
Barry Warsawaeb207c1996-12-23 23:36:24 +0000795rotorobj_getattr(s, name)
796 Rotorobj *s;
Guido van Rossum50098201992-07-31 15:10:13 +0000797 char *name;
798{
Barry Warsawaeb207c1996-12-23 23:36:24 +0000799 return Py_FindMethod(rotorobj_methods, (PyObject*)s, name);
Guido van Rossum50098201992-07-31 15:10:13 +0000800}
801
Barry Warsawaeb207c1996-12-23 23:36:24 +0000802
803statichere PyTypeObject Rotor_Type = {
Guido van Rossuma597dde1995-01-10 20:56:29 +0000804 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000805 0, /*ob_size*/
Guido van Rossum50098201992-07-31 15:10:13 +0000806 "rotor", /*tp_name*/
Barry Warsawaeb207c1996-12-23 23:36:24 +0000807 sizeof(Rotorobj), /*tp_size*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000808 0, /*tp_itemsize*/
Guido van Rossum50098201992-07-31 15:10:13 +0000809 /* methods */
Barry Warsawaeb207c1996-12-23 23:36:24 +0000810 (destructor)rotor_dealloc, /*tp_dealloc*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000811 0, /*tp_print*/
Barry Warsawaeb207c1996-12-23 23:36:24 +0000812 (getattrfunc)rotorobj_getattr, /*tp_getattr*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000813 0, /*tp_setattr*/
814 0, /*tp_compare*/
815 0, /*tp_repr*/
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000816 0, /*tp_hash*/
Guido van Rossum50098201992-07-31 15:10:13 +0000817};
818
819
Guido van Rossumf6971e21994-08-30 12:25:20 +0000820static PyObject *
Barry Warsawaeb207c1996-12-23 23:36:24 +0000821rotor_rotor(self, args)
Guido van Rossumf6971e21994-08-30 12:25:20 +0000822 PyObject * self;
823 PyObject * args;
Guido van Rossum50098201992-07-31 15:10:13 +0000824{
Barry Warsawaeb207c1996-12-23 23:36:24 +0000825 Rotorobj *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000826 char *string;
Guido van Rossum50098201992-07-31 15:10:13 +0000827 int len;
Barry Warsawaeb207c1996-12-23 23:36:24 +0000828 int num_rotors = 6;
Guido van Rossum50098201992-07-31 15:10:13 +0000829
Barry Warsawaeb207c1996-12-23 23:36:24 +0000830 if (!PyArg_ParseTuple(args, "s#|i", &string, &len, &num_rotors))
831 return NULL;
832
833 r = rotorobj_new(num_rotors, string);
834 return (PyObject *)r;
Guido van Rossum50098201992-07-31 15:10:13 +0000835}
836
Barry Warsawaeb207c1996-12-23 23:36:24 +0000837
838static struct PyMethodDef
839rotor_methods[] = {
840 {"newrotor", rotor_rotor, 1},
841 {NULL, NULL} /* sentinel */
Guido van Rossum50098201992-07-31 15:10:13 +0000842};
843
844
845/* Initialize this module.
846 This is called when the first 'import rotor' is done,
847 via a table in config.c, if config.c is compiled with USE_ROTOR
848 defined. */
849
850void
851initrotor()
852{
Barry Warsawaeb207c1996-12-23 23:36:24 +0000853 (void)Py_InitModule("rotor", rotor_methods);
Guido van Rossum50098201992-07-31 15:10:13 +0000854}