BSD 3 development
[unix-history] / usr / src / cmd / net / nbs.c
CommitLineData
91978b44
ES
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*/
34char *deblknot(), *deblkclr();
35char *nbs8decrypt(), *nbs8encrypt();
36static char E[48];
37char e[];
38char *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 }
54char *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/*
74testing(){
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
114char *nbs8encrypt(str,key)
115register 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}
128char *nbs8decrypt(crp,key)
129register 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}
142enblkclr(blk,str) /* ignores top bit of chars in string str */
143char *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 }
153char *deblkclr(blk)
154char *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 }
169enblknot(blk,crp)
170char *blk;
171char *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 }
183char *deblknot(blk)
184char *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 */
212static 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 */
226static 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 */
243static 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
250static 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*/
260static 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 */
268static 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
275static 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
286static char C[28];
287static char D[28];
288/*
289 * The key schedule.
290 * Generated from the key.
291 */
292static char KS[16][48];
293
294/*
295 * Set up the key schedule from the key.
296 */
297
298nbssetkey(key)
299char *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 */
346static 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 */
362static 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 */
408static 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 */
422static char L[32], R[32];
423static char tempL[32];
424static char f[32];
425
426/*
427 * The combination of the key and the input, before selection.
428 */
429static char preS[48];
430
431/*
432 * The payoff: encrypt a block.
433 */
434
435blkencrypt(block, edflag)
436char *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}