This file has the necessary procedures to use the NBS algorithm
to encrypt and decrypt strings of arbitrary length.
ciphertext = nbsencrypt(cleartext,secretkey,ciphertext);
yields a string ciphertext from string cleartext using
the secret string secretkey.
cleartext = nbsdecrypt(ciphertext,secretkey,cleartext);
yields the original string cleartext IF the string secretkey
is the same for both calls.
The third parameter is filled with the result of the call-
it must be (11/8)*size(firstarg).
The first and third areguments must be different.
The cleartext must be ASCII - the top eighth bit is ignored,
so binary data won't work.
The plaintext is broken into 8 character sections,
encrypted, and concatenated separated by $'s to make the ciphertext.
The first 8 letter section uses the secretkey, subsequent
sections use the cleartext of the previous section as
Thus the ciphertext depends on itself, except for
the first section, which depends on the key.
This means that sections of the ciphertext, except the first,
Only the first 8 characters of the key matter.
char *deblknot(), *deblkclr();
char *nbs8decrypt(), *nbs8encrypt();
char *nbsencrypt(str
,key
,result
)
register char *str
, *key
; {
static char buf
[20],oldbuf
[20];
for(j
=0;j
<10;j
++)buf
[j
] = 0;
for(j
=0;j
<8 && *str
;j
++)buf
[j
] = *str
++;
strcat(result
,nbs8encrypt(buf
,oldbuf
));
char *nbsdecrypt(cpt
,key
,result
)
register char *cpt
,*key
; {
for(s
= cpt
;*s
&& *s
!= '$';s
++);
strcpy(oldbuf
,nbs8decrypt(cpt
,oldbuf
));
/* all other calls are private */
static char stbuf[BUFSIZ],res[BUFSIZ];
fprintf(stderr,"String:\n");
s = nbsencrypt(str,"hellothere",res);
fprintf(stderr,"encrypted:\n%s\n",s);
fprintf(stderr,"decrypted:\n");
printf("%s",nbsdecrypt(s,"hellothere",str));
The first level of call splits the input strings into strings
no longer than 8 characters, for encryption.
Then the encryption of 8 characters breaks all but the top bit
of each character into a 64-character block, each character
with 1 or 0 corresponding to binary.
The encrypted form is then converted, 6 bits at a time,
We take the result of the encryption, 6 significant bits
per character, and convert it to the block(64-char) fmt.
This is decrypted by running the nbs algorithm in reverse,
and transformed back into 7bit ASCII.
The subroutines to do ASCII blocking and deblocking
are .....clr and the funny 6-bit code are .....not.
char *nbs8encrypt(str
,key
)
register char *str
, *key
; {
static char keyblk
[100], blk
[100];
for(i
=0;i
<48;i
++) E
[i
] = e
[i
];
blkencrypt(blk
,0); /* forward dir */
char *nbs8decrypt(crp
,key
)
register char *crp
, *key
; {
static char keyblk
[100], blk
[100];
for(i
=0;i
<48;i
++) E
[i
] = e
[i
];
blkencrypt(blk
,1); /* backward dir */
enblkclr(blk
,str
) /* ignores top bit of chars in string str */
for(i
=0;i
<70;i
++)blk
[i
] = 0;
for(i
=0; (c
= *str
) && i
<64; str
++){
blk
[i
] = (c
>>(6-j
)) & 01;
for(i
=0;i
<70;i
++)blk
[i
] = 0;
for(i
=0; (c
= *crp
) && i
<64; crp
++){
blk
[i
] = (c
>>(5-j
)) & 01;
* This program implements the
* Proposed Federal Information Processing
* Data Encryption Standard.
* See Federal Register, March 17, 1975 (40FR12134)
* Final permutation, FP = IP^(-1)
* Permuted-choice 1 from the key bits
* Note that bits 8,16... are left out:
* They are intended for a parity check.
* Sequence of shifts used for the key schedule.
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.
* The C and D arrays used to calculate the key schedule.
* Generated from the key.
* Set up the key schedule from the key.
* 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
* To generate Ki, rotate C and D according
* to schedule and pick up a permutation
for (k
=0; k
<shifts
[i
]; k
++) {
* get Ki. Note C and D are concatenated.
KS
[i
][j
] = C
[PC2_C
[j
]-1];
KS
[i
][j
+24] = D
[PC2_D
[j
]-28-1];
* The E bit-selection table.
* The 8 selection functions.
* For some reason, they give a 0-origin
* index, unlike everything else.
14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
* P is a permutation on the selected combination
* of the current L and key.
* The current block, divided into 2 halves.
static char L
[32], R
[32];
* The combination of the key and the input, before selection.
* The payoff: encrypt a block.
blkencrypt(block
, edflag
)
* First, permute the bits in the input
* Perform an encryption operation 16 times.
for (ii
=0; ii
<16; ii
++) {
* which will be the new L.
* Expand R to 48 bits using the E selector;
* exclusive-or with the current key bits.
preS
[j
] = R
[E
[j
]-1] ^ KS
[i
][j
];
* The pre-select bits are now considered
* in 8 groups of 6 bits each.
* The 8 selection functions map these
* 6-bit quantities into 4-bit quantities
* and the results permuted
* The indexing into the selection functions
* is peculiar; it could be simplified by
* The new R is L ^ f(R, K).
* The f here has to be permuted first, though.
* Finally, the new L (the original R)
* The output L and R are reversed.
* gets the inverse permutation of the very original.