Xor-Salt Encryption
NOTE: Encryption changed after Wize 2.1.
Xor-Salt implements low-rent, symmetrical encryption by
xor-ing data with a password and
salt.
The salt is generated from the password itself,
and gets
reshuffled at periods of irregular length throughout the encryption.
DISCLAIMER: Xor-Salt does NOT provide commercial grade encryption!!!
In fact, Xor-Salt uses no cryptographic math what-so-ever. For that you should use SSL.
Nevertheless, for many real world applications SSL is overkill.
Xor-Salt offers simple encryption in a very small code base.
And, using Xor-Salt to encrypt with the
128 bit MD5 of a password provides
pretty good secrecy.
An example application using Xor-Salt is
Sqlite Over Sockets.
In place of a detailed description, code is provided below:
/* BSD copyright 2008 - Peter MacDonald - http://pdqi.com
* Xor-salt encryption. Returns encrypted string of length len
* where in-len == out-len and odata and data may be the same.
* If odata is NULL, it gets alloc'ed.
* The value of saltsz is >=0 && <=256. Typical values: 4 or 8.
*/
static char *
saltxorstr(
int plen,
char *password,
int len,
char *data,
char *odata,
int saltsz
) {
unsigned char *ip, *pp, *ib, *c, rval, seed, salts[256], ppBuf[BUFSIZ+20];
int i=0, j, p, n, random = 0;
ip = password;
ib = data;
if (plen<1) {
return NULL;
}
if (saltsz<0 || saltsz>256) {
return NULL;
}
if (odata != NULL) {
c = (unsigned char *)odata;
} else {
c = (unsigned char *)ckalloc(len*sizeof(unsigned char));
}
if (plen<BUFSIZ) {
pp = ppBuf;
} else {
pp = (unsigned char *)ckalloc((plen+20)*sizeof(unsigned char));
}
strcpy(pp, ip);
for (i=0; i<16; i++) {
pp[plen+i] = ip[i%plen];
}
p = -1;
if (saltsz) {
for (i=0; i<saltsz; i++) {
salts[i] = 0;
}
/* Rotate password bits 90 degrees and skew. */
for (i=0; i<plen; i+=8) {
for (j=0; j<8; j++) {
unsigned char nv;
nv = (pp[i+j]&0x1)|(pp[i+j+4]&0x10)| \
(pp[i+j+1]&0x2)|(pp[i+j+5]&0x20)| \
(pp[i+j+2]&0x4)|(pp[i+j+6]&0x40)| \
(pp[i+j+3]&0x8)|(pp[i+j+7]&0x80);
salts[j%saltsz] ^= nv;
}
}
/* Use full password to generate the seed starting value. */
seed = ip[0];
for (i=1; i<plen; i++) {
seed=seed^ip[i];
}
p = ((seed%plen)-1);
}
n = -1;
for (i=0; i<len; i++) {
n = ((n+1)%saltsz);
p++;
if (p>=plen) p=0;
rval=ip[p];
if (saltsz) {
/* At irregular intervals shuffle the salts and seed. */
if (((p+random)%plen) == (seed%plen)) {
random = seed;
seed ^= salts[p%saltsz];
for (j=0; j<saltsz; j++) {
salts[j] = ((salts[j]<<1) | ((salts[j]&0x80) != 0));
}
}
rval = ((ip[p]^salts[n])^seed);
}
c[i] = (ib[i]^rval);
}
if (pp != ppBuf) {
ckfree(pp);
}
return (char *)c;
}
/*
* Xor based symmetric encryption.
* If called with -nosalt or -saltsize 0, fall back to plain old xor.
*/
static int
xorstrcmd(ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]) {
Tcl_Obj *result;
char *ib;
char *ip;
int plen, olen, saltsz=8;
unsigned char *c, cBuf[BUFSIZ+10];
while (1) {
if ( objc>=4 && strcmp("-nosalt", Tcl_GetString(objv[1])) == 0) {
saltsz=0;
objc--;
objv++;
continue;
}
if ( objc>=5 && strcmp("-saltsize", Tcl_GetString(objv[1])) == 0) {
if (Tcl_GetIntFromObj(interp, objv[2], &saltsz) != TCL_OK) {
return TCL_ERROR;
}
if (saltsz<0 || saltsz>256) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("salt <0 or >256 ", -1));
return TCL_ERROR;
}
objc-=2;
objv+=2;
continue;
}
break;
}
if (objc != 3) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"usage: xorcrypt ?-nosalt? ?-saltsize N? password data", -1));
return TCL_ERROR;
}
ip = Tcl_GetStringFromObj(objv[1], &plen);
ib = Tcl_GetByteArrayFromObj(objv[2], &olen);
if (plen<1) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("null password", -1));
return TCL_ERROR;
}
c = saltxorstr(plen, ip, olen, ib, (olen<BUFSIZ?cBuf:NULL), saltsz);
if (c == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("crypt failure", -1));
return TCL_ERROR;
}
result=Tcl_NewByteArrayObj(c, olen);
if (c != cBuf) {
ckfree(c);
}
Tcl_SetObjResult(interp, result);
return TCL_OK;
}
© 2008 Peter MacDonald