mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			813 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			813 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/***********************************************************
 | 
						|
Copyright 1994 by Lance Ellinghouse,
 | 
						|
Cathedral City, California Republic, United States of America.
 | 
						|
 | 
						|
                        All Rights Reserved
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this software and its 
 | 
						|
documentation for any purpose and without fee is hereby granted, 
 | 
						|
provided that the above copyright notice appear in all copies and that
 | 
						|
both that copyright notice and this permission notice appear in 
 | 
						|
supporting documentation, and that the name of Lance Ellinghouse
 | 
						|
not be used in advertising or publicity pertaining to distribution 
 | 
						|
of the software without specific, written prior permission.
 | 
						|
 | 
						|
LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
 | 
						|
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
						|
FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE BE LIABLE FOR ANY SPECIAL, 
 | 
						|
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 
 | 
						|
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 
 | 
						|
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 
 | 
						|
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 | 
						|
******************************************************************/
 | 
						|
 | 
						|
/* This creates an encryption and decryption engine I am calling
 | 
						|
   a rotor due to the original design was a harware rotor with
 | 
						|
   contacts used in Germany during WWII.
 | 
						|
 | 
						|
Rotor Module:
 | 
						|
 | 
						|
-  rotor.newrotor('key') -> rotorobject  (default of 6 rotors)
 | 
						|
-  rotor.newrotor('key', num_rotors) -> rotorobject
 | 
						|
 | 
						|
Rotor Objects:
 | 
						|
 | 
						|
-  ro.setkey('string') -> None (resets the key as defined in newrotor().
 | 
						|
-  ro.encrypt('string') -> encrypted string
 | 
						|
-  ro.decrypt('encrypted string') -> unencrypted string
 | 
						|
 | 
						|
-  ro.encryptmore('string') -> encrypted string
 | 
						|
-  ro.decryptmore('encrypted string') -> unencrypted string
 | 
						|
 | 
						|
NOTE: the {en,de}cryptmore() methods use the setup that was
 | 
						|
      established via the {en,de}crypt calls. They will NOT
 | 
						|
      re-initalize the rotors unless: 1) They have not been
 | 
						|
      initalized with {en,de}crypt since the last setkey() call;
 | 
						|
      2) {en,de}crypt has not been called for this rotor yet.
 | 
						|
 | 
						|
NOTE: you MUST use the SAME key in rotor.newrotor()
 | 
						|
      if you wish to decrypt an encrypted string.
 | 
						|
      Also, the encrypted string is NOT 0-127 ASCII. 
 | 
						|
      It is considered BINARY data.
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
/* Rotor objects */
 | 
						|
 | 
						|
#include "Python.h"
 | 
						|
 | 
						|
#include "mymath.h"
 | 
						|
 | 
						|
#define TRUE	1
 | 
						|
#define FALSE	0
 | 
						|
 | 
						|
typedef struct {
 | 
						|
	PyObject_HEAD
 | 
						|
	int seed[3];
 | 
						|
    	short key[5];
 | 
						|
	int  isinited;
 | 
						|
	int  size;
 | 
						|
	int  size_mask;
 | 
						|
    	int  rotors;
 | 
						|
	unsigned char *e_rotor; /* [num_rotors][size] */
 | 
						|
	unsigned char *d_rotor; /* [num_rotors][size] */
 | 
						|
	unsigned char *positions; /* [num_rotors] */
 | 
						|
	unsigned char *advances; /* [num_rotors] */
 | 
						|
} PyRotorObject;
 | 
						|
 | 
						|
staticforward PyTypeObject PyRotor_Type;
 | 
						|
 | 
						|
#define PyRotor_Check(v)		((v)->ob_type == &PyRotor_Type)
 | 
						|
 | 
						|
/*
 | 
						|
	This defines the necessary routines to manage rotor objects
 | 
						|
*/
 | 
						|
 | 
						|
static void set_seed( r )
 | 
						|
PyRotorObject *r;
 | 
						|
{
 | 
						|
	r->seed[0] = r->key[0];
 | 
						|
	r->seed[1] = r->key[1];
 | 
						|
	r->seed[2] = r->key[2];
 | 
						|
	r->isinited = FALSE;
 | 
						|
}
 | 
						|
	
 | 
						|
/* Return the next random number in the range [0.0 .. 1.0) */
 | 
						|
static float r_random( r )
 | 
						|
PyRotorObject *r;
 | 
						|
{
 | 
						|
	int x, y, z;
 | 
						|
	float val, term;
 | 
						|
 | 
						|
	x = r->seed[0];
 | 
						|
	y = r->seed[1];
 | 
						|
	z = r->seed[2];
 | 
						|
 | 
						|
	x = 171 * (x % 177) - 2 * (x/177);
 | 
						|
	y = 172 * (y % 176) - 35 * (y/176);
 | 
						|
	z = 170 * (z % 178) - 63 * (z/178);
 | 
						|
	
 | 
						|
	if (x < 0) x = x + 30269;
 | 
						|
	if (y < 0) y = y + 30307;
 | 
						|
	if (z < 0) z = z + 30323;
 | 
						|
	
 | 
						|
	r->seed[0] = x;
 | 
						|
	r->seed[1] = y;
 | 
						|
	r->seed[2] = z;
 | 
						|
 | 
						|
	term = (float)(
 | 
						|
			(((float)x)/(float)30269.0) + 
 | 
						|
			(((float)y)/(float)30307.0) + 
 | 
						|
			(((float)z)/(float)30323.0)
 | 
						|
			);
 | 
						|
	val = term - (float)floor((double)term);
 | 
						|
 | 
						|
	if (val >= 1.0) val = 0.0;
 | 
						|
 | 
						|
	return val;
 | 
						|
}
 | 
						|
 | 
						|
static short r_rand(r,s)
 | 
						|
PyRotorObject *r;
 | 
						|
short s;
 | 
						|
{
 | 
						|
	/*short tmp = (short)((int)(r_random(r) * (float)32768.0) % 32768);*/
 | 
						|
	short tmp = (short)((short)(r_random(r) * (float)s) % s);
 | 
						|
	return tmp;
 | 
						|
}
 | 
						|
 | 
						|
static void set_key(r, key)
 | 
						|
PyRotorObject *r;
 | 
						|
char *key;
 | 
						|
{
 | 
						|
#ifdef BUGGY_CODE_BW_COMPAT
 | 
						|
	/* See comments below */
 | 
						|
	int k1=995, k2=576, k3=767, k4=671, k5=463;
 | 
						|
#else
 | 
						|
	unsigned long k1=995, k2=576, k3=767, k4=671, k5=463;
 | 
						|
#endif
 | 
						|
	int i;
 | 
						|
	int len=strlen(key);
 | 
						|
	for (i=0;i<len;i++) {
 | 
						|
#ifdef BUGGY_CODE_BW_COMPAT
 | 
						|
		/* This is the code as it was originally released.
 | 
						|
		   It causes warnings on many systems and can generate
 | 
						|
		   different results as well.  If you have files
 | 
						|
		   encrypted using an older version you may want to
 | 
						|
		   #define BUGGY_CODE_BW_COMPAT so as to be able to
 | 
						|
		   decrypt them... */
 | 
						|
		k1 = (((k1<<3 | k1<<-13) + key[i]) & 65535);
 | 
						|
		k2 = (((k2<<3 | k2<<-13) ^ key[i]) & 65535);
 | 
						|
		k3 = (((k3<<3 | k3<<-13) - key[i]) & 65535);
 | 
						|
		k4 = ((key[i] - (k4<<3 | k4<<-13)) & 65535);
 | 
						|
		k5 = (((k5<<3 | k5<<-13) ^ ~key[i]) & 65535);
 | 
						|
#else
 | 
						|
		/* This code should be more portable */
 | 
						|
		k1 = (((k1<<3 | k1>>13) + key[i]) & 65535);
 | 
						|
		k2 = (((k2<<3 | k2>>13) ^ key[i]) & 65535);
 | 
						|
		k3 = (((k3<<3 | k3>>13) - key[i]) & 65535);
 | 
						|
		k4 = ((key[i] - (k4<<3 | k4>>13)) & 65535);
 | 
						|
		k5 = (((k5<<3 | k5>>13) ^ ~key[i]) & 65535);
 | 
						|
#endif
 | 
						|
	}
 | 
						|
	r->key[0] = (short)k1;
 | 
						|
	r->key[1] = (short)(k2|1);
 | 
						|
	r->key[2] = (short)k3;
 | 
						|
	r->key[3] = (short)k4;
 | 
						|
	r->key[4] = (short)k5;
 | 
						|
 | 
						|
	set_seed(r);
 | 
						|
}
 | 
						|
 | 
						|
/* These define the interface to a rotor object */
 | 
						|
static PyRotorObject *
 | 
						|
PyRotor_New(num_rotors, key)
 | 
						|
	int num_rotors;
 | 
						|
	char *key;
 | 
						|
{
 | 
						|
	PyRotorObject *xp;
 | 
						|
	xp = PyObject_NEW(PyRotorObject, &PyRotor_Type);
 | 
						|
	if (xp == NULL)
 | 
						|
		return NULL;
 | 
						|
	set_key(xp, key);
 | 
						|
 | 
						|
	xp->size = 256;
 | 
						|
	xp->size_mask = xp->size - 1;
 | 
						|
	xp->size_mask = 0;
 | 
						|
	xp->rotors = num_rotors;
 | 
						|
	xp->e_rotor = NULL;
 | 
						|
	xp->d_rotor = NULL;
 | 
						|
	xp->positions = NULL;
 | 
						|
	xp->advances = NULL;
 | 
						|
 | 
						|
	xp->e_rotor =
 | 
						|
	     (unsigned char *)malloc((num_rotors * (xp->size * sizeof(char))));
 | 
						|
	if (xp->e_rotor == (unsigned char *)NULL)
 | 
						|
		goto fail;
 | 
						|
	xp->d_rotor =
 | 
						|
	     (unsigned char *)malloc((num_rotors * (xp->size * sizeof(char))));
 | 
						|
	if (xp->d_rotor == (unsigned char *)NULL)
 | 
						|
		goto fail;
 | 
						|
	xp->positions = (unsigned char *)malloc(num_rotors * sizeof(char));
 | 
						|
	if (xp->positions == (unsigned char *)NULL)
 | 
						|
		goto fail;
 | 
						|
	xp->advances  = (unsigned char *)malloc(num_rotors * sizeof(char));
 | 
						|
	if (xp->advances == (unsigned char *)NULL)
 | 
						|
		goto fail;
 | 
						|
	return xp;
 | 
						|
fail:
 | 
						|
	Py_DECREF(xp);
 | 
						|
	return (PyRotorObject *)PyErr_NoMemory();
 | 
						|
}
 | 
						|
 | 
						|
/* These routines impliment the rotor itself */
 | 
						|
 | 
						|
/*  Here is a fairly sofisticated {en,de}cryption system.  It is bassed
 | 
						|
on the idea of a "rotor" machine.  A bunch of rotors, each with a
 | 
						|
different permutation of the alphabet, rotate around a different
 | 
						|
amount after encrypting one character.  The current state of the
 | 
						|
rotors is used to encrypt one character.
 | 
						|
 | 
						|
  The code is smart enought to tell if your alphabet has a number of
 | 
						|
characters equal to a power of two.  If it does, it uses logical
 | 
						|
operations, if not it uses div and mod (both require a division).
 | 
						|
 | 
						|
  You will need to make two changes to the code 1) convert to c, and
 | 
						|
customize for an alphabet of 255 chars 2) add a filter at the
 | 
						|
begining, and end, which subtracts one on the way in, and adds one on
 | 
						|
the way out.
 | 
						|
 | 
						|
  You might wish to do some timing studies.  Another viable
 | 
						|
alternative is to "byte stuff" the encrypted data of a normal (perhaps
 | 
						|
this one) encryption routine.
 | 
						|
 | 
						|
j'
 | 
						|
*/
 | 
						|
 | 
						|
/*(defun RTR-make-id-rotor (rotor)
 | 
						|
  "Set ROTOR to the identity permutation"
 | 
						|
  (let ((j 0))
 | 
						|
    (while (< j RTR-size)
 | 
						|
      (aset rotor j j)
 | 
						|
      (setq j (+ 1 j)))
 | 
						|
    rotor))*/
 | 
						|
static void RTR_make_id_rotor(r, rtr)
 | 
						|
	PyRotorObject *r;
 | 
						|
	unsigned char *rtr;
 | 
						|
{
 | 
						|
	register int j;
 | 
						|
	register int size = r->size;
 | 
						|
	for (j=0;j<size;j++) {
 | 
						|
		rtr[j] = (unsigned char)j;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*(defvar RTR-e-rotors 
 | 
						|
  (let ((rv (make-vector RTR-number-of-rotors 0))
 | 
						|
	(i 0)
 | 
						|
	tr)
 | 
						|
    (while (< i RTR-number-of-rotors)
 | 
						|
      (setq tr (make-vector RTR-size 0))
 | 
						|
      (RTR-make-id-rotor tr)
 | 
						|
      (aset rv i tr)
 | 
						|
      (setq i (+ 1 i)))
 | 
						|
    rv)
 | 
						|
  "The current set of encryption rotors")*/
 | 
						|
static void RTR_e_rotors(r)
 | 
						|
	PyRotorObject *r;
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	for (i=0;i<r->rotors;i++) {
 | 
						|
		RTR_make_id_rotor(r,&(r->e_rotor[(i*r->size)]));
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*(defvar RTR-d-rotors 
 | 
						|
  (let ((rv (make-vector RTR-number-of-rotors 0))
 | 
						|
	(i 0)
 | 
						|
	tr)
 | 
						|
    (while (< i RTR-number-of-rotors)
 | 
						|
      (setq tr (make-vector RTR-size 0))
 | 
						|
      (setq j 0)
 | 
						|
      (while (< j RTR-size)
 | 
						|
	(aset tr j j)
 | 
						|
	(setq j (+ 1 j)))
 | 
						|
      (aset rv i tr)
 | 
						|
      (setq i (+ 1 i)))
 | 
						|
    rv)
 | 
						|
  "The current set of decryption rotors")*/
 | 
						|
static void RTR_d_rotors(r)
 | 
						|
	PyRotorObject *r;
 | 
						|
{
 | 
						|
	register int i, j;
 | 
						|
	for (i=0;i<r->rotors;i++) {
 | 
						|
		for (j=0;j<r->size;j++) {
 | 
						|
			r->d_rotor[((i*r->size)+j)] = (unsigned char)j;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*(defvar RTR-positions (make-vector RTR-number-of-rotors 1)
 | 
						|
  "The positions of the rotors at this time")*/
 | 
						|
static void RTR_positions(r)
 | 
						|
	PyRotorObject *r;
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	for (i=0;i<r->rotors;i++) {
 | 
						|
		r->positions[i] = 1;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*(defvar RTR-advances (make-vector RTR-number-of-rotors 1)
 | 
						|
  "The number of positions to advance the rotors at a time")*/
 | 
						|
static void RTR_advances(r) 
 | 
						|
	PyRotorObject *r;
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	for (i=0;i<r->rotors;i++) {
 | 
						|
		r->advances[i] = 1;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*(defun RTR-permute-rotor (e d)
 | 
						|
  "Permute the E rotor, and make the D rotor its inverse"
 | 
						|
  ;; see Knuth for explaination of algorythm.
 | 
						|
  (RTR-make-id-rotor e)
 | 
						|
  (let ((i RTR-size)
 | 
						|
	q j)
 | 
						|
    (while (<= 2 i)
 | 
						|
      (setq q (fair16 i))		; a little tricky, decrement here
 | 
						|
      (setq i (- i 1))			; since we have origin 0 array's
 | 
						|
      (setq j (aref e q))
 | 
						|
      (aset e q (aref e i))
 | 
						|
      (aset e i j)
 | 
						|
      (aset d j i))
 | 
						|
    (aset e 0 (aref e 0))		; don't forget e[0] and d[0]
 | 
						|
    (aset d (aref e 0) 0)))*/
 | 
						|
static void RTR_permute_rotor(r, e, d)
 | 
						|
	PyRotorObject *r;
 | 
						|
	unsigned char *e;
 | 
						|
	unsigned char *d;
 | 
						|
{
 | 
						|
	short i = r->size;
 | 
						|
	short q;
 | 
						|
	unsigned char j;
 | 
						|
	RTR_make_id_rotor(r,e);
 | 
						|
	while (2 <= i) {
 | 
						|
		q = r_rand(r,i);
 | 
						|
		i--;
 | 
						|
		j = e[q];
 | 
						|
		e[q] = (unsigned char)e[i];
 | 
						|
		e[i] = (unsigned char)j;
 | 
						|
		d[j] = (unsigned char)i;
 | 
						|
	}
 | 
						|
	e[0] = (unsigned char)e[0];
 | 
						|
	d[(e[0])] = (unsigned char)0;
 | 
						|
}
 | 
						|
 | 
						|
/*(defun RTR-init (key)
 | 
						|
  "Given KEY (a list of 5 16 bit numbers), initialize the rotor machine.
 | 
						|
Set the advancement, position, and permutation of the rotors"
 | 
						|
  (R16-set-state key)
 | 
						|
  (let (i)
 | 
						|
    (setq i 0)
 | 
						|
    (while (< i RTR-number-of-rotors)
 | 
						|
      (aset RTR-positions i (fair16 RTR-size))
 | 
						|
      (aset RTR-advances i (+ 1 (* 2 (fair16 (/ RTR-size 2)))))
 | 
						|
      (message "Initializing rotor %d..." i)
 | 
						|
      (RTR-permute-rotor (aref RTR-e-rotors i) (aref RTR-d-rotors i))
 | 
						|
      (setq i (+ 1 i)))))*/
 | 
						|
static void RTR_init(r)
 | 
						|
	PyRotorObject *r;
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	set_seed(r);
 | 
						|
	RTR_positions(r);
 | 
						|
	RTR_advances(r);
 | 
						|
	RTR_e_rotors(r);
 | 
						|
	RTR_d_rotors(r);
 | 
						|
	for(i=0;i<r->rotors;i++) {
 | 
						|
		r->positions[i] = r_rand(r,r->size);
 | 
						|
		r->advances[i] = (1+(2*(r_rand(r,r->size/2))));
 | 
						|
		RTR_permute_rotor(r,&(r->e_rotor[(i*r->size)]),&(r->d_rotor[(i*r->size)]));
 | 
						|
	}
 | 
						|
	r->isinited = TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/*(defun RTR-advance ()
 | 
						|
  "Change the RTR-positions vector, using the RTR-advances vector"
 | 
						|
  (let ((i 0)
 | 
						|
	(temp 0))
 | 
						|
    (if RTR-size-mask
 | 
						|
	(while (< i RTR-number-of-rotors)
 | 
						|
	  (setq temp (+ (aref RTR-positions i) (aref RTR-advances i)))
 | 
						|
	  (aset RTR-positions i (logand temp RTR-size-mask))
 | 
						|
	  (if (and (>= temp RTR-size)
 | 
						|
		   (< i (- RTR-number-of-rotors 1))) 
 | 
						|
	      (aset RTR-positions (+ i 1)
 | 
						|
		    (+ 1 (aref RTR-positions (+ i 1)))))
 | 
						|
	  (setq i (+ i 1)))
 | 
						|
      (while (< i RTR-number-of-rotors)
 | 
						|
	(setq temp (+ (aref RTR-positions i) (aref RTR-advances i)))
 | 
						|
	(aset RTR-positions i (% temp RTR-size))
 | 
						|
	(if (and (>= temp RTR-size)
 | 
						|
		 (< i (- RTR-number-of-rotors 1))) 
 | 
						|
	    (aset RTR-positions (+ i 1)
 | 
						|
		  (+ 1 (aref RTR-positions (+ i 1)))))
 | 
						|
	(setq i (+ i 1))))))*/
 | 
						|
static void RTR_advance(r)
 | 
						|
	PyRotorObject *r;
 | 
						|
{
 | 
						|
	register int i=0, temp=0;
 | 
						|
	if (r->size_mask) {
 | 
						|
		while (i<r->rotors) {
 | 
						|
			temp = r->positions[i] + r->advances[i];
 | 
						|
			r->positions[i] = temp & r->size_mask;
 | 
						|
			if ((temp >= r->size) && (i < (r->rotors - 1))) {
 | 
						|
				r->positions[(i+1)] = 1 + r->positions[(i+1)];
 | 
						|
			}
 | 
						|
			i++;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		while (i<r->rotors) {
 | 
						|
			temp = r->positions[i] + r->advances[i];
 | 
						|
			r->positions[i] = temp%r->size;
 | 
						|
			if ((temp >= r->size) && (i < (r->rotors - 1))) {
 | 
						|
				r->positions[(i+1)] = 1 + r->positions[(i+1)];
 | 
						|
			}
 | 
						|
			i++;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*(defun RTR-e-char (p)
 | 
						|
  "Encrypt the character P with the current rotor machine"
 | 
						|
  (let ((i 0))
 | 
						|
    (if RTR-size-mask
 | 
						|
	(while (< i RTR-number-of-rotors)
 | 
						|
	  (setq p (aref (aref RTR-e-rotors i)
 | 
						|
			(logand (logxor (aref RTR-positions i)
 | 
						|
					p)
 | 
						|
				RTR-size-mask)))
 | 
						|
	  (setq i (+ 1 i)))
 | 
						|
      (while (< i RTR-number-of-rotors)
 | 
						|
	  (setq p (aref (aref RTR-e-rotors i)
 | 
						|
			(% (logxor (aref RTR-positions i)
 | 
						|
				   p)
 | 
						|
			   RTR-size)))
 | 
						|
	(setq i (+ 1 i))))
 | 
						|
    (RTR-advance)
 | 
						|
    p))*/
 | 
						|
static unsigned char RTR_e_char(r, p)
 | 
						|
	PyRotorObject *r;
 | 
						|
	unsigned char p;
 | 
						|
{
 | 
						|
	register int i=0;
 | 
						|
	register unsigned char tp=p;
 | 
						|
	if (r->size_mask) {
 | 
						|
		while (i < r->rotors) {
 | 
						|
			tp = r->e_rotor[(i*r->size)+(((r->positions[i] ^ tp) & r->size_mask))];
 | 
						|
			i++;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		while (i < r->rotors) {
 | 
						|
			tp = r->e_rotor[(i*r->size)+(((r->positions[i] ^ tp) % (unsigned int) r->size))];
 | 
						|
			i++;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	RTR_advance(r);
 | 
						|
	return ((unsigned char)tp);
 | 
						|
}
 | 
						|
 | 
						|
/*(defun RTR-d-char (c)
 | 
						|
  "Decrypt the character C with the current rotor machine"
 | 
						|
  (let ((i (- RTR-number-of-rotors 1)))
 | 
						|
    (if RTR-size-mask
 | 
						|
	(while (<= 0 i)
 | 
						|
	  (setq c (logand (logxor (aref RTR-positions i)
 | 
						|
				  (aref (aref RTR-d-rotors i)
 | 
						|
					c))
 | 
						|
			  RTR-size-mask))
 | 
						|
	  (setq i (- i 1)))
 | 
						|
	(while (<= 0 i)
 | 
						|
	  (setq c (% (logxor (aref RTR-positions i)
 | 
						|
			     (aref (aref RTR-d-rotors i)
 | 
						|
				   c))
 | 
						|
		     RTR-size))
 | 
						|
	  (setq i (- i 1))))
 | 
						|
    (RTR-advance)
 | 
						|
    c))*/
 | 
						|
static unsigned char RTR_d_char(r, c)
 | 
						|
	PyRotorObject *r;
 | 
						|
	unsigned char c;
 | 
						|
{
 | 
						|
	register int i=r->rotors - 1;
 | 
						|
	register unsigned char tc=c;
 | 
						|
	if (r->size_mask) {
 | 
						|
		while (0 <= i) {
 | 
						|
			tc = (r->positions[i] ^ r->d_rotor[(i*r->size)+tc]) & r->size_mask;
 | 
						|
			i--;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		while (0 <= i) {
 | 
						|
			tc = (r->positions[i] ^ r->d_rotor[(i*r->size)+tc]) % (unsigned int) r->size;
 | 
						|
			i--;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	RTR_advance(r);
 | 
						|
	return(tc);
 | 
						|
}
 | 
						|
 | 
						|
/*(defun RTR-e-region (beg end key)
 | 
						|
  "Perform a rotor encryption of the region from BEG to END by KEY"
 | 
						|
  (save-excursion
 | 
						|
    (let ((tenth (/ (- end beg) 10)))
 | 
						|
      (RTR-init key)
 | 
						|
      (goto-char beg)
 | 
						|
      ;; ### make it stop evry 10% or so to tell us
 | 
						|
      (while (< (point) end)
 | 
						|
	(let ((fc (following-char)))
 | 
						|
	  (insert-char (RTR-e-char fc) 1)
 | 
						|
	  (delete-char 1))))))*/
 | 
						|
static void RTR_e_region(r, beg, len, doinit)
 | 
						|
	PyRotorObject *r;
 | 
						|
	unsigned char *beg;
 | 
						|
	int len;
 | 
						|
	int doinit;
 | 
						|
{
 | 
						|
	register int i;
 | 
						|
	if (doinit || r->isinited == FALSE)
 | 
						|
		RTR_init(r);
 | 
						|
	for (i=0;i<len;i++) {
 | 
						|
		beg[i]=RTR_e_char(r,beg[i]);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*(defun RTR-d-region (beg end key)
 | 
						|
  "Perform a rotor decryption of the region from BEG to END by KEY"
 | 
						|
  (save-excursion
 | 
						|
    (progn
 | 
						|
      (RTR-init key)
 | 
						|
      (goto-char beg)
 | 
						|
      (while (< (point) end)
 | 
						|
	(let ((fc (following-char)))
 | 
						|
	  (insert-char (RTR-d-char fc) 1)
 | 
						|
	  (delete-char 1))))))*/
 | 
						|
static void RTR_d_region(r, beg, len, doinit)
 | 
						|
	PyRotorObject *r;
 | 
						|
	unsigned char *beg;
 | 
						|
	int len;
 | 
						|
	int doinit;
 | 
						|
{
 | 
						|
	register int i;
 | 
						|
	if (doinit || r->isinited == FALSE)
 | 
						|
		RTR_init(r);
 | 
						|
	for (i=0;i<len;i++) {
 | 
						|
		beg[i]=RTR_d_char(r,beg[i]);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*(defun RTR-key-string-to-ints (key)
 | 
						|
  "Convert a string into a list of 4 numbers"
 | 
						|
  (let ((k1 995)
 | 
						|
	(k2 576)
 | 
						|
	(k3 767)
 | 
						|
	(k4 671)
 | 
						|
	(k5 463)
 | 
						|
	(i 0))
 | 
						|
    (while (< i (length key))
 | 
						|
      (setq k1 (logand (+      (logior (lsh k1 3) (lsh k1 -13)) (aref key i)) 65535))
 | 
						|
      (setq k2 (logand (logxor (logior (lsh k2 3) (lsh k2 -13)) (aref key i)) 65535))
 | 
						|
      (setq k3 (logand (-      (logior (lsh k3 3) (lsh k3 -13)) (aref key i)) 65535))
 | 
						|
      (setq k4 (logand (-      (aref key i) (logior (lsh k4 3) (lsh k4 -13))) 65535))
 | 
						|
      (setq k5 (logand (logxor (logior (lsh k5 3) (lsh k5 -13)) (lognot (aref key i))) 65535))
 | 
						|
      (setq i (+ i 1)))
 | 
						|
    (list k1 (logior 1 k2) k3 k4 k5)))*/
 | 
						|
/* This is done in set_key() above */
 | 
						|
 | 
						|
#if 0
 | 
						|
/*(defun encrypt-region (beg end key)
 | 
						|
  "Interactivly encrypt the region"
 | 
						|
  (interactive "r\nsKey:")
 | 
						|
  (RTR-e-region beg end (RTR-key-string-to-ints key)))*/
 | 
						|
static void encrypt_region(r, region, len)
 | 
						|
	PyRotorObject *r;
 | 
						|
	unsigned char *region;
 | 
						|
	int len;
 | 
						|
{
 | 
						|
	RTR_e_region(r,region,len,TRUE);
 | 
						|
}
 | 
						|
 | 
						|
/*(defun decrypt-region (beg end key)
 | 
						|
  "Interactivly decrypt the region"
 | 
						|
  (interactive "r\nsKey:")
 | 
						|
  (RTR-d-region beg end (RTR-key-string-to-ints key)))*/
 | 
						|
static void decrypt_region(r, region, len)
 | 
						|
	PyRotorObject *r;
 | 
						|
	unsigned char *region;
 | 
						|
	int len;
 | 
						|
{
 | 
						|
	RTR_d_region(r,region,len,TRUE);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* Rotor methods */
 | 
						|
 | 
						|
static void
 | 
						|
PyRotor_Dealloc(xp)
 | 
						|
	PyRotorObject *xp;
 | 
						|
{
 | 
						|
	PyMem_XDEL(xp->e_rotor);
 | 
						|
	PyMem_XDEL(xp->d_rotor);
 | 
						|
	PyMem_XDEL(xp->positions);
 | 
						|
	PyMem_XDEL(xp->advances);
 | 
						|
	PyMem_DEL(xp);
 | 
						|
}
 | 
						|
 | 
						|
static PyObject * 
 | 
						|
PyRotor_Encrypt(self, args)
 | 
						|
	PyRotorObject *self;
 | 
						|
	PyObject * args;
 | 
						|
{
 | 
						|
	char *string = (char *)NULL;
 | 
						|
	int len = 0;
 | 
						|
	PyObject * rtn = (PyObject * )NULL;
 | 
						|
	char *tmp;
 | 
						|
 | 
						|
	if (!PyArg_Parse(args,"s#",&string, &len))
 | 
						|
		return NULL;
 | 
						|
	if (!(tmp = (char *)malloc(len+5))) {
 | 
						|
		PyErr_NoMemory();
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
	memset(tmp,'\0',len+1);
 | 
						|
	memcpy(tmp,string,len);
 | 
						|
	RTR_e_region(self,(unsigned char *)tmp,len, TRUE);
 | 
						|
	rtn = PyString_FromStringAndSize(tmp,len);
 | 
						|
	free(tmp);
 | 
						|
	return(rtn);
 | 
						|
}
 | 
						|
 | 
						|
static PyObject * 
 | 
						|
PyRotor_EncryptMore(self, args)
 | 
						|
	PyRotorObject *self;
 | 
						|
	PyObject * args;
 | 
						|
{
 | 
						|
	char *string = (char *)NULL;
 | 
						|
	int len = 0;
 | 
						|
	PyObject * rtn = (PyObject * )NULL;
 | 
						|
	char *tmp;
 | 
						|
 | 
						|
	if (!PyArg_Parse(args,"s#",&string, &len))
 | 
						|
		return NULL;
 | 
						|
	if (!(tmp = (char *)malloc(len+5))) {
 | 
						|
		PyErr_NoMemory();
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
	memset(tmp,'\0',len+1);
 | 
						|
	memcpy(tmp,string,len);
 | 
						|
	RTR_e_region(self,(unsigned char *)tmp,len, FALSE);
 | 
						|
	rtn = PyString_FromStringAndSize(tmp,len);
 | 
						|
	free(tmp);
 | 
						|
	return(rtn);
 | 
						|
}
 | 
						|
 | 
						|
static PyObject * 
 | 
						|
PyRotor_Decrypt(self, args)
 | 
						|
	PyRotorObject *self;
 | 
						|
	PyObject * args;
 | 
						|
{
 | 
						|
	char *string = (char *)NULL;
 | 
						|
	int len = 0;
 | 
						|
	PyObject * rtn = (PyObject * )NULL;
 | 
						|
	char *tmp;
 | 
						|
 | 
						|
	if (!PyArg_Parse(args,"s#",&string, &len))
 | 
						|
		return NULL;
 | 
						|
	if (!(tmp = (char *)malloc(len+5))) {
 | 
						|
		PyErr_NoMemory();
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
	memset(tmp,'\0',len+1);
 | 
						|
	memcpy(tmp,string,len);
 | 
						|
	RTR_d_region(self,(unsigned char *)tmp,len, TRUE);
 | 
						|
	rtn = PyString_FromStringAndSize(tmp,len);
 | 
						|
	free(tmp);
 | 
						|
	return(rtn);
 | 
						|
}
 | 
						|
 | 
						|
static PyObject * 
 | 
						|
PyRotor_DecryptMore(self, args)
 | 
						|
	PyRotorObject *self;
 | 
						|
	PyObject * args;
 | 
						|
{
 | 
						|
	char *string = (char *)NULL;
 | 
						|
	int len = 0;
 | 
						|
	PyObject * rtn = (PyObject * )NULL;
 | 
						|
	char *tmp;
 | 
						|
 | 
						|
	if (!PyArg_Parse(args,"s#",&string, &len))
 | 
						|
		return NULL;
 | 
						|
	if (!(tmp = (char *)malloc(len+5))) {
 | 
						|
		PyErr_NoMemory();
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
	memset(tmp,'\0',len+1);
 | 
						|
	memcpy(tmp,string,len);
 | 
						|
	RTR_d_region(self,(unsigned char *)tmp,len, FALSE);
 | 
						|
	rtn = PyString_FromStringAndSize(tmp,len);
 | 
						|
	free(tmp);
 | 
						|
	return(rtn);
 | 
						|
}
 | 
						|
 | 
						|
static PyObject * 
 | 
						|
PyRotor_SetKey(self, args)
 | 
						|
	PyRotorObject *self;
 | 
						|
	PyObject * args;
 | 
						|
{
 | 
						|
	char *string;
 | 
						|
 | 
						|
	if (PyArg_Parse(args,"s",&string))
 | 
						|
		set_key(self,string);
 | 
						|
	Py_INCREF(Py_None);
 | 
						|
	return Py_None;
 | 
						|
}
 | 
						|
 | 
						|
static struct PyMethodDef PyRotor_Methods[] = {
 | 
						|
	{"encrypt",	(PyCFunction)PyRotor_Encrypt},
 | 
						|
	{"encryptmore",	(PyCFunction)PyRotor_EncryptMore},
 | 
						|
	{"decrypt",	(PyCFunction)PyRotor_Decrypt},
 | 
						|
	{"decryptmore",	(PyCFunction)PyRotor_DecryptMore},
 | 
						|
	{"setkey",	(PyCFunction)PyRotor_SetKey},
 | 
						|
	{NULL,		NULL}		/* sentinel */
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/* Return a rotor object's named attribute. */
 | 
						|
static PyObject * 
 | 
						|
PyRotor_GetAttr(s, name)
 | 
						|
	PyRotorObject *s;
 | 
						|
	char *name;
 | 
						|
{
 | 
						|
	return Py_FindMethod(PyRotor_Methods, (PyObject * ) s, name);
 | 
						|
}
 | 
						|
 | 
						|
statichere PyTypeObject PyRotor_Type = {
 | 
						|
	PyObject_HEAD_INIT(&PyType_Type)
 | 
						|
	0,				/*ob_size*/
 | 
						|
	"rotor",			/*tp_name*/
 | 
						|
	sizeof(PyRotorObject),		/*tp_size*/
 | 
						|
	0,				/*tp_itemsize*/
 | 
						|
	/* methods */
 | 
						|
	(destructor)PyRotor_Dealloc,	/*tp_dealloc*/
 | 
						|
	0,				/*tp_print*/
 | 
						|
	(getattrfunc)PyRotor_GetAttr,	/*tp_getattr*/
 | 
						|
	0,				/*tp_setattr*/
 | 
						|
	0,				/*tp_compare*/
 | 
						|
	0,				/*tp_repr*/
 | 
						|
	0,                              /*tp_hash*/
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
static PyObject * 
 | 
						|
PyRotor_Rotor(self, args)
 | 
						|
	PyObject * self;
 | 
						|
	PyObject * args;
 | 
						|
{
 | 
						|
	char *string;
 | 
						|
	PyRotorObject *r;
 | 
						|
	int len;
 | 
						|
	int num_rotors;
 | 
						|
 | 
						|
	if (PyArg_Parse(args,"s#", &string, &len)) {
 | 
						|
		num_rotors = 6;
 | 
						|
	} else {
 | 
						|
		PyErr_Clear();
 | 
						|
		if (!PyArg_Parse(args,"(s#i)", &string, &len, &num_rotors))
 | 
						|
			return NULL;
 | 
						|
	}
 | 
						|
	r = PyRotor_New(num_rotors, string);
 | 
						|
	return (PyObject * )r;
 | 
						|
}
 | 
						|
 | 
						|
static struct PyMethodDef PyRotor_Rotor_Methods[] = {
 | 
						|
	{"newrotor",		(PyCFunction)PyRotor_Rotor},
 | 
						|
	{NULL,			NULL}		 /* Sentinel */
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/* Initialize this module.
 | 
						|
   This is called when the first 'import rotor' is done,
 | 
						|
   via a table in config.c, if config.c is compiled with USE_ROTOR
 | 
						|
   defined. */
 | 
						|
 | 
						|
void
 | 
						|
initrotor()
 | 
						|
{
 | 
						|
	PyObject * m;
 | 
						|
 | 
						|
	m = Py_InitModule("rotor", PyRotor_Rotor_Methods);
 | 
						|
}
 |