Hi: DARNOC sent me an interesting program on UNIX salt. The salt is used to permute the expansion function E in DES to prevent the use of most commercially available chips. Using the salt also allows the use of the same password on other accounts without it being obvious, unless the salt is the same. {This practice might be questioned.} I checked the program out on our UNIX system and seems ok. The salt is defined as 12 bits. The remaining 11 characters of the password define the 64 bit hash of the password against a data value of zero. The password field is encoded in asc64 where 0-0x3f is mapped to 0x2e-0x39, 0x41-0x5a, and 0x61-0x6a or (.-9, A-Z, a-z). LANAKI **************************************************************** Greeting, Its great to have you back. I read the first part of lecture 19 and believe you should say more about the use of the salt in the unix password scheme. The salt is used to permute the expansion function E in DES to prevent the use of most (all) commercially available chips. Using the salt also allows the use of the same password on other accounts without it being obvious, unless the salt is the same. I have included a code that will demonstrate unix passwords for you. Please don't attribute this code to me, I found most of it on the net. I did check it against the sun I use and two other unix boxes. Darnoc /* * Show How UNIX crypt works. The first two letters of each * password are the salt. A salt is defined as 12 bits. The other * remaining 11 characters of the password define the 64 bits hash * of the password against a data value of zero. * * The password field is encoded in asc64 where 0-0x3f is mapped to * 0x2e-0x39, 0x41-0x5a, and 0x61-0x6a or (.-9, A-Z, a-z) * * Set the key schedule with the bits from the password. Zero fill * password bytes or truncate back to 8 bytes. * * The salt is used to permute the expansion function E in DES. * If bit 1 of the salt is 1, swap bits 1 and 25 of the 48 bit block * generated by E. If salt bit 2 is 1 swap bits 2 and 26, and so on * for each of the 12 salt bits. * * Now DES encrypt 0 25 times. The answer is our hash. (If you know * the password, you can decrypt to get the orignial 0 data.) * * Test Data * bush:fZ1XesQEjw.jY:2:100:George Bush:/usr/bush:/bin/csh * danq:0cOiQZGxzL3EI:3:100:Dan Quayle:/usr/danq:/bin/csh * conrad;oHyWmy7dMwsMw;1;1;;c:/conrad;c:/dos/command.com * * Compiles with bcc 4.5 */ #include /* * This program implements the * Proposed Federal Information Processing * Data Encryption Standard. * See Federal Register, March 17, 1975 (40FR12134) */ /* * Initial permutation, */ static char IP[] = { 58,50,42,34,26,18,10, 2, 60,52,44,36,28,20,12, 4, 62,54,46,38,30,22,14, 6, 64,56,48,40,32,24,16, 8, 57,49,41,33,25,17, 9, 1, 59,51,43,35,27,19,11, 3, 61,53,45,37,29,21,13, 5, 63,55,47,39,31,23,15, 7, }; /* * Final permutation, FP = IP^(-1) */ static char FP[] = { 40, 8,48,16,56,24,64,32, 39, 7,47,15,55,23,63,31, 38, 6,46,14,54,22,62,30, 37, 5,45,13,53,21,61,29, 36, 4,44,12,52,20,60,28, 35, 3,43,11,51,19,59,27, 34, 2,42,10,50,18,58,26, 33, 1,41, 9,49,17,57,25, }; /* * Permuted-choice 1 from the key bits * to yield C and D. * Note that bits 8,16... are left out: * They are intended for a parity check. */ static char PC1_C[] = { 57,49,41,33,25,17, 9, 1,58,50,42,34,26,18, 10, 2,59,51,43,35,27, 19,11, 3,60,52,44,36, }; static char PC1_D[] = { 63,55,47,39,31,23,15, 7,62,54,46,38,30,22, 14, 6,61,53,45,37,29, 21,13, 5,28,20,12, 4, }; /* * Sequence of shifts used for the key schedule. */ static char shifts[] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1, }; /* * Permuted-choice 2, to pick out the bits from * the CD array that generate the key schedule. */ static char PC2_C[] = { 14,17,11,24, 1, 5, 3,28,15, 6,21,10, 23,19,12, 4,26, 8, 16, 7,27,20,13, 2, }; static char PC2_D[] = { 41,52,31,37,47,55, 30,40,51,45,33,48, 44,49,39,56,34,53, 46,42,50,36,29,32, }; /* * The C and D arrays used to calculate the key schedule. */ static char C[28]; static char D[28]; /* * The key schedule. * Generated from the key. */ static char KS[16][48]; /* * Set up the key schedule from the key. */ void setkey(char *key) { register i, j, k; int t; /* * First, generate C and D by permuting * the key. The low order bit of each * 8-bit char is not used, so C and D are only 28 * bits apiece. */ for (i=0; i<28; i++) { C[i] = key[PC1_C[i]-1]; D[i] = key[PC1_D[i]-1]; } /* * To generate Ki, rotate C and D according * to schedule and pick up a permutation * using PC2. */ for (i=0; i<16; i++) { /* * rotate. */ for (k=0; k>3)&01; f[t+1] = (k>>2)&01; f[t+2] = (k>>1)&01; f[t+3] = (k>>0)&01; } /* * The new R is L ^ f(R, K). * The f here has to be permuted first, though. */ for (j=0; j<32; j++) R[j] = L[j] ^ f[P[j]-1]; /* * Finally, the new L (the original R) * is copied back. */ for (j=0; j<32; j++) L[j] = tempL[j]; } /* * The output L and R are reversed. */ for (j=0; j<32; j++) { t = L[j]; L[j] = R[j]; R[j] = t; } /* * The final output * gets the inverse permutation of the very original. */ for (j=0; j<64; j++) block[j] = L[FP[j]-1]; } char *crypt(char *pw, char *salt) { register i, j, c; int temp; static char block[66], iobuf[16]; for(i=0; i<66; i++) block[i] = 0; for(i=0; (c= *pw) && i<64; pw++) { for(j=0; j<7; j++, i++) block[i] = (c>>(6-j)) & 01; i++; } setkey(block); for(i=0; i<66; i++) block[i] = 0; for(i=0;i<48;i++) E[i] = e[i]; for(i=0;i<2;i++) { c = *salt++; iobuf[i] = c; if(c>'Z') c -= 6; if(c>'9') c -= 7; c -= '.'; for(j=0;j<6;j++) { if((c>>j) & 01) { temp = E[6*i+j]; E[6*i+j] = E[6*i+j+24]; E[6*i+j+24] = temp; } } } for(i=0; i<25; i++) encrypt(block,0); for(i=0; i<11; i++) { c = 0; for(j=0; j<6; j++) { c <<= 1; c |= block[6*i+j]; } c += '.'; if(c>'9') c += 7; if(c>'Z') c += 6; iobuf[i+2] = c; } iobuf[i+2] = 0; if(iobuf[1]==0) iobuf[1] = iobuf[0]; return(iobuf); } void main(void) { int i; char *salt1 = "0c"; char *pwd1 = "marilyn"; char *ans1 = "danq:0cOiQZGxzL3EI:3:100:Dan Quayle:/usr/danq:/bin/csh"; char *salt2 = "fZ"; char *pwd2 = "barbara"; char *ans2 = "bush:fZ1XesQEjw.jY:2:100:George Bush:/usr/bush:/bin/csh"; char *salt3 = "oH"; char *pwd3 = "schlundt"; char *ans3 = "conrad;oHyWmy7dMwsMw;1;1;;c:/conrad;c:/dos/command.com"; char *sp; sp = crypt(pwd1, salt1); for (i = 0; i < 13; ++i) printf("%c", sp[i]); printf("\n%s\n\n", ans1); sp = crypt(pwd2, salt2); for (i = 0; i < 13; ++i) printf("%c", sp[i]); printf("\n%s\n\n", ans2); sp = crypt(pwd3, salt3); for (i = 0; i < 13; ++i) printf("%c", sp[i]); printf("\n%s\n\n", ans3); } Distribution: To: [75542,1003]