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