1992-07-31 23:10:13 +08:00
|
|
|
|
/***********************************************************
|
1994-08-30 20:25:20 +08:00
|
|
|
|
Copyright 1994 by Lance Ellinghouse,
|
|
|
|
|
Cathedral City, California Republic, United States of America.
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
|
|
|
|
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
|
1994-08-30 20:25:20 +08:00
|
|
|
|
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.
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
1994-08-30 20:25:20 +08:00
|
|
|
|
LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
1992-07-31 23:10:13 +08:00
|
|
|
|
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
1994-08-30 20:25:20 +08:00
|
|
|
|
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.
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
|
|
|
|
******************************************************************/
|
|
|
|
|
|
|
|
|
|
/* 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:
|
|
|
|
|
|
1992-08-02 17:00:06 +08:00
|
|
|
|
- ro.setkey('string') -> None (resets the key as defined in newrotor().
|
1992-07-31 23:10:13 +08:00
|
|
|
|
- ro.encrypt('string') -> encrypted string
|
|
|
|
|
- ro.decrypt('encrypted string') -> unencrypted string
|
|
|
|
|
|
1992-08-02 17:00:06 +08:00
|
|
|
|
- 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.
|
|
|
|
|
|
1992-07-31 23:10:13 +08:00
|
|
|
|
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 */
|
|
|
|
|
|
1994-09-14 21:32:22 +08:00
|
|
|
|
#include "Python.h"
|
1995-03-09 20:14:15 +08:00
|
|
|
|
#include "mymath.h"
|
1995-01-11 04:56:29 +08:00
|
|
|
|
|
1997-05-20 23:58:36 +08:00
|
|
|
|
#ifndef TRUE
|
1992-08-02 17:00:06 +08:00
|
|
|
|
#define TRUE 1
|
1997-05-20 23:58:36 +08:00
|
|
|
|
#endif
|
|
|
|
|
#ifndef FALSE
|
1992-08-02 17:00:06 +08:00
|
|
|
|
#define FALSE 0
|
1997-05-20 23:58:36 +08:00
|
|
|
|
#endif
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
|
|
|
|
typedef struct {
|
1994-08-29 18:46:42 +08:00
|
|
|
|
PyObject_HEAD
|
1992-07-31 23:10:13 +08:00
|
|
|
|
int seed[3];
|
|
|
|
|
short key[5];
|
1992-08-02 17:00:06 +08:00
|
|
|
|
int isinited;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
int size;
|
|
|
|
|
int size_mask;
|
|
|
|
|
int rotors;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
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;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
staticforward PyTypeObject Rotor_Type;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
#define is_rotor(v) ((v)->ob_type == &Rotor_Type)
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
|
|
|
|
|
/* This defines the necessary routines to manage rotor objects */
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static void
|
|
|
|
|
set_seed(r)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
r->seed[0] = r->key[0];
|
|
|
|
|
r->seed[1] = r->key[1];
|
|
|
|
|
r->seed[2] = r->key[2];
|
1992-08-02 17:00:06 +08:00
|
|
|
|
r->isinited = FALSE;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return the next random number in the range [0.0 .. 1.0) */
|
1997-04-12 04:44:04 +08:00
|
|
|
|
static double
|
1996-12-24 07:36:24 +08:00
|
|
|
|
r_random(r)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
int x, y, z;
|
1997-04-12 04:44:04 +08:00
|
|
|
|
double val, term;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
1997-04-12 04:44:04 +08:00
|
|
|
|
term = (double)(
|
|
|
|
|
(((double)x)/(double)30269.0) +
|
|
|
|
|
(((double)y)/(double)30307.0) +
|
|
|
|
|
(((double)z)/(double)30323.0)
|
1996-12-24 07:36:24 +08:00
|
|
|
|
);
|
1997-04-12 04:44:04 +08:00
|
|
|
|
val = term - (double)floor((double)term);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
if (val >= 1.0)
|
|
|
|
|
val = 0.0;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static short
|
|
|
|
|
r_rand(r, s)
|
|
|
|
|
Rotorobj *r;
|
|
|
|
|
short s;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
1997-04-12 04:44:04 +08:00
|
|
|
|
return (short)((short)(r_random(r) * (double)s) % s);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static void
|
|
|
|
|
set_key(r, key)
|
|
|
|
|
Rotorobj *r;
|
|
|
|
|
char *key;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
1993-11-03 23:01:26 +08:00
|
|
|
|
unsigned long k1=995, k2=576, k3=767, k4=671, k5=463;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
int i;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
int len = strlen(key);
|
1997-01-17 00:49:44 +08:00
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
for (i = 0; i < len; i++) {
|
1997-01-17 00:49:44 +08:00
|
|
|
|
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);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
|
|
|
|
|
|
1992-07-31 23:10:13 +08:00
|
|
|
|
/* These define the interface to a rotor object */
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static Rotorobj *
|
|
|
|
|
rotorobj_new(num_rotors, key)
|
1992-07-31 23:10:13 +08:00
|
|
|
|
int num_rotors;
|
|
|
|
|
char *key;
|
|
|
|
|
{
|
1996-12-24 07:36:24 +08:00
|
|
|
|
Rotorobj *xp;
|
|
|
|
|
|
|
|
|
|
xp = PyObject_NEW(Rotorobj, &Rotor_Type);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
if (xp == NULL)
|
|
|
|
|
return NULL;
|
1992-07-31 23:11:01 +08:00
|
|
|
|
set_key(xp, key);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
|
|
|
|
xp->size = 256;
|
|
|
|
|
xp->size_mask = xp->size - 1;
|
|
|
|
|
xp->size_mask = 0;
|
|
|
|
|
xp->rotors = num_rotors;
|
1992-07-31 23:11:01 +08:00
|
|
|
|
xp->e_rotor = NULL;
|
|
|
|
|
xp->d_rotor = NULL;
|
|
|
|
|
xp->positions = NULL;
|
|
|
|
|
xp->advances = NULL;
|
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
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;
|
|
|
|
|
|
1992-07-31 23:10:13 +08:00
|
|
|
|
return xp;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
|
|
|
|
|
finally:
|
|
|
|
|
PyMem_XDEL(xp->e_rotor);
|
|
|
|
|
PyMem_XDEL(xp->d_rotor);
|
|
|
|
|
PyMem_XDEL(xp->positions);
|
|
|
|
|
PyMem_XDEL(xp->advances);
|
1995-01-11 04:56:29 +08:00
|
|
|
|
Py_DECREF(xp);
|
1996-12-24 07:36:24 +08:00
|
|
|
|
return (Rotorobj*)PyErr_NoMemory();
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
|
1992-07-31 23:10:13 +08:00
|
|
|
|
/* These routines impliment the rotor itself */
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
/* 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
|
1996-12-24 07:36:24 +08:00
|
|
|
|
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.
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
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).
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
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.
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
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.
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
j'
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* 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 */
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static void
|
|
|
|
|
RTR_make_id_rotor(r, rtr)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
unsigned char *rtr;
|
|
|
|
|
{
|
|
|
|
|
register int j;
|
|
|
|
|
register int size = r->size;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
for (j = 0; j < size; j++) {
|
1992-07-31 23:10:13 +08:00
|
|
|
|
rtr[j] = (unsigned char)j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
/* The current set of encryption rotors */
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static void
|
|
|
|
|
RTR_e_rotors(r)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
int i;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
for (i = 0; i < r->rotors; i++) {
|
|
|
|
|
RTR_make_id_rotor(r, &(r->e_rotor[(i*r->size)]));
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
/* The current set of decryption rotors */
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static void
|
|
|
|
|
RTR_d_rotors(r)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
register int i, j;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
for (i = 0; i < r->rotors; i++) {
|
|
|
|
|
for (j = 0; j < r->size; j++) {
|
1992-07-31 23:10:13 +08:00
|
|
|
|
r->d_rotor[((i*r->size)+j)] = (unsigned char)j;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
/* The positions of the rotors at this time */
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static void
|
|
|
|
|
RTR_positions(r)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
int i;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
for (i = 0; i < r->rotors; i++) {
|
1992-07-31 23:10:13 +08:00
|
|
|
|
r->positions[i] = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
/* The number of positions to advance the rotors at a time */
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static void
|
|
|
|
|
RTR_advances(r)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
int i;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
for (i = 0; i < r->rotors; i++) {
|
1992-07-31 23:10:13 +08:00
|
|
|
|
r->advances[i] = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
/* Permute the E rotor, and make the D rotor its inverse
|
|
|
|
|
* see Knuth for explanation of algorithm.
|
|
|
|
|
*/
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static void
|
|
|
|
|
RTR_permute_rotor(r, e, d)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
/* Given KEY (a list of 5 16 bit numbers), initialize the rotor machine.
|
|
|
|
|
* Set the advancement, position, and permutation of the rotors
|
|
|
|
|
*/
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static void
|
|
|
|
|
RTR_init(r)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
set_seed(r);
|
|
|
|
|
RTR_positions(r);
|
|
|
|
|
RTR_advances(r);
|
|
|
|
|
RTR_e_rotors(r);
|
|
|
|
|
RTR_d_rotors(r);
|
1996-12-24 07:36:24 +08:00
|
|
|
|
for (i = 0; i < r->rotors; i++) {
|
1997-04-12 04:44:04 +08:00
|
|
|
|
r->positions[i] = (unsigned char) r_rand(r,r->size);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
r->advances[i] = (1+(2*(r_rand(r,r->size/2))));
|
1996-12-24 07:36:24 +08:00
|
|
|
|
RTR_permute_rotor(r,
|
|
|
|
|
&(r->e_rotor[(i*r->size)]),
|
|
|
|
|
&(r->d_rotor[(i*r->size)]));
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
1992-08-02 17:00:06 +08:00
|
|
|
|
r->isinited = TRUE;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
/* Change the RTR-positions vector, using the RTR-advances vector */
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static void
|
|
|
|
|
RTR_advance(r)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
register int i=0, temp=0;
|
|
|
|
|
if (r->size_mask) {
|
1996-12-24 07:36:24 +08:00
|
|
|
|
while (i < r->rotors) {
|
1992-07-31 23:10:13 +08:00
|
|
|
|
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 {
|
1996-12-24 07:36:24 +08:00
|
|
|
|
while (i < r->rotors) {
|
1992-07-31 23:10:13 +08:00
|
|
|
|
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++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
/* Encrypt the character P with the current rotor machine */
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static unsigned char
|
|
|
|
|
RTR_e_char(r, p)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
unsigned char p;
|
|
|
|
|
{
|
|
|
|
|
register int i=0;
|
|
|
|
|
register unsigned char tp=p;
|
|
|
|
|
if (r->size_mask) {
|
|
|
|
|
while (i < r->rotors) {
|
1996-12-24 07:36:24 +08:00
|
|
|
|
tp = r->e_rotor[(i*r->size) +
|
|
|
|
|
(((r->positions[i] ^ tp) &
|
|
|
|
|
r->size_mask))];
|
1992-07-31 23:10:13 +08:00
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
while (i < r->rotors) {
|
1996-12-24 07:36:24 +08:00
|
|
|
|
tp = r->e_rotor[(i*r->size) +
|
|
|
|
|
(((r->positions[i] ^ tp) %
|
|
|
|
|
(unsigned int) r->size))];
|
1992-07-31 23:10:13 +08:00
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
RTR_advance(r);
|
|
|
|
|
return ((unsigned char)tp);
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
/* Decrypt the character C with the current rotor machine */
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static unsigned char
|
|
|
|
|
RTR_d_char(r, c)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
unsigned char c;
|
|
|
|
|
{
|
1996-12-24 07:36:24 +08:00
|
|
|
|
register int i = r->rotors - 1;
|
|
|
|
|
register unsigned char tc = c;
|
|
|
|
|
|
1992-07-31 23:10:13 +08:00
|
|
|
|
if (r->size_mask) {
|
|
|
|
|
while (0 <= i) {
|
1996-12-24 07:36:24 +08:00
|
|
|
|
tc = (r->positions[i] ^
|
|
|
|
|
r->d_rotor[(i*r->size)+tc]) & r->size_mask;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
i--;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
while (0 <= i) {
|
1996-12-24 07:36:24 +08:00
|
|
|
|
tc = (r->positions[i] ^
|
|
|
|
|
r->d_rotor[(i*r->size)+tc]) %
|
|
|
|
|
(unsigned int) r->size;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
i--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
RTR_advance(r);
|
|
|
|
|
return(tc);
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
/* Perform a rotor encryption of the region from BEG to END by KEY */
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static void
|
|
|
|
|
RTR_e_region(r, beg, len, doinit)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
unsigned char *beg;
|
|
|
|
|
int len;
|
1992-08-02 17:00:06 +08:00
|
|
|
|
int doinit;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
register int i;
|
1992-08-02 17:00:06 +08:00
|
|
|
|
if (doinit || r->isinited == FALSE)
|
|
|
|
|
RTR_init(r);
|
1996-12-24 07:36:24 +08:00
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
beg[i] = RTR_e_char(r, beg[i]);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
/* Perform a rotor decryption of the region from BEG to END by KEY */
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static void
|
|
|
|
|
RTR_d_region(r, beg, len, doinit)
|
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
unsigned char *beg;
|
|
|
|
|
int len;
|
1992-08-02 17:00:06 +08:00
|
|
|
|
int doinit;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
register int i;
|
1992-08-02 17:00:06 +08:00
|
|
|
|
if (doinit || r->isinited == FALSE)
|
|
|
|
|
RTR_init(r);
|
1996-12-24 07:36:24 +08:00
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
beg[i] = RTR_d_char(r, beg[i]);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
|
1992-07-31 23:10:13 +08:00
|
|
|
|
/* Rotor methods */
|
|
|
|
|
static void
|
1996-12-24 07:36:24 +08:00
|
|
|
|
rotor_dealloc(xp)
|
|
|
|
|
Rotorobj *xp;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
1994-08-29 18:46:42 +08:00
|
|
|
|
PyMem_XDEL(xp->e_rotor);
|
|
|
|
|
PyMem_XDEL(xp->d_rotor);
|
|
|
|
|
PyMem_XDEL(xp->positions);
|
|
|
|
|
PyMem_XDEL(xp->advances);
|
|
|
|
|
PyMem_DEL(xp);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
1994-08-30 20:25:20 +08:00
|
|
|
|
static PyObject *
|
1996-12-24 07:36:24 +08:00
|
|
|
|
rotorobj_encrypt(self, args)
|
|
|
|
|
Rotorobj *self;
|
1994-08-30 20:25:20 +08:00
|
|
|
|
PyObject * args;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
1996-12-24 07:36:24 +08:00
|
|
|
|
char *string = NULL;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
int len = 0;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
PyObject *rtn = NULL;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
char *tmp;
|
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
if (!PyArg_Parse(args, "s#", &string, &len))
|
1992-07-31 23:10:13 +08:00
|
|
|
|
return NULL;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
if (!(tmp = PyMem_NEW(char, len+5))) {
|
1994-08-29 18:46:42 +08:00
|
|
|
|
PyErr_NoMemory();
|
1992-07-31 23:10:13 +08:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
1996-12-24 07:36:24 +08:00
|
|
|
|
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);
|
1992-08-02 17:00:06 +08:00
|
|
|
|
return(rtn);
|
|
|
|
|
}
|
|
|
|
|
|
1994-08-30 20:25:20 +08:00
|
|
|
|
static PyObject *
|
1996-12-24 07:36:24 +08:00
|
|
|
|
rotorobj_encrypt_more(self, args)
|
|
|
|
|
Rotorobj *self;
|
1994-08-30 20:25:20 +08:00
|
|
|
|
PyObject * args;
|
1992-08-02 17:00:06 +08:00
|
|
|
|
{
|
1996-12-24 07:36:24 +08:00
|
|
|
|
char *string = NULL;
|
1992-08-02 17:00:06 +08:00
|
|
|
|
int len = 0;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
PyObject *rtn = NULL;
|
1992-08-02 17:00:06 +08:00
|
|
|
|
char *tmp;
|
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
if (!PyArg_Parse(args, "s#", &string, &len))
|
1992-08-02 17:00:06 +08:00
|
|
|
|
return NULL;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
if (!(tmp = PyMem_NEW(char, len+5))) {
|
1994-08-29 18:46:42 +08:00
|
|
|
|
PyErr_NoMemory();
|
1992-08-02 17:00:06 +08:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
1996-12-24 07:36:24 +08:00
|
|
|
|
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);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
return(rtn);
|
|
|
|
|
}
|
|
|
|
|
|
1994-08-30 20:25:20 +08:00
|
|
|
|
static PyObject *
|
1996-12-24 07:36:24 +08:00
|
|
|
|
rotorobj_decrypt(self, args)
|
|
|
|
|
Rotorobj *self;
|
1994-08-30 20:25:20 +08:00
|
|
|
|
PyObject * args;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
1996-12-24 07:36:24 +08:00
|
|
|
|
char *string = NULL;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
int len = 0;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
PyObject *rtn = NULL;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
char *tmp;
|
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
if (!PyArg_Parse(args, "s#", &string, &len))
|
1992-07-31 23:10:13 +08:00
|
|
|
|
return NULL;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
if (!(tmp = PyMem_NEW(char, len+5))) {
|
1994-08-29 18:46:42 +08:00
|
|
|
|
PyErr_NoMemory();
|
1992-07-31 23:10:13 +08:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
1996-12-24 07:36:24 +08:00
|
|
|
|
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);
|
1992-08-02 17:00:06 +08:00
|
|
|
|
return(rtn);
|
|
|
|
|
}
|
|
|
|
|
|
1994-08-30 20:25:20 +08:00
|
|
|
|
static PyObject *
|
1996-12-24 07:36:24 +08:00
|
|
|
|
rotorobj_decrypt_more(self, args)
|
|
|
|
|
Rotorobj *self;
|
1994-08-30 20:25:20 +08:00
|
|
|
|
PyObject * args;
|
1992-08-02 17:00:06 +08:00
|
|
|
|
{
|
1996-12-24 07:36:24 +08:00
|
|
|
|
char *string = NULL;
|
1992-08-02 17:00:06 +08:00
|
|
|
|
int len = 0;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
PyObject *rtn = NULL;
|
1992-08-02 17:00:06 +08:00
|
|
|
|
char *tmp;
|
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
if (!PyArg_Parse(args, "s#", &string, &len))
|
1992-08-02 17:00:06 +08:00
|
|
|
|
return NULL;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
if (!(tmp = PyMem_NEW(char, len+5))) {
|
1994-08-29 18:46:42 +08:00
|
|
|
|
PyErr_NoMemory();
|
1992-08-02 17:00:06 +08:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
1996-12-24 07:36:24 +08:00
|
|
|
|
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);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
return(rtn);
|
|
|
|
|
}
|
|
|
|
|
|
1994-08-30 20:25:20 +08:00
|
|
|
|
static PyObject *
|
1996-12-24 07:36:24 +08:00
|
|
|
|
rotorobj_setkey(self, args)
|
|
|
|
|
Rotorobj *self;
|
1994-08-30 20:25:20 +08:00
|
|
|
|
PyObject * args;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
1997-01-03 04:36:36 +08:00
|
|
|
|
char *key;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
|
1997-01-03 04:36:36 +08:00
|
|
|
|
if (!PyArg_ParseTuple(args, "s", &key))
|
1996-12-24 07:36:24 +08:00
|
|
|
|
return NULL;
|
|
|
|
|
|
1997-01-03 04:36:36 +08:00
|
|
|
|
set_key(self, key);
|
1994-08-30 20:25:20 +08:00
|
|
|
|
Py_INCREF(Py_None);
|
|
|
|
|
return Py_None;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
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},
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{NULL, NULL} /* sentinel */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Return a rotor object's named attribute. */
|
1994-08-30 20:25:20 +08:00
|
|
|
|
static PyObject *
|
1996-12-24 07:36:24 +08:00
|
|
|
|
rotorobj_getattr(s, name)
|
|
|
|
|
Rotorobj *s;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
char *name;
|
|
|
|
|
{
|
1996-12-24 07:36:24 +08:00
|
|
|
|
return Py_FindMethod(rotorobj_methods, (PyObject*)s, name);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
|
|
|
|
|
statichere PyTypeObject Rotor_Type = {
|
1995-01-11 04:56:29 +08:00
|
|
|
|
PyObject_HEAD_INIT(&PyType_Type)
|
1994-08-01 19:34:53 +08:00
|
|
|
|
0, /*ob_size*/
|
1992-07-31 23:10:13 +08:00
|
|
|
|
"rotor", /*tp_name*/
|
1996-12-24 07:36:24 +08:00
|
|
|
|
sizeof(Rotorobj), /*tp_size*/
|
1994-08-01 19:34:53 +08:00
|
|
|
|
0, /*tp_itemsize*/
|
1992-07-31 23:10:13 +08:00
|
|
|
|
/* methods */
|
1996-12-24 07:36:24 +08:00
|
|
|
|
(destructor)rotor_dealloc, /*tp_dealloc*/
|
1994-08-01 19:34:53 +08:00
|
|
|
|
0, /*tp_print*/
|
1996-12-24 07:36:24 +08:00
|
|
|
|
(getattrfunc)rotorobj_getattr, /*tp_getattr*/
|
1994-08-01 19:34:53 +08:00
|
|
|
|
0, /*tp_setattr*/
|
|
|
|
|
0, /*tp_compare*/
|
|
|
|
|
0, /*tp_repr*/
|
1994-08-29 18:46:42 +08:00
|
|
|
|
0, /*tp_hash*/
|
1992-07-31 23:10:13 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
1994-08-30 20:25:20 +08:00
|
|
|
|
static PyObject *
|
1996-12-24 07:36:24 +08:00
|
|
|
|
rotor_rotor(self, args)
|
1994-08-30 20:25:20 +08:00
|
|
|
|
PyObject * self;
|
|
|
|
|
PyObject * args;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
{
|
1996-12-24 07:36:24 +08:00
|
|
|
|
Rotorobj *r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
char *string;
|
|
|
|
|
int len;
|
1996-12-24 07:36:24 +08:00
|
|
|
|
int num_rotors = 6;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
if (!PyArg_ParseTuple(args, "s#|i", &string, &len, &num_rotors))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
r = rotorobj_new(num_rotors, string);
|
|
|
|
|
return (PyObject *)r;
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
|
1997-01-17 00:49:44 +08:00
|
|
|
|
|
1996-12-24 07:36:24 +08:00
|
|
|
|
static struct PyMethodDef
|
|
|
|
|
rotor_methods[] = {
|
|
|
|
|
{"newrotor", rotor_rotor, 1},
|
|
|
|
|
{NULL, NULL} /* sentinel */
|
1992-07-31 23:10:13 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
initrotor()
|
|
|
|
|
{
|
1996-12-24 07:36:24 +08:00
|
|
|
|
(void)Py_InitModule("rotor", rotor_methods);
|
1992-07-31 23:10:13 +08:00
|
|
|
|
}
|