|
|
1.1 ! root 1: static char sccsid[] = "@(#)nbs.c 4.1 (Berkeley) 9/12/82"; ! 2: ! 3: # include <stdio.h> ! 4: /* sccs id variable */ ! 5: static char *nbs_sid = "@(#)nbs.c 1.2"; ! 6: ! 7: /* file nbs.c ! 8: This file has the necessary procedures to use the NBS algorithm ! 9: to encrypt and decrypt strings of arbitrary length. ! 10: ! 11: Basically ! 12: ! 13: ciphertext = nbsencrypt(cleartext,secretkey,ciphertext); ! 14: ! 15: yields a string ciphertext from string cleartext using ! 16: the secret string secretkey. ! 17: Then ! 18: ! 19: cleartext = nbsdecrypt(ciphertext,secretkey,cleartext); ! 20: ! 21: yields the original string cleartext IF the string secretkey ! 22: is the same for both calls. ! 23: The third parameter is filled with the result of the call- ! 24: it must be (11/8)*size(firstarg). ! 25: The first and third areguments must be different. ! 26: The cleartext must be ASCII - the top eighth bit is ignored, ! 27: so binary data won't work. ! 28: The plaintext is broken into 8 character sections, ! 29: encrypted, and concatenated separated by $'s to make the ciphertext. ! 30: The first 8 letter section uses the secretkey, subsequent ! 31: sections use the cleartext of the previous section as ! 32: the key. ! 33: Thus the ciphertext depends on itself, except for ! 34: the first section, which depends on the key. ! 35: This means that sections of the ciphertext, except the first, ! 36: may not stand alone. ! 37: Only the first 8 characters of the key matter. ! 38: */ ! 39: char *deblknot(), *deblkclr(); ! 40: char *nbs8decrypt(), *nbs8encrypt(); ! 41: static char E[48]; ! 42: char e[]; ! 43: char *nbsencrypt(str,key,result) ! 44: char *result; ! 45: char *str, *key; { ! 46: static char buf[20],oldbuf[20]; ! 47: register int j; ! 48: result[0] = 0; ! 49: strcpy(oldbuf,key); ! 50: while(*str){ ! 51: for(j=0;j<10;j++)buf[j] = 0; ! 52: for(j=0;j<8 && *str;j++)buf[j] = *str++; ! 53: strcat(result,nbs8encrypt(buf,oldbuf)); ! 54: strcat(result,"$"); ! 55: strcpy(oldbuf,buf); ! 56: } ! 57: return(result); ! 58: } ! 59: char *nbsdecrypt(cpt,key,result) ! 60: char *result; ! 61: char *cpt,*key; { ! 62: char *s; ! 63: char c,oldbuf[20]; ! 64: result[0] = 0; ! 65: strcpy(oldbuf,key); ! 66: while(*cpt){ ! 67: for(s = cpt;*s && *s != '$';s++); ! 68: c = *s; ! 69: *s = 0; ! 70: strcpy(oldbuf,nbs8decrypt(cpt,oldbuf)); ! 71: strcat(result,oldbuf); ! 72: if(c == 0)break; ! 73: cpt = s + 1; ! 74: } ! 75: return(result); ! 76: } ! 77: /* make key to be sent across the network */ ! 78: makeuukey(skey,sn,mch) ! 79: char *skey, *sn, mch; ! 80: { ! 81: skey[0] = mch; ! 82: skey[1] = 0; ! 83: strcat(skey,sn); ! 84: } ! 85: ! 86: /* all other calls are private */ ! 87: /* ! 88: char _sobuf[BUFSIZ]; ! 89: testing(){ ! 90: static char res[BUFSIZ]; ! 91: char *s; ! 92: char str[BUFSIZ]; ! 93: setbuf(stdout,_sobuf); ! 94: while(!feof(stdin)){ ! 95: fprintf(stderr,"String:\n"); ! 96: fgets(str,BUFSIZ,stdin); ! 97: if(feof(stdin))break; ! 98: strcat(str,"\n"); ! 99: s = nbsencrypt(str,"hellothere",res); ! 100: fprintf(stderr,"encrypted:\n%s\n",s); ! 101: fprintf(stderr,"decrypted:\n"); ! 102: printf("%s",nbsdecrypt(s,"hellothere",str)); ! 103: fprintf(stderr,"\n"); ! 104: } ! 105: } ! 106: */ ! 107: /* ! 108: To encrypt: ! 109: The first level of call splits the input strings into strings ! 110: no longer than 8 characters, for encryption. ! 111: Then the encryption of 8 characters breaks all but the top bit ! 112: of each character into a 64-character block, each character ! 113: with 1 or 0 corresponding to binary. ! 114: The key is set likewise. ! 115: The encrypted form is then converted, 6 bits at a time, ! 116: into an ASCII string. ! 117: ! 118: To decrypt: ! 119: We take the result of the encryption, 6 significant bits ! 120: per character, and convert it to the block(64-char) fmt. ! 121: This is decrypted by running the nbs algorithm in reverse, ! 122: and transformed back into 7bit ASCII. ! 123: ! 124: The subroutines to do ASCII blocking and deblocking ! 125: are .....clr and the funny 6-bit code are .....not. ! 126: ! 127: */ ! 128: ! 129: char *nbs8encrypt(str,key) ! 130: char *str, *key; { ! 131: static char keyblk[100], blk[100]; ! 132: register int i; ! 133: ! 134: enblkclr(keyblk,key); ! 135: nbssetkey(keyblk); ! 136: ! 137: for(i=0;i<48;i++) E[i] = e[i]; ! 138: enblkclr(blk,str); ! 139: blkencrypt(blk,0); /* forward dir */ ! 140: ! 141: return(deblknot(blk)); ! 142: } ! 143: char *nbs8decrypt(crp,key) ! 144: char *crp, *key; { ! 145: static char keyblk[100], blk[100]; ! 146: register int i; ! 147: ! 148: enblkclr(keyblk,key); ! 149: nbssetkey(keyblk); ! 150: ! 151: for(i=0;i<48;i++) E[i] = e[i]; ! 152: enblknot(blk,crp); ! 153: blkencrypt(blk,1); /* backward dir */ ! 154: ! 155: return(deblkclr(blk)); ! 156: } ! 157: enblkclr(blk,str) /* ignores top bit of chars in string str */ ! 158: char *blk,*str; { ! 159: register int i,j; ! 160: char c; ! 161: for(i=0;i<70;i++)blk[i] = 0; ! 162: for(i=0; (c= *str) && i<64; str++){ ! 163: for(j=0; j<7; j++, i++) ! 164: blk[i] = (c>>(6-j)) & 01; ! 165: i++; ! 166: } ! 167: } ! 168: char *deblkclr(blk) ! 169: char *blk; { ! 170: register int i,j; ! 171: char c; ! 172: static char iobuf[30]; ! 173: for(i=0; i<10; i++){ ! 174: c = 0; ! 175: for(j=0; j<7; j++){ ! 176: c <<= 1; ! 177: c |= blk[8*i+j]; ! 178: } ! 179: iobuf[i] = c; ! 180: } ! 181: iobuf[i] = 0; ! 182: return(iobuf); ! 183: } ! 184: enblknot(blk,crp) ! 185: char *blk; ! 186: char *crp; { ! 187: register int i,j; ! 188: char c; ! 189: for(i=0;i<70;i++)blk[i] = 0; ! 190: for(i=0; (c= *crp) && i<64; crp++){ ! 191: if(c>'Z') c -= 6; ! 192: if(c>'9') c -= 7; ! 193: c -= '.'; ! 194: for(j=0; j<6; j++, i++) ! 195: blk[i] = (c>>(5-j)) & 01; ! 196: } ! 197: } ! 198: char *deblknot(blk) ! 199: char *blk; { ! 200: register int i,j; ! 201: char c; ! 202: static char iobuf[30]; ! 203: for(i=0; i<11; i++){ ! 204: c = 0; ! 205: for(j=0; j<6; j++){ ! 206: c <<= 1; ! 207: c |= blk[6*i+j]; ! 208: } ! 209: c += '.'; ! 210: if(c > '9')c += 7; ! 211: if(c > 'Z')c += 6; ! 212: iobuf[i] = c; ! 213: } ! 214: iobuf[i] = 0; ! 215: return(iobuf); ! 216: } ! 217: /* ! 218: * This program implements the ! 219: * Proposed Federal Information Processing ! 220: * Data Encryption Standard. ! 221: * See Federal Register, March 17, 1975 (40FR12134) ! 222: */ ! 223: ! 224: /* ! 225: * Initial permutation, ! 226: */ ! 227: static char IP[] = { ! 228: 58,50,42,34,26,18,10, 2, ! 229: 60,52,44,36,28,20,12, 4, ! 230: 62,54,46,38,30,22,14, 6, ! 231: 64,56,48,40,32,24,16, 8, ! 232: 57,49,41,33,25,17, 9, 1, ! 233: 59,51,43,35,27,19,11, 3, ! 234: 61,53,45,37,29,21,13, 5, ! 235: 63,55,47,39,31,23,15, 7, ! 236: }; ! 237: ! 238: /* ! 239: * Final permutation, FP = IP^(-1) ! 240: */ ! 241: static char FP[] = { ! 242: 40, 8,48,16,56,24,64,32, ! 243: 39, 7,47,15,55,23,63,31, ! 244: 38, 6,46,14,54,22,62,30, ! 245: 37, 5,45,13,53,21,61,29, ! 246: 36, 4,44,12,52,20,60,28, ! 247: 35, 3,43,11,51,19,59,27, ! 248: 34, 2,42,10,50,18,58,26, ! 249: 33, 1,41, 9,49,17,57,25, ! 250: }; ! 251: ! 252: /* ! 253: * Permuted-choice 1 from the key bits ! 254: * to yield C and D. ! 255: * Note that bits 8,16... are left out: ! 256: * They are intended for a parity check. ! 257: */ ! 258: static char PC1_C[] = { ! 259: 57,49,41,33,25,17, 9, ! 260: 1,58,50,42,34,26,18, ! 261: 10, 2,59,51,43,35,27, ! 262: 19,11, 3,60,52,44,36, ! 263: }; ! 264: ! 265: static char PC1_D[] = { ! 266: 63,55,47,39,31,23,15, ! 267: 7,62,54,46,38,30,22, ! 268: 14, 6,61,53,45,37,29, ! 269: 21,13, 5,28,20,12, 4, ! 270: }; ! 271: ! 272: /* ! 273: * Sequence of shifts used for the key schedule. ! 274: */ ! 275: static char shifts[] = { ! 276: 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1, ! 277: }; ! 278: ! 279: /* ! 280: * Permuted-choice 2, to pick out the bits from ! 281: * the CD array that generate the key schedule. ! 282: */ ! 283: static char PC2_C[] = { ! 284: 14,17,11,24, 1, 5, ! 285: 3,28,15, 6,21,10, ! 286: 23,19,12, 4,26, 8, ! 287: 16, 7,27,20,13, 2, ! 288: }; ! 289: ! 290: static char PC2_D[] = { ! 291: 41,52,31,37,47,55, ! 292: 30,40,51,45,33,48, ! 293: 44,49,39,56,34,53, ! 294: 46,42,50,36,29,32, ! 295: }; ! 296: ! 297: /* ! 298: * The C and D arrays used to calculate the key schedule. ! 299: */ ! 300: ! 301: static char C[28]; ! 302: static char D[28]; ! 303: /* ! 304: * The key schedule. ! 305: * Generated from the key. ! 306: */ ! 307: static char KS[16][48]; ! 308: ! 309: /* ! 310: * Set up the key schedule from the key. ! 311: */ ! 312: ! 313: nbssetkey(key) ! 314: char *key; ! 315: { ! 316: register i, j, k; ! 317: int t; ! 318: ! 319: /* ! 320: * First, generate C and D by permuting ! 321: * the key. The low order bit of each ! 322: * 8-bit char is not used, so C and D are only 28 ! 323: * bits apiece. ! 324: */ ! 325: for (i=0; i<28; i++) { ! 326: C[i] = key[PC1_C[i]-1]; ! 327: D[i] = key[PC1_D[i]-1]; ! 328: } ! 329: /* ! 330: * To generate Ki, rotate C and D according ! 331: * to schedule and pick up a permutation ! 332: * using PC2. ! 333: */ ! 334: for (i=0; i<16; i++) { ! 335: /* ! 336: * rotate. ! 337: */ ! 338: for (k=0; k<shifts[i]; k++) { ! 339: t = C[0]; ! 340: for (j=0; j<28-1; j++) ! 341: C[j] = C[j+1]; ! 342: C[27] = t; ! 343: t = D[0]; ! 344: for (j=0; j<28-1; j++) ! 345: D[j] = D[j+1]; ! 346: D[27] = t; ! 347: } ! 348: /* ! 349: * get Ki. Note C and D are concatenated. ! 350: */ ! 351: for (j=0; j<24; j++) { ! 352: KS[i][j] = C[PC2_C[j]-1]; ! 353: KS[i][j+24] = D[PC2_D[j]-28-1]; ! 354: } ! 355: } ! 356: } ! 357: ! 358: /* ! 359: * The E bit-selection table. ! 360: */ ! 361: static char e[] = { ! 362: 32, 1, 2, 3, 4, 5, ! 363: 4, 5, 6, 7, 8, 9, ! 364: 8, 9,10,11,12,13, ! 365: 12,13,14,15,16,17, ! 366: 16,17,18,19,20,21, ! 367: 20,21,22,23,24,25, ! 368: 24,25,26,27,28,29, ! 369: 28,29,30,31,32, 1, ! 370: }; ! 371: ! 372: /* ! 373: * The 8 selection functions. ! 374: * For some reason, they give a 0-origin ! 375: * index, unlike everything else. ! 376: */ ! 377: static char S[8][64] = { ! 378: 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7, ! 379: 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8, ! 380: 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0, ! 381: 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13, ! 382: ! 383: 15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10, ! 384: 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5, ! 385: 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15, ! 386: 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9, ! 387: ! 388: 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8, ! 389: 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1, ! 390: 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7, ! 391: 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12, ! 392: ! 393: 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15, ! 394: 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9, ! 395: 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4, ! 396: 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14, ! 397: ! 398: 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9, ! 399: 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6, ! 400: 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14, ! 401: 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3, ! 402: ! 403: 12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11, ! 404: 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8, ! 405: 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6, ! 406: 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13, ! 407: ! 408: 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1, ! 409: 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6, ! 410: 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2, ! 411: 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12, ! 412: ! 413: 13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7, ! 414: 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2, ! 415: 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8, ! 416: 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11, ! 417: }; ! 418: ! 419: /* ! 420: * P is a permutation on the selected combination ! 421: * of the current L and key. ! 422: */ ! 423: static char P[] = { ! 424: 16, 7,20,21, ! 425: 29,12,28,17, ! 426: 1,15,23,26, ! 427: 5,18,31,10, ! 428: 2, 8,24,14, ! 429: 32,27, 3, 9, ! 430: 19,13,30, 6, ! 431: 22,11, 4,25, ! 432: }; ! 433: ! 434: /* ! 435: * The current block, divided into 2 halves. ! 436: */ ! 437: static char L[32], R[32]; ! 438: static char tempL[32]; ! 439: static char f[32]; ! 440: ! 441: /* ! 442: * The combination of the key and the input, before selection. ! 443: */ ! 444: static char preS[48]; ! 445: ! 446: /* ! 447: * The payoff: encrypt a block. ! 448: */ ! 449: ! 450: blkencrypt(block, edflag) ! 451: char *block; ! 452: { ! 453: int i, ii; ! 454: register t, j, k; ! 455: ! 456: /* ! 457: * First, permute the bits in the input ! 458: */ ! 459: for (j=0; j<64; j++) ! 460: L[j] = block[IP[j]-1]; ! 461: /* ! 462: * Perform an encryption operation 16 times. ! 463: */ ! 464: for (ii=0; ii<16; ii++) { ! 465: /* ! 466: * Set direction ! 467: */ ! 468: if (edflag) ! 469: i = 15-ii; ! 470: else ! 471: i = ii; ! 472: /* ! 473: * Save the R array, ! 474: * which will be the new L. ! 475: */ ! 476: for (j=0; j<32; j++) ! 477: tempL[j] = R[j]; ! 478: /* ! 479: * Expand R to 48 bits using the E selector; ! 480: * exclusive-or with the current key bits. ! 481: */ ! 482: for (j=0; j<48; j++) ! 483: preS[j] = R[E[j]-1] ^ KS[i][j]; ! 484: /* ! 485: * The pre-select bits are now considered ! 486: * in 8 groups of 6 bits each. ! 487: * The 8 selection functions map these ! 488: * 6-bit quantities into 4-bit quantities ! 489: * and the results permuted ! 490: * to make an f(R, K). ! 491: * The indexing into the selection functions ! 492: * is peculiar; it could be simplified by ! 493: * rewriting the tables. ! 494: */ ! 495: for (j=0; j<8; j++) { ! 496: t = 6*j; ! 497: k = S[j][(preS[t+0]<<5)+ ! 498: (preS[t+1]<<3)+ ! 499: (preS[t+2]<<2)+ ! 500: (preS[t+3]<<1)+ ! 501: (preS[t+4]<<0)+ ! 502: (preS[t+5]<<4)]; ! 503: t = 4*j; ! 504: f[t+0] = (k>>3)&01; ! 505: f[t+1] = (k>>2)&01; ! 506: f[t+2] = (k>>1)&01; ! 507: f[t+3] = (k>>0)&01; ! 508: } ! 509: /* ! 510: * The new R is L ^ f(R, K). ! 511: * The f here has to be permuted first, though. ! 512: */ ! 513: for (j=0; j<32; j++) ! 514: R[j] = L[j] ^ f[P[j]-1]; ! 515: /* ! 516: * Finally, the new L (the original R) ! 517: * is copied back. ! 518: */ ! 519: for (j=0; j<32; j++) ! 520: L[j] = tempL[j]; ! 521: } ! 522: /* ! 523: * The output L and R are reversed. ! 524: */ ! 525: for (j=0; j<32; j++) { ! 526: t = L[j]; ! 527: L[j] = R[j]; ! 528: R[j] = t; ! 529: } ! 530: /* ! 531: * The final output ! 532: * gets the inverse permutation of the very original. ! 533: */ ! 534: for (j=0; j<64; j++) ! 535: block[j] = L[FP[j]-1]; ! 536: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.