/*% cc -O -o decryptdb decryptdb.c */ /* The command above should be all you need to install this on a Unix system (using the vendor-supplied library functions setkey and encrypt, defined in Research Unix 7th Edition, BSD 4.3, and SVID.) On some not-quite-Unix systems, or on Unix systems hobbled by US export regulations, these functions may not be available. In that case get Stig Ostholm's DES implementation, available by ftp chalmers.se login: anonymous password: binary cd pub/unix/des get des-2.2.tar.Z quit Install by gzcat des-2.2.tar.Z | tar xf - cd des-2.2/lib make (perhaps after editing makefiles in subdirectories) and finally compile the program below by cc -O -o decryptdb decryptdb.c des/lib/libdes.a If you have trouble with this, or have suggestions for improvements, send email to ehg@research.bell-labs.com. The method is described in @article{siamdb91, author="Joan Feigenbaum and Eric Grosse and James A. Reeds", title="Cryptographic Protection of Membership Lists", year="1992", journal="Newsletter of the International Association for Cryptologic Research", volume="9:1", pages="16-20"} also available from http://cm.bell-labs.com/cm/cs/doc/91/4-12.ps.gz. The database itself is obtained by ftp as follows ftp netlib.bell-labs.com login: anonymous password: binary cd research get siamdb.enc quit Finally, to run the program, say "decryptdb siamdb.enc Grosse". The first argument is a pathname, the second is the search string, which may be either the last name (spelled correctly and properly capitalized) or a telephone number. The membership list protected by this program is also copyrighted by its owning organization. So even if you break through our scheme, you still have the lawyers to contend with. */ /* * The authors of this are Joan Feigenbaum, Eric Grosse, and Jim Reeds. * Copyright (c) 1991 by AT&T. * * Permission to use, copy, modify, and distribute this software for any * purpose without fee is hereby granted, provided that this entire notice * is included in all copies of any software which is or includes a copy * or modification of this software and in all copies of the supporting * documentation for such software. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */ /* * file layout: * * encr_rnd (4 bytes, number of encrypt() rounds) * datstart (4 bytes, addr of first data record) * key records (24 bytes apiece, last 16 encrypted) * data records (each described by one or more key records) * * all numbers are 4 bytes, high byte first */ #define KRECLEN 24 /* length of a keyrecord */ #define KHASH 0 /* offset of hash value */ #define KKEY 8 /* offset of crypto key for data */ #define KPTR 16 /* offset of data address (rel to datstart) */ #define KLEN 20 /* offset of data length */ #define ENC 0 #define DEC 1 #include #ifndef NULL #define NULL 0 #endif extern char *calloc(), *realloc(); long datstart; /* start of data records in file */ FILE *kp; /* to read key parts of file */ FILE *dp; /* to read data parts of file */ unsigned long toc[256]; /* table of contents */ unsigned long encr_rnd; /* number of times to encrypt() */ unsigned long makelong(); unsigned char *hash(); main(argc, argv) char *argv[]; { int i; if(argc<3) error("usage: decrypt_db file searchkey...\n",""); if((kp = fopen(argv[1], "r"))==NULL) error("cannot open %s\n", argv[1]); if((dp = fopen(argv[1], "r"))==NULL) error("cannot re-open %s\n", argv[1]); setup(); for(i=2; i100000 || ptr>100000000) error("hash collision?\n",""); if(dbuf==NULL) dbuf = calloc(1, dlen = len+1); if(len>=dlen) dbuf = realloc(dbuf, dlen = len+1); if(dbuf==NULL) error("mem alloc trouble\n", ""); fseek(dp, (long)datstart+ptr, 0); if(fread(dbuf, 1, len, dp) != len) return 0; dbuf[len] = 0; cipher((unsigned char*)dbuf, len, &krec[KKEY], ENC, 1); fputs(dbuf,stdout); return 1; } /* Some vendors that supply encrypt() allow only the ENC direction, so decryptdb only uses this. */ unsigned long makelong(); unsigned char *hash(); /* Here are a couple functions to crunch the search key into 8 bytes ready for DES. When we used purely DES, there were problems because distinct search keys commonly share a prefix (think about phone numbers of people in a math department). */ unsigned long hashasu(key) char *key; { unsigned long h; h = 0; while (*key != 0) { h = 65599 * h + (unsigned char)*key; key++; } return(h); } unsigned long hashpjw(key) char *key; { unsigned long h; h = 0; while ((unsigned char)*key != 0) { h = (h << 4) + (unsigned char)*key; key++; } return(h); } /* * hash the 'name' string, by using it as key for encryption of 'param'. */ unsigned char * hash(name,param) char *param, *name; { static unsigned char a[8], b[8]; strncpy((char*)a,param,8); nput(hashpjw(name),b); nput(hashasu(name),b+4); cipher(a, 8, b, ENC, encr_rnd); return a; } /* * machine independent repn to native repn */ unsigned long makelong(s) unsigned char *s; { unsigned long val; val = *s++; val = (val << 8) + *s++; val = (val << 8) + *s++; val = (val << 8) + *s; return(val); } /* * native repn to machine independent repn */ nput(val, s) unsigned long val; unsigned char *s; { *s++ = (val>>24)&0xff; *s++ = (val>>16)&0xff; *s++ = (val>>8)&0xff; *s = (val>>0)&0xff; } /* * encrypt n chars at s, using 8-char key8 */ cipher(s, n, key8, edflag, rnds) unsigned char *s, *key8; int rnds; { char *b, block[64], key[64]; int c, i, j, k; if(n&7)error("bad block len to cipher\n",""); s_pre(key8, key); setkey(key); n /= 8; for(i=0; i>7)&1; c += c; } } } /* * lexicographic comparison of 8 unsigned char strings * (don't seem to be in C libe) */ umemcmp(s,t) unsigned char *s, *t; { int i; for(i=0; i<8; i++){ if(*s>*t)return 1; if(*s++<*t++)return -1; } return 0; } /* * bleat and die */ error(s,t) char *s, *t; { fprintf(stderr, s, t); exit(1); }