mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			670 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			670 lines
		
	
	
	
		
			15 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"
 | ||
| 
 | ||
| #ifndef TRUE
 | ||
| #define TRUE	1
 | ||
| #endif
 | ||
| #ifndef FALSE
 | ||
| #define FALSE	0
 | ||
| #endif
 | ||
| 
 | ||
| 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] */
 | ||
| } Rotorobj;
 | ||
| 
 | ||
| staticforward PyTypeObject Rotor_Type;
 | ||
| 
 | ||
| #define is_rotor(v)		((v)->ob_type == &Rotor_Type)
 | ||
| 
 | ||
| 
 | ||
| /* This defines the necessary routines to manage rotor objects */
 | ||
| 
 | ||
| static void
 | ||
| set_seed(r) 
 | ||
| 	Rotorobj *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 double
 | ||
| r_random(r)
 | ||
| 	Rotorobj *r;
 | ||
| {
 | ||
| 	int x, y, z;
 | ||
| 	double 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 = (double)(
 | ||
| 		(((double)x)/(double)30269.0) + 
 | ||
| 		(((double)y)/(double)30307.0) + 
 | ||
| 		(((double)z)/(double)30323.0)
 | ||
| 		);
 | ||
| 	val = term - (double)floor((double)term);
 | ||
| 
 | ||
| 	if (val >= 1.0)
 | ||
| 		val = 0.0;
 | ||
| 
 | ||
| 	return val;
 | ||
| }
 | ||
| 
 | ||
| static short
 | ||
| r_rand(r, s)
 | ||
| 	Rotorobj *r;
 | ||
| 	short s;
 | ||
| {
 | ||
| 	return (short)((short)(r_random(r) * (double)s) % s);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| set_key(r, key)
 | ||
| 	Rotorobj *r;
 | ||
| 	char *key;
 | ||
| {
 | ||
| 	unsigned long k1=995, k2=576, k3=767, k4=671, k5=463;
 | ||
| 	size_t i;
 | ||
| 	size_t len = strlen(key);
 | ||
| 
 | ||
| 	for (i = 0; i < len; i++) {
 | ||
| 		unsigned short ki = Py_CHARMASK(key[i]);
 | ||
| 
 | ||
| 		k1 = (((k1<<3 | k1>>13) + ki) & 65535);
 | ||
| 		k2 = (((k2<<3 | k2>>13) ^ ki) & 65535);
 | ||
| 		k3 = (((k3<<3 | k3>>13) - ki) & 65535);
 | ||
| 		k4 = ((ki - (k4<<3 | k4>>13)) & 65535);
 | ||
| 		k5 = (((k5<<3 | k5>>13) ^ ~ki) & 65535);
 | ||
| 	}
 | ||
| 	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 Rotorobj *
 | ||
| rotorobj_new(num_rotors, key)
 | ||
| 	int num_rotors;
 | ||
| 	char *key;
 | ||
| {
 | ||
| 	Rotorobj *xp;
 | ||
| 
 | ||
| 	xp = PyObject_New(Rotorobj, &Rotor_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;
 | ||
| 
 | ||
| 	if (!(xp->e_rotor = PyMem_NEW(unsigned char, num_rotors * xp->size)))
 | ||
| 		goto finally;
 | ||
| 	if (!(xp->d_rotor = PyMem_NEW(unsigned char, num_rotors * xp->size)))
 | ||
| 		goto finally;
 | ||
| 	if (!(xp->positions = PyMem_NEW(unsigned char, num_rotors)))
 | ||
| 		goto finally;
 | ||
| 	if (!(xp->advances = PyMem_NEW(unsigned char, num_rotors)))
 | ||
| 		goto finally;
 | ||
| 
 | ||
| 	return xp;
 | ||
| 
 | ||
|   finally:
 | ||
| 	if (xp->e_rotor)
 | ||
| 		PyMem_DEL(xp->e_rotor);
 | ||
| 	if (xp->d_rotor)
 | ||
| 		PyMem_DEL(xp->d_rotor);
 | ||
| 	if (xp->positions)
 | ||
| 		PyMem_DEL(xp->positions);
 | ||
| 	if (xp->advances)
 | ||
| 		PyMem_DEL(xp->advances);
 | ||
| 	Py_DECREF(xp);
 | ||
| 	return (Rotorobj*)PyErr_NoMemory();
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /* These routines impliment the rotor itself */
 | ||
| 
 | ||
| /*  Here is a fairly sophisticated {en,de}cryption system.  It is based 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'
 | ||
| 
 | ||
|  */
 | ||
| 
 | ||
| /* Note: the C code here is a fairly straightforward transliteration of a
 | ||
|  * rotor implemented in lisp.  The original lisp code has been removed from
 | ||
|  * this file to for simplification, but I've kept the docstrings as
 | ||
|  * comments in front of the functions.
 | ||
|  */
 | ||
| 
 | ||
| 
 | ||
| /* Set ROTOR to the identity permutation */
 | ||
| static void
 | ||
| RTR_make_id_rotor(r, rtr)
 | ||
| 	Rotorobj *r;
 | ||
| 	unsigned char *rtr;
 | ||
| {
 | ||
| 	register int j;
 | ||
| 	register int size = r->size;
 | ||
| 	for (j = 0; j < size; j++) {
 | ||
| 		rtr[j] = (unsigned char)j;
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /* The current set of encryption rotors */
 | ||
| static void
 | ||
| RTR_e_rotors(r)
 | ||
| 	Rotorobj *r;
 | ||
| {
 | ||
| 	int i;
 | ||
| 	for (i = 0; i < r->rotors; i++) {
 | ||
| 		RTR_make_id_rotor(r, &(r->e_rotor[(i*r->size)]));
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| /* The current set of decryption rotors */
 | ||
| static void
 | ||
| RTR_d_rotors(r)
 | ||
| 	Rotorobj *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;
 | ||
| 		}
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| /* The positions of the rotors at this time */
 | ||
| static void
 | ||
| RTR_positions(r)
 | ||
| 	Rotorobj *r;
 | ||
| {
 | ||
| 	int i;
 | ||
| 	for (i = 0; i < r->rotors; i++) {
 | ||
| 		r->positions[i] = 1;
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| /* The number of positions to advance the rotors at a time */
 | ||
| static void
 | ||
| RTR_advances(r) 
 | ||
| 	Rotorobj *r;
 | ||
| {
 | ||
| 	int i;
 | ||
| 	for (i = 0; i < r->rotors; i++) {
 | ||
| 		r->advances[i] = 1;
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| /* Permute the E rotor, and make the D rotor its inverse
 | ||
|  * see Knuth for explanation of algorithm.
 | ||
|  */
 | ||
| static void
 | ||
| RTR_permute_rotor(r, e, d)
 | ||
| 	Rotorobj *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;
 | ||
| }
 | ||
| 
 | ||
| /* Given KEY (a list of 5 16 bit numbers), initialize the rotor machine.
 | ||
|  * Set the advancement, position, and permutation of the rotors
 | ||
|  */
 | ||
| static void
 | ||
| RTR_init(r)
 | ||
| 	Rotorobj *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] = (unsigned char) 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;
 | ||
| }
 | ||
| 
 | ||
| /* Change the RTR-positions vector, using the RTR-advances vector */
 | ||
| static void
 | ||
| RTR_advance(r)
 | ||
| 	Rotorobj *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++;
 | ||
| 		}
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| /* Encrypt the character P with the current rotor machine */
 | ||
| static unsigned char
 | ||
| RTR_e_char(r, p)
 | ||
| 	Rotorobj *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);
 | ||
| }
 | ||
| 
 | ||
| /* Decrypt the character C with the current rotor machine */
 | ||
| static unsigned char
 | ||
| RTR_d_char(r, c)
 | ||
| 	Rotorobj *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);
 | ||
| }
 | ||
| 
 | ||
| /* Perform a rotor encryption of the region from BEG to END by KEY */
 | ||
| static void
 | ||
| RTR_e_region(r, beg, len, doinit)
 | ||
| 	Rotorobj *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]);
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| /* Perform a rotor decryption of the region from BEG to END by KEY */
 | ||
| static void
 | ||
| RTR_d_region(r, beg, len, doinit)
 | ||
| 	Rotorobj *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]);
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| /* Rotor methods */
 | ||
| static void
 | ||
| rotor_dealloc(xp)
 | ||
| 	Rotorobj *xp;
 | ||
| {
 | ||
| 	if (xp->e_rotor)
 | ||
| 		PyMem_DEL(xp->e_rotor);
 | ||
| 	if (xp->d_rotor)
 | ||
| 		PyMem_DEL(xp->d_rotor);
 | ||
| 	if (xp->positions)
 | ||
| 		PyMem_DEL(xp->positions);
 | ||
| 	if (xp->advances)
 | ||
| 		PyMem_DEL(xp->advances);
 | ||
| 	PyObject_Del(xp);
 | ||
| }
 | ||
| 
 | ||
| static PyObject * 
 | ||
| rotorobj_encrypt(self, args)
 | ||
| 	Rotorobj *self;
 | ||
| 	PyObject * args;
 | ||
| {
 | ||
| 	char *string = NULL;
 | ||
| 	int len = 0;
 | ||
| 	PyObject *rtn = NULL;
 | ||
| 	char *tmp;
 | ||
| 
 | ||
| 	if (!PyArg_Parse(args, "s#", &string, &len))
 | ||
| 		return NULL;
 | ||
| 	if (!(tmp = PyMem_NEW(char, 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);
 | ||
| 	PyMem_DEL(tmp);
 | ||
| 	return(rtn);
 | ||
| }
 | ||
| 
 | ||
| static PyObject * 
 | ||
| rotorobj_encrypt_more(self, args)
 | ||
| 	Rotorobj *self;
 | ||
| 	PyObject * args;
 | ||
| {
 | ||
| 	char *string = NULL;
 | ||
| 	int len = 0;
 | ||
| 	PyObject *rtn = NULL;
 | ||
| 	char *tmp;
 | ||
| 
 | ||
| 	if (!PyArg_Parse(args, "s#", &string, &len))
 | ||
| 		return NULL;
 | ||
| 	if (!(tmp = PyMem_NEW(char, 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);
 | ||
| 	PyMem_DEL(tmp);
 | ||
| 	return(rtn);
 | ||
| }
 | ||
| 
 | ||
| static PyObject * 
 | ||
| rotorobj_decrypt(self, args)
 | ||
| 	Rotorobj *self;
 | ||
| 	PyObject * args;
 | ||
| {
 | ||
| 	char *string = NULL;
 | ||
| 	int len = 0;
 | ||
| 	PyObject *rtn = NULL;
 | ||
| 	char *tmp;
 | ||
| 
 | ||
| 	if (!PyArg_Parse(args, "s#", &string, &len))
 | ||
| 		return NULL;
 | ||
| 	if (!(tmp = PyMem_NEW(char, 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);
 | ||
| 	PyMem_DEL(tmp);
 | ||
| 	return(rtn);
 | ||
| }
 | ||
| 
 | ||
| static PyObject * 
 | ||
| rotorobj_decrypt_more(self, args)
 | ||
| 	Rotorobj *self;
 | ||
| 	PyObject * args;
 | ||
| {
 | ||
| 	char *string = NULL;
 | ||
| 	int len = 0;
 | ||
| 	PyObject *rtn = NULL;
 | ||
| 	char *tmp;
 | ||
| 
 | ||
| 	if (!PyArg_Parse(args, "s#", &string, &len))
 | ||
| 		return NULL;
 | ||
| 	if (!(tmp = PyMem_NEW(char, 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);
 | ||
| 	PyMem_DEL(tmp);
 | ||
| 	return(rtn);
 | ||
| }
 | ||
| 
 | ||
| static PyObject * 
 | ||
| rotorobj_setkey(self, args)
 | ||
| 	Rotorobj *self;
 | ||
| 	PyObject * args;
 | ||
| {
 | ||
| 	char *key;
 | ||
| 
 | ||
| 	if (!PyArg_ParseTuple(args, "s:setkey", &key))
 | ||
| 		return NULL;
 | ||
| 
 | ||
| 	set_key(self, key);
 | ||
| 	Py_INCREF(Py_None);
 | ||
| 	return Py_None;
 | ||
| }
 | ||
| 
 | ||
| static struct PyMethodDef
 | ||
| rotorobj_methods[] = {
 | ||
| 	{"encrypt",	(PyCFunction)rotorobj_encrypt},
 | ||
| 	{"encryptmore",	(PyCFunction)rotorobj_encrypt_more},
 | ||
| 	{"decrypt",	(PyCFunction)rotorobj_decrypt},
 | ||
| 	{"decryptmore",	(PyCFunction)rotorobj_decrypt_more},
 | ||
| 	{"setkey",	(PyCFunction)rotorobj_setkey, 1},
 | ||
| 	{NULL,		NULL}		/* sentinel */
 | ||
| };
 | ||
| 
 | ||
| 
 | ||
| /* Return a rotor object's named attribute. */
 | ||
| static PyObject * 
 | ||
| rotorobj_getattr(s, name)
 | ||
| 	Rotorobj *s;
 | ||
| 	char *name;
 | ||
| {
 | ||
| 	return Py_FindMethod(rotorobj_methods, (PyObject*)s, name);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| statichere PyTypeObject Rotor_Type = {
 | ||
| 	PyObject_HEAD_INIT(&PyType_Type)
 | ||
| 	0,				/*ob_size*/
 | ||
| 	"rotor",			/*tp_name*/
 | ||
| 	sizeof(Rotorobj),		/*tp_size*/
 | ||
| 	0,				/*tp_itemsize*/
 | ||
| 	/* methods */
 | ||
| 	(destructor)rotor_dealloc,	/*tp_dealloc*/
 | ||
| 	0,				/*tp_print*/
 | ||
| 	(getattrfunc)rotorobj_getattr,	/*tp_getattr*/
 | ||
| 	0,				/*tp_setattr*/
 | ||
| 	0,				/*tp_compare*/
 | ||
| 	0,				/*tp_repr*/
 | ||
| 	0,                              /*tp_hash*/
 | ||
| };
 | ||
| 
 | ||
| 
 | ||
| static PyObject * 
 | ||
| rotor_rotor(self, args)
 | ||
| 	PyObject * self;
 | ||
| 	PyObject * args;
 | ||
| {
 | ||
| 	Rotorobj *r;
 | ||
| 	char *string;
 | ||
| 	int len;
 | ||
| 	int num_rotors = 6;
 | ||
| 
 | ||
| 	if (!PyArg_ParseTuple(args, "s#|i:newrotor", &string, &len, &num_rotors))
 | ||
| 		return NULL;
 | ||
| 
 | ||
| 	r = rotorobj_new(num_rotors, string);
 | ||
| 	return (PyObject *)r;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| static struct PyMethodDef
 | ||
| rotor_methods[] = {
 | ||
| 	{"newrotor",  rotor_rotor, 1},
 | ||
| 	{NULL,        NULL}		     /* sentinel */
 | ||
| };
 | ||
| 
 | ||
| 
 | ||
| DL_EXPORT(void)
 | ||
| initrotor()
 | ||
| {
 | ||
| 	(void)Py_InitModule("rotor", rotor_methods);
 | ||
| }
 | 
