blob: a7529a3a0c6344f11a1ece3acd82a78dd69235b9 [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"
59
Guido van Rossum50098201992-07-31 15:10:13 +000060#include <stdio.h>
61#include <math.h>
Guido van Rossum7b2c03f1992-08-02 09:00:06 +000062#define TRUE 1
63#define FALSE 0
Guido van Rossum50098201992-07-31 15:10:13 +000064
65typedef struct {
Guido van Rossum7b1e9741994-08-29 10:46:42 +000066 PyObject_HEAD
Guido van Rossum50098201992-07-31 15:10:13 +000067 int seed[3];
68 short key[5];
Guido van Rossum7b2c03f1992-08-02 09:00:06 +000069 int isinited;
Guido van Rossum50098201992-07-31 15:10:13 +000070 int size;
71 int size_mask;
72 int rotors;
73 unsigned char *e_rotor; /* [num_rotors][size] */
74 unsigned char *d_rotor; /* [num_rotors][size] */
75 unsigned char *positions; /* [num_rotors] */
76 unsigned char *advances; /* [num_rotors] */
Guido van Rossum7b1e9741994-08-29 10:46:42 +000077} PyRotorObject;
Guido van Rossum50098201992-07-31 15:10:13 +000078
Guido van Rossum7b1e9741994-08-29 10:46:42 +000079staticforward PyTypeObject PyRotor_Type;
Guido van Rossum50098201992-07-31 15:10:13 +000080
Guido van Rossum7b1e9741994-08-29 10:46:42 +000081#define PyRotor_Check(v) ((v)->ob_type == &PyRotor_Type)
Guido van Rossum50098201992-07-31 15:10:13 +000082
83/*
84 This defines the necessary routines to manage rotor objects
85*/
86
87static void set_seed( r )
Guido van Rossum7b1e9741994-08-29 10:46:42 +000088PyRotorObject *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) */
97static float r_random( r )
Guido van Rossum7b1e9741994-08-29 10:46:42 +000098PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +000099{
100 int x, y, z;
101 float val, term;
102
103 x = r->seed[0];
104 y = r->seed[1];
105 z = r->seed[2];
106
107 x = 171 * (x % 177) - 2 * (x/177);
108 y = 172 * (y % 176) - 35 * (y/176);
109 z = 170 * (z % 178) - 63 * (z/178);
110
111 if (x < 0) x = x + 30269;
112 if (y < 0) y = y + 30307;
113 if (z < 0) z = z + 30323;
114
115 r->seed[0] = x;
116 r->seed[1] = y;
117 r->seed[2] = z;
118
119 term = (float)(
120 (((float)x)/(float)30269.0) +
121 (((float)y)/(float)30307.0) +
122 (((float)z)/(float)30323.0)
123 );
124 val = term - (float)floor((double)term);
125
126 if (val >= 1.0) val = 0.0;
127
128 return val;
129}
130
131static short r_rand(r,s)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000132PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000133short s;
134{
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000135 /*short tmp = (short)((int)(r_random(r) * (float)32768.0) % 32768);*/
Guido van Rossum50098201992-07-31 15:10:13 +0000136 short tmp = (short)((short)(r_random(r) * (float)s) % s);
137 return tmp;
138}
139
140static void set_key(r, key)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000141PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000142char *key;
143{
Guido van Rossume77a7571993-11-03 15:01:26 +0000144#ifdef BUGGY_CODE_BW_COMPAT
145 /* See comments below */
Guido van Rossum50098201992-07-31 15:10:13 +0000146 int k1=995, k2=576, k3=767, k4=671, k5=463;
Guido van Rossume77a7571993-11-03 15:01:26 +0000147#else
148 unsigned long k1=995, k2=576, k3=767, k4=671, k5=463;
149#endif
Guido van Rossum50098201992-07-31 15:10:13 +0000150 int i;
151 int len=strlen(key);
152 for (i=0;i<len;i++) {
Guido van Rossum06676261993-11-01 16:20:18 +0000153#ifdef BUGGY_CODE_BW_COMPAT
154 /* This is the code as it was originally released.
155 It causes warnings on many systems and can generate
156 different results as well. If you have files
157 encrypted using an older version you may want to
158 #define BUGGY_CODE_BW_COMPAT so as to be able to
159 decrypt them... */
Guido van Rossum50098201992-07-31 15:10:13 +0000160 k1 = (((k1<<3 | k1<<-13) + key[i]) & 65535);
161 k2 = (((k2<<3 | k2<<-13) ^ key[i]) & 65535);
162 k3 = (((k3<<3 | k3<<-13) - key[i]) & 65535);
163 k4 = ((key[i] - (k4<<3 | k4<<-13)) & 65535);
164 k5 = (((k5<<3 | k5<<-13) ^ ~key[i]) & 65535);
Guido van Rossum06676261993-11-01 16:20:18 +0000165#else
166 /* This code should be more portable */
167 k1 = (((k1<<3 | k1>>13) + key[i]) & 65535);
168 k2 = (((k2<<3 | k2>>13) ^ key[i]) & 65535);
169 k3 = (((k3<<3 | k3>>13) - key[i]) & 65535);
170 k4 = ((key[i] - (k4<<3 | k4>>13)) & 65535);
171 k5 = (((k5<<3 | k5>>13) ^ ~key[i]) & 65535);
172#endif
Guido van Rossum50098201992-07-31 15:10:13 +0000173 }
174 r->key[0] = (short)k1;
175 r->key[1] = (short)(k2|1);
176 r->key[2] = (short)k3;
177 r->key[3] = (short)k4;
178 r->key[4] = (short)k5;
179
180 set_seed(r);
181}
182
183/* These define the interface to a rotor object */
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000184static PyRotorObject *
185PyRotor_New(num_rotors, key)
Guido van Rossum50098201992-07-31 15:10:13 +0000186 int num_rotors;
187 char *key;
188{
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000189 PyRotorObject *xp;
190 xp = PyObject_NEW(PyRotorObject, &PyRotor_Type);
Guido van Rossum50098201992-07-31 15:10:13 +0000191 if (xp == NULL)
192 return NULL;
Guido van Rossume6e9fe181992-07-31 15:11:01 +0000193 set_key(xp, key);
Guido van Rossum50098201992-07-31 15:10:13 +0000194
195 xp->size = 256;
196 xp->size_mask = xp->size - 1;
197 xp->size_mask = 0;
198 xp->rotors = num_rotors;
Guido van Rossume6e9fe181992-07-31 15:11:01 +0000199 xp->e_rotor = NULL;
200 xp->d_rotor = NULL;
201 xp->positions = NULL;
202 xp->advances = NULL;
Guido van Rossum50098201992-07-31 15:10:13 +0000203
Guido van Rossume6e9fe181992-07-31 15:11:01 +0000204 xp->e_rotor =
205 (unsigned char *)malloc((num_rotors * (xp->size * sizeof(char))));
206 if (xp->e_rotor == (unsigned char *)NULL)
207 goto fail;
208 xp->d_rotor =
209 (unsigned char *)malloc((num_rotors * (xp->size * sizeof(char))));
210 if (xp->d_rotor == (unsigned char *)NULL)
211 goto fail;
Guido van Rossum50098201992-07-31 15:10:13 +0000212 xp->positions = (unsigned char *)malloc(num_rotors * sizeof(char));
Guido van Rossume6e9fe181992-07-31 15:11:01 +0000213 if (xp->positions == (unsigned char *)NULL)
214 goto fail;
Guido van Rossum50098201992-07-31 15:10:13 +0000215 xp->advances = (unsigned char *)malloc(num_rotors * sizeof(char));
Guido van Rossume6e9fe181992-07-31 15:11:01 +0000216 if (xp->advances == (unsigned char *)NULL)
217 goto fail;
Guido van Rossum50098201992-07-31 15:10:13 +0000218 return xp;
Guido van Rossume6e9fe181992-07-31 15:11:01 +0000219fail:
220 DECREF(xp);
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000221 return (PyRotorObject *)PyErr_NoMemory();
Guido van Rossum50098201992-07-31 15:10:13 +0000222}
223
224/* These routines impliment the rotor itself */
225
226/* Here is a fairly sofisticated {en,de}cryption system. It is bassed
227on the idea of a "rotor" machine. A bunch of rotors, each with a
228different permutation of the alphabet, rotate around a different
229amount after encrypting one character. The current state of the
230rotors is used to encrypt one character.
231
232 The code is smart enought to tell if your alphabet has a number of
233characters equal to a power of two. If it does, it uses logical
234operations, if not it uses div and mod (both require a division).
235
236 You will need to make two changes to the code 1) convert to c, and
237customize for an alphabet of 255 chars 2) add a filter at the
238begining, and end, which subtracts one on the way in, and adds one on
239the way out.
240
241 You might wish to do some timing studies. Another viable
242alternative is to "byte stuff" the encrypted data of a normal (perhaps
243this one) encryption routine.
244
245j'
246*/
247
248/*(defun RTR-make-id-rotor (rotor)
249 "Set ROTOR to the identity permutation"
250 (let ((j 0))
251 (while (< j RTR-size)
252 (aset rotor j j)
253 (setq j (+ 1 j)))
254 rotor))*/
255static void RTR_make_id_rotor(r, rtr)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000256 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000257 unsigned char *rtr;
258{
259 register int j;
260 register int size = r->size;
261 for (j=0;j<size;j++) {
262 rtr[j] = (unsigned char)j;
263 }
264}
265
266
267/*(defvar RTR-e-rotors
268 (let ((rv (make-vector RTR-number-of-rotors 0))
269 (i 0)
270 tr)
271 (while (< i RTR-number-of-rotors)
272 (setq tr (make-vector RTR-size 0))
273 (RTR-make-id-rotor tr)
274 (aset rv i tr)
275 (setq i (+ 1 i)))
276 rv)
277 "The current set of encryption rotors")*/
278static void RTR_e_rotors(r)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000279 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000280{
281 int i;
282 for (i=0;i<r->rotors;i++) {
283 RTR_make_id_rotor(r,&(r->e_rotor[(i*r->size)]));
284 }
285}
286
287/*(defvar RTR-d-rotors
288 (let ((rv (make-vector RTR-number-of-rotors 0))
289 (i 0)
290 tr)
291 (while (< i RTR-number-of-rotors)
292 (setq tr (make-vector RTR-size 0))
293 (setq j 0)
294 (while (< j RTR-size)
295 (aset tr j j)
296 (setq j (+ 1 j)))
297 (aset rv i tr)
298 (setq i (+ 1 i)))
299 rv)
300 "The current set of decryption rotors")*/
301static void RTR_d_rotors(r)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000302 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000303{
304 register int i, j;
305 for (i=0;i<r->rotors;i++) {
306 for (j=0;j<r->size;j++) {
307 r->d_rotor[((i*r->size)+j)] = (unsigned char)j;
308 }
309 }
310}
311
312/*(defvar RTR-positions (make-vector RTR-number-of-rotors 1)
313 "The positions of the rotors at this time")*/
314static void RTR_positions(r)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000315 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000316{
317 int i;
318 for (i=0;i<r->rotors;i++) {
319 r->positions[i] = 1;
320 }
321}
322
323/*(defvar RTR-advances (make-vector RTR-number-of-rotors 1)
324 "The number of positions to advance the rotors at a time")*/
325static void RTR_advances(r)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000326 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000327{
328 int i;
329 for (i=0;i<r->rotors;i++) {
330 r->advances[i] = 1;
331 }
332}
333
334/*(defun RTR-permute-rotor (e d)
335 "Permute the E rotor, and make the D rotor its inverse"
336 ;; see Knuth for explaination of algorythm.
337 (RTR-make-id-rotor e)
338 (let ((i RTR-size)
339 q j)
340 (while (<= 2 i)
341 (setq q (fair16 i)) ; a little tricky, decrement here
342 (setq i (- i 1)) ; since we have origin 0 array's
343 (setq j (aref e q))
344 (aset e q (aref e i))
345 (aset e i j)
346 (aset d j i))
347 (aset e 0 (aref e 0)) ; don't forget e[0] and d[0]
348 (aset d (aref e 0) 0)))*/
349static void RTR_permute_rotor(r, e, d)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000350 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000351 unsigned char *e;
352 unsigned char *d;
353{
354 short i = r->size;
355 short q;
356 unsigned char j;
357 RTR_make_id_rotor(r,e);
358 while (2 <= i) {
359 q = r_rand(r,i);
360 i--;
361 j = e[q];
362 e[q] = (unsigned char)e[i];
363 e[i] = (unsigned char)j;
364 d[j] = (unsigned char)i;
365 }
366 e[0] = (unsigned char)e[0];
367 d[(e[0])] = (unsigned char)0;
368}
369
370/*(defun RTR-init (key)
371 "Given KEY (a list of 5 16 bit numbers), initialize the rotor machine.
372Set the advancement, position, and permutation of the rotors"
373 (R16-set-state key)
374 (let (i)
375 (setq i 0)
376 (while (< i RTR-number-of-rotors)
377 (aset RTR-positions i (fair16 RTR-size))
378 (aset RTR-advances i (+ 1 (* 2 (fair16 (/ RTR-size 2)))))
379 (message "Initializing rotor %d..." i)
380 (RTR-permute-rotor (aref RTR-e-rotors i) (aref RTR-d-rotors i))
381 (setq i (+ 1 i)))))*/
382static void RTR_init(r)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000383 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000384{
385 int i;
386 set_seed(r);
387 RTR_positions(r);
388 RTR_advances(r);
389 RTR_e_rotors(r);
390 RTR_d_rotors(r);
391 for(i=0;i<r->rotors;i++) {
392 r->positions[i] = r_rand(r,r->size);
393 r->advances[i] = (1+(2*(r_rand(r,r->size/2))));
394 RTR_permute_rotor(r,&(r->e_rotor[(i*r->size)]),&(r->d_rotor[(i*r->size)]));
395 }
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000396 r->isinited = TRUE;
Guido van Rossum50098201992-07-31 15:10:13 +0000397}
398
399/*(defun RTR-advance ()
400 "Change the RTR-positions vector, using the RTR-advances vector"
401 (let ((i 0)
402 (temp 0))
403 (if RTR-size-mask
404 (while (< i RTR-number-of-rotors)
405 (setq temp (+ (aref RTR-positions i) (aref RTR-advances i)))
406 (aset RTR-positions i (logand temp RTR-size-mask))
407 (if (and (>= temp RTR-size)
408 (< i (- RTR-number-of-rotors 1)))
409 (aset RTR-positions (+ i 1)
410 (+ 1 (aref RTR-positions (+ i 1)))))
411 (setq i (+ i 1)))
412 (while (< i RTR-number-of-rotors)
413 (setq temp (+ (aref RTR-positions i) (aref RTR-advances i)))
414 (aset RTR-positions i (% temp RTR-size))
415 (if (and (>= temp RTR-size)
416 (< i (- RTR-number-of-rotors 1)))
417 (aset RTR-positions (+ i 1)
418 (+ 1 (aref RTR-positions (+ i 1)))))
419 (setq i (+ i 1))))))*/
420static void RTR_advance(r)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000421 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000422{
423 register int i=0, temp=0;
424 if (r->size_mask) {
425 while (i<r->rotors) {
426 temp = r->positions[i] + r->advances[i];
427 r->positions[i] = temp & r->size_mask;
428 if ((temp >= r->size) && (i < (r->rotors - 1))) {
429 r->positions[(i+1)] = 1 + r->positions[(i+1)];
430 }
431 i++;
432 }
433 } else {
434 while (i<r->rotors) {
435 temp = r->positions[i] + r->advances[i];
436 r->positions[i] = temp%r->size;
437 if ((temp >= r->size) && (i < (r->rotors - 1))) {
438 r->positions[(i+1)] = 1 + r->positions[(i+1)];
439 }
440 i++;
441 }
442 }
443}
444
445/*(defun RTR-e-char (p)
446 "Encrypt the character P with the current rotor machine"
447 (let ((i 0))
448 (if RTR-size-mask
449 (while (< i RTR-number-of-rotors)
450 (setq p (aref (aref RTR-e-rotors i)
451 (logand (logxor (aref RTR-positions i)
452 p)
453 RTR-size-mask)))
454 (setq i (+ 1 i)))
455 (while (< i RTR-number-of-rotors)
456 (setq p (aref (aref RTR-e-rotors i)
457 (% (logxor (aref RTR-positions i)
458 p)
459 RTR-size)))
460 (setq i (+ 1 i))))
461 (RTR-advance)
462 p))*/
463static unsigned char RTR_e_char(r, p)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000464 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000465 unsigned char p;
466{
467 register int i=0;
468 register unsigned char tp=p;
469 if (r->size_mask) {
470 while (i < r->rotors) {
471 tp = r->e_rotor[(i*r->size)+(((r->positions[i] ^ tp) & r->size_mask))];
472 i++;
473 }
474 } else {
475 while (i < r->rotors) {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000476 tp = r->e_rotor[(i*r->size)+(((r->positions[i] ^ tp) % (unsigned int) r->size))];
Guido van Rossum50098201992-07-31 15:10:13 +0000477 i++;
478 }
479 }
480 RTR_advance(r);
481 return ((unsigned char)tp);
482}
483
484/*(defun RTR-d-char (c)
485 "Decrypt the character C with the current rotor machine"
486 (let ((i (- RTR-number-of-rotors 1)))
487 (if RTR-size-mask
488 (while (<= 0 i)
489 (setq c (logand (logxor (aref RTR-positions i)
490 (aref (aref RTR-d-rotors i)
491 c))
492 RTR-size-mask))
493 (setq i (- i 1)))
494 (while (<= 0 i)
495 (setq c (% (logxor (aref RTR-positions i)
496 (aref (aref RTR-d-rotors i)
497 c))
498 RTR-size))
499 (setq i (- i 1))))
500 (RTR-advance)
501 c))*/
502static unsigned char RTR_d_char(r, c)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000503 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000504 unsigned char c;
505{
506 register int i=r->rotors - 1;
507 register unsigned char tc=c;
508 if (r->size_mask) {
509 while (0 <= i) {
510 tc = (r->positions[i] ^ r->d_rotor[(i*r->size)+tc]) & r->size_mask;
511 i--;
512 }
513 } else {
514 while (0 <= i) {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000515 tc = (r->positions[i] ^ r->d_rotor[(i*r->size)+tc]) % (unsigned int) r->size;
Guido van Rossum50098201992-07-31 15:10:13 +0000516 i--;
517 }
518 }
519 RTR_advance(r);
520 return(tc);
521}
522
523/*(defun RTR-e-region (beg end key)
524 "Perform a rotor encryption of the region from BEG to END by KEY"
525 (save-excursion
526 (let ((tenth (/ (- end beg) 10)))
527 (RTR-init key)
528 (goto-char beg)
529 ;; ### make it stop evry 10% or so to tell us
530 (while (< (point) end)
531 (let ((fc (following-char)))
532 (insert-char (RTR-e-char fc) 1)
533 (delete-char 1))))))*/
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000534static void RTR_e_region(r, beg, len, doinit)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000535 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000536 unsigned char *beg;
537 int len;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000538 int doinit;
Guido van Rossum50098201992-07-31 15:10:13 +0000539{
540 register int i;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000541 if (doinit || r->isinited == FALSE)
542 RTR_init(r);
Guido van Rossum50098201992-07-31 15:10:13 +0000543 for (i=0;i<len;i++) {
544 beg[i]=RTR_e_char(r,beg[i]);
545 }
546}
547
548/*(defun RTR-d-region (beg end key)
549 "Perform a rotor decryption of the region from BEG to END by KEY"
550 (save-excursion
551 (progn
552 (RTR-init key)
553 (goto-char beg)
554 (while (< (point) end)
555 (let ((fc (following-char)))
556 (insert-char (RTR-d-char fc) 1)
557 (delete-char 1))))))*/
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000558static void RTR_d_region(r, beg, len, doinit)
559 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000560 unsigned char *beg;
561 int len;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000562 int doinit;
Guido van Rossum50098201992-07-31 15:10:13 +0000563{
564 register int i;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000565 if (doinit || r->isinited == FALSE)
566 RTR_init(r);
Guido van Rossum50098201992-07-31 15:10:13 +0000567 for (i=0;i<len;i++) {
568 beg[i]=RTR_d_char(r,beg[i]);
569 }
570}
571
572
573/*(defun RTR-key-string-to-ints (key)
574 "Convert a string into a list of 4 numbers"
575 (let ((k1 995)
576 (k2 576)
577 (k3 767)
578 (k4 671)
579 (k5 463)
580 (i 0))
581 (while (< i (length key))
582 (setq k1 (logand (+ (logior (lsh k1 3) (lsh k1 -13)) (aref key i)) 65535))
583 (setq k2 (logand (logxor (logior (lsh k2 3) (lsh k2 -13)) (aref key i)) 65535))
584 (setq k3 (logand (- (logior (lsh k3 3) (lsh k3 -13)) (aref key i)) 65535))
585 (setq k4 (logand (- (aref key i) (logior (lsh k4 3) (lsh k4 -13))) 65535))
586 (setq k5 (logand (logxor (logior (lsh k5 3) (lsh k5 -13)) (lognot (aref key i))) 65535))
587 (setq i (+ i 1)))
588 (list k1 (logior 1 k2) k3 k4 k5)))*/
589/* This is done in set_key() above */
590
591/*(defun encrypt-region (beg end key)
592 "Interactivly encrypt the region"
593 (interactive "r\nsKey:")
594 (RTR-e-region beg end (RTR-key-string-to-ints key)))*/
595static void encrypt_region(r, region, len)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000596 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000597 unsigned char *region;
598 int len;
599{
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000600 RTR_e_region(r,region,len,TRUE);
Guido van Rossum50098201992-07-31 15:10:13 +0000601}
602
603/*(defun decrypt-region (beg end key)
604 "Interactivly decrypt the region"
605 (interactive "r\nsKey:")
606 (RTR-d-region beg end (RTR-key-string-to-ints key)))*/
607static void decrypt_region(r, region, len)
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000608 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000609 unsigned char *region;
610 int len;
611{
Guido van Rossum0b0db8e1993-01-21 16:07:51 +0000612 RTR_d_region(r,region,len,TRUE);
Guido van Rossum50098201992-07-31 15:10:13 +0000613}
614
615/* Rotor methods */
616
617static void
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000618PyRotor_Dealloc(xp)
619 PyRotorObject *xp;
Guido van Rossum50098201992-07-31 15:10:13 +0000620{
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000621 PyMem_XDEL(xp->e_rotor);
622 PyMem_XDEL(xp->d_rotor);
623 PyMem_XDEL(xp->positions);
624 PyMem_XDEL(xp->advances);
625 PyMem_DEL(xp);
Guido van Rossum50098201992-07-31 15:10:13 +0000626}
627
Guido van Rossumf6971e21994-08-30 12:25:20 +0000628static PyObject *
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000629PyRotor_Encrypt(self, args)
630 PyRotorObject *self;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000631 PyObject * args;
Guido van Rossum50098201992-07-31 15:10:13 +0000632{
633 char *string = (char *)NULL;
634 int len = 0;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000635 PyObject * rtn = (PyObject * )NULL;
Guido van Rossum50098201992-07-31 15:10:13 +0000636 char *tmp;
637
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000638 if (!PyArg_Parse(args,"s#",&string, &len))
Guido van Rossum50098201992-07-31 15:10:13 +0000639 return NULL;
640 if (!(tmp = (char *)malloc(len+5))) {
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000641 PyErr_NoMemory();
Guido van Rossum50098201992-07-31 15:10:13 +0000642 return NULL;
643 }
644 memset(tmp,'\0',len+1);
645 memcpy(tmp,string,len);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000646 RTR_e_region(self,(unsigned char *)tmp,len, TRUE);
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000647 rtn = PyString_FromStringAndSize(tmp,len);
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000648 free(tmp);
649 return(rtn);
650}
651
Guido van Rossumf6971e21994-08-30 12:25:20 +0000652static PyObject *
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000653PyRotor_EncryptMore(self, args)
654 PyRotorObject *self;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000655 PyObject * args;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000656{
657 char *string = (char *)NULL;
658 int len = 0;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000659 PyObject * rtn = (PyObject * )NULL;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000660 char *tmp;
661
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000662 if (!PyArg_Parse(args,"s#",&string, &len))
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000663 return NULL;
664 if (!(tmp = (char *)malloc(len+5))) {
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000665 PyErr_NoMemory();
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000666 return NULL;
667 }
668 memset(tmp,'\0',len+1);
669 memcpy(tmp,string,len);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000670 RTR_e_region(self,(unsigned char *)tmp,len, FALSE);
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000671 rtn = PyString_FromStringAndSize(tmp,len);
Guido van Rossum50098201992-07-31 15:10:13 +0000672 free(tmp);
673 return(rtn);
674}
675
Guido van Rossumf6971e21994-08-30 12:25:20 +0000676static PyObject *
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000677PyRotor_Decrypt(self, args)
678 PyRotorObject *self;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000679 PyObject * args;
Guido van Rossum50098201992-07-31 15:10:13 +0000680{
681 char *string = (char *)NULL;
682 int len = 0;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000683 PyObject * rtn = (PyObject * )NULL;
Guido van Rossum50098201992-07-31 15:10:13 +0000684 char *tmp;
685
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000686 if (!PyArg_Parse(args,"s#",&string, &len))
Guido van Rossum50098201992-07-31 15:10:13 +0000687 return NULL;
688 if (!(tmp = (char *)malloc(len+5))) {
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000689 PyErr_NoMemory();
Guido van Rossum50098201992-07-31 15:10:13 +0000690 return NULL;
691 }
692 memset(tmp,'\0',len+1);
693 memcpy(tmp,string,len);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000694 RTR_d_region(self,(unsigned char *)tmp,len, TRUE);
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000695 rtn = PyString_FromStringAndSize(tmp,len);
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000696 free(tmp);
697 return(rtn);
698}
699
Guido van Rossumf6971e21994-08-30 12:25:20 +0000700static PyObject *
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000701PyRotor_DecryptMore(self, args)
702 PyRotorObject *self;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000703 PyObject * args;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000704{
705 char *string = (char *)NULL;
706 int len = 0;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000707 PyObject * rtn = (PyObject * )NULL;
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000708 char *tmp;
709
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000710 if (!PyArg_Parse(args,"s#",&string, &len))
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000711 return NULL;
712 if (!(tmp = (char *)malloc(len+5))) {
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000713 PyErr_NoMemory();
Guido van Rossum7b2c03f1992-08-02 09:00:06 +0000714 return NULL;
715 }
716 memset(tmp,'\0',len+1);
717 memcpy(tmp,string,len);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000718 RTR_d_region(self,(unsigned char *)tmp,len, FALSE);
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000719 rtn = PyString_FromStringAndSize(tmp,len);
Guido van Rossum50098201992-07-31 15:10:13 +0000720 free(tmp);
721 return(rtn);
722}
723
Guido van Rossumf6971e21994-08-30 12:25:20 +0000724static PyObject *
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000725PyRotor_SetKey(self, args)
726 PyRotorObject *self;
Guido van Rossumf6971e21994-08-30 12:25:20 +0000727 PyObject * args;
Guido van Rossum50098201992-07-31 15:10:13 +0000728{
729 char *key;
730 char *string;
731
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000732 if (PyArg_Parse(args,"s",&string))
Guido van Rossum50098201992-07-31 15:10:13 +0000733 set_key(self,string);
Guido van Rossumf6971e21994-08-30 12:25:20 +0000734 Py_INCREF(Py_None);
735 return Py_None;
Guido van Rossum50098201992-07-31 15:10:13 +0000736}
737
Guido van Rossumf6971e21994-08-30 12:25:20 +0000738static struct methodlist PyRotor_Methods[] = {
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000739 {"encrypt", (PyCFunction)PyRotor_Encrypt},
740 {"encryptmore", (PyCFunction)PyRotor_EncryptMore},
741 {"decrypt", (PyCFunction)PyRotor_Decrypt},
742 {"decryptmore", (PyCFunction)PyRotor_DecryptMore},
743 {"setkey", (PyCFunction)PyRotor_SetKey},
Guido van Rossum50098201992-07-31 15:10:13 +0000744 {NULL, NULL} /* sentinel */
745};
746
747
748/* Return a rotor object's named attribute. */
Guido van Rossumf6971e21994-08-30 12:25:20 +0000749static PyObject *
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000750PyRotor_GetAttr(s, name)
751 PyRotorObject *s;
Guido van Rossum50098201992-07-31 15:10:13 +0000752 char *name;
753{
Guido van Rossumf6971e21994-08-30 12:25:20 +0000754 return Py_FindMethod(PyRotor_Methods, (PyObject * ) s, name);
Guido van Rossum50098201992-07-31 15:10:13 +0000755}
756
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000757static PyTypeObject PyRotor_Type = {
758 PyObject_HEAD_INIT(&Typetype)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000759 0, /*ob_size*/
Guido van Rossum50098201992-07-31 15:10:13 +0000760 "rotor", /*tp_name*/
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000761 sizeof(PyRotorObject), /*tp_size*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000762 0, /*tp_itemsize*/
Guido van Rossum50098201992-07-31 15:10:13 +0000763 /* methods */
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000764 (destructor)PyRotor_Dealloc, /*tp_dealloc*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000765 0, /*tp_print*/
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000766 (getattrfunc)PyRotor_GetAttr, /*tp_getattr*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000767 0, /*tp_setattr*/
768 0, /*tp_compare*/
769 0, /*tp_repr*/
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000770 0, /*tp_hash*/
Guido van Rossum50098201992-07-31 15:10:13 +0000771};
772
773
Guido van Rossumf6971e21994-08-30 12:25:20 +0000774static PyObject *
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000775PyRotor_Rotor(self, args)
Guido van Rossumf6971e21994-08-30 12:25:20 +0000776 PyObject * self;
777 PyObject * args;
Guido van Rossum50098201992-07-31 15:10:13 +0000778{
779 char *string;
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000780 PyRotorObject *r;
Guido van Rossum50098201992-07-31 15:10:13 +0000781 int len;
782 int num_rotors;
783
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000784 if (PyArg_Parse(args,"s#", &string, &len)) {
Guido van Rossum50098201992-07-31 15:10:13 +0000785 num_rotors = 6;
786 } else {
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000787 PyErr_Clear();
788 if (!PyArg_Parse(args,"(s#i)", &string, &len, &num_rotors))
Guido van Rossum50098201992-07-31 15:10:13 +0000789 return NULL;
790 }
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000791 r = PyRotor_New(num_rotors, string);
Guido van Rossumf6971e21994-08-30 12:25:20 +0000792 return (PyObject * )r;
Guido van Rossum50098201992-07-31 15:10:13 +0000793}
794
Guido van Rossumf6971e21994-08-30 12:25:20 +0000795static struct methodlist PyRotor_Rotor_Methods[] = {
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000796 {"newrotor", (PyCFunction)PyRotor_Rotor},
Guido van Rossum50098201992-07-31 15:10:13 +0000797 {NULL, NULL} /* Sentinel */
798};
799
800
801/* Initialize this module.
802 This is called when the first 'import rotor' is done,
803 via a table in config.c, if config.c is compiled with USE_ROTOR
804 defined. */
805
806void
807initrotor()
808{
Guido van Rossumf6971e21994-08-30 12:25:20 +0000809 PyObject * m;
Guido van Rossum50098201992-07-31 15:10:13 +0000810
Guido van Rossum7b1e9741994-08-29 10:46:42 +0000811 m = Py_InitModule("rotor", PyRotor_Rotor_Methods);
Guido van Rossum50098201992-07-31 15:10:13 +0000812}