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