PRECOMPUTING DES KEY SCHEDULES FOR QUICK ACCESS
TO ENCRYPTED DATABASES
BACKGROUND OF THE INVENTION
The present invention relates to encryption and decryption of data in databases. More particularly, the present invention relates to efficient handling of accesses to encrypted databases to allow for quick responses to the accesses.
Data is stored in encrypted form to prevent access to the data. Typically, the data is created in a form known as "plaintext" because the data is plainly available and the data is converted to a form known as "ciphertext" that is not readily usable. The process of converting from plaintext to ciphertext is known as "encrypting" and the process of converting from ciphertext to plaintext is known as "decrypting". For effective encryption of data, the decryption should be such that it can only be done with a process that has knowledge of a key.
In theory, with enough time and enough computing power, nearly all ciphertext can be decrypted without the key, but in practice the time needed could be in the billions of years and the computing power needed could require all the molecules in the known universe. Therefore, being unable to decrypt without the key is generally assumed to mean being unable to decrypt without the key in less time than some amount of time and less computing power than some level of computing power. Of course, with suitable selection of the minimum amount of time and the minimum amount of computing power, it could be said that data cannot be decrypted without the key by anyone of concern to the encryptor. For example, if a financial transaction is encrypted and an assailant can steal up to one hundred dollars upon decrypting the message, the difference between being unable to decrypt the message and being unable to encrypt the message with less expense than ten thousand dollars, the encryptor does not care about the difference. Likewise, if a military secret is encrypted during a battle, the encryptor does not likely care whether the message is undecryptable without a key or is undecryptable without a key in less than two hundred years.
Some encryption systems use symmetric keys, where the same key is used to encrypt and decrypt. Other encryption systems use asymmetric keys, where the
2 encryption key and decryption key is different. One common symmetric key encryption system is the Data Encryption Standard (DES). DES is described in FTPS Publication 46-2, "Data Encryption Standard", dated December 30, 1993 and incorporated by reference herein for all purposes. That reference is available from the National Technical Information Service of the U.S. Department of Commerce (http://www.nist.gov), among other sources. Many hardware devices and software programs exist that encrypt and decrypt data using DES.
In DES, data is encrypted and decrypted in blocks. Because of the symmetry of the DES process, if the input block is plaintext the output block is ciphertext and if the ciphertext is provided as the input to the DES process with the same key the output block is the original plaintext. The size of the input and output blocks is eight bytes and the key is 64 bits. Thus, if an eight-byte block of plaintext and a 64-bit key are provided to an encryptor, an eight-byte block of ciphertext results. If the eight-byte block of ciphertext and the same key were provided to a decryptor, the decryptor would output the original eight-byte block of plaintext. Where more than eight bytes of data are to be encrypted or decrypted in one operation, a larger block of input data might be provided to the DES process, with the DES process internally dividing up the input data into eight-byte blocks, padding as necessary.
A process for encrypting/decrypting a block of plaintext/ciphertext is shown in Fig. 1. As shown in Fig. 1 , the inputs to a DES processor are an input block and a key. Following an initialization step, the input block is permuted, sixteen "rounds" of iteration are performed, and the input block is again permuted to arrive at the output block. In each round of the iteration, the result from the previous round (or the result of the first permutation, in the case of the first round) is combined with a 48-bit subkey using a cipher function f(R,Ki), where R is the right half of the input block from the previous round and Ki is the subkey for the z'-th round. The sixteen subkeys (one per round) are collectively referred to as the key schedule. An appendix to the DES standard shows how to calculate a given subkey from the key.
In a hardware implementation, a special purpose circuit might be included just to calculate the key schedule from the key upon request from an iteration process. In a software implementation, a processor might execute program code for generating the key schedule. In a typical DES process, an input block of eight-bytes and a key is passed to the process. Where an encryption step processes more than eight-bytes at once, the
input block is divided into eight-byte blocks and each is encrypted in turn, with padding added as needed. In some cases, where the DES process is passed more than eight bytes of data for an encrypt or decrypt operation, the key schedule might be generated once for , that operation. Where sufficiently fast hardware is available, or enough time is available for software processing, DES operations can be done in a straightforward manner given an input block and a key. However, where DES operations must be more efficient, faster methods are needed.
SUMMARY OF THE INVENTION In one embodiment of a database management system according to the present invention, data is stored in an encrypted form, encrypted using an encryption routine such as DES using a key that is common to large numbers of data blocks. When a database is opened, operations and calculations needed for encryption that are independent of the data are performed and the key schedule that results is saved in a memory or other data storage element. When data is accessed and needs to be encrypted (typically for a write operation) or decrypted (typically for a read operation), the data is encrypted or decrypted using the key schedule. The data is then quickly encrypted or decrypted using the key schedule. This allows the encryption or decryption process to run much faster, as much as five or more times faster, than if the key schedule is calculated each time data is encrypted or decrypted. When the database is closed for access, the key schedule is deleted.
A further underst.anding of the nature and advantages of the inventions herein may be realized by reference to the remaining portions of the specification and the attached drawings.
BRIEF DESCRIPTION OF THE DRAWTNGS
Fig. 1 is a block diagram illustrating a standard DES encryption/decryption process.
Fig. 2 is a block diagram illustrating the elements of a system for encrypting and decrypting data in a database according to one embodiment of an encoding system according to the present invention.
4 Fig. 3 is a flowchart of a key schedule generation process according to one embodiment of the present invention.
A source code appendix is appended to the present specification. That source code appendix is a listing of a program named "dessrc.c", which is a C program implementing an encryption/decryption process described herein.
DESCRIPTION OF THE SPECIFIC EMBODIMENTS Fig. 2 is a block diagram illustrating the elements of a system for encrypting and decrypting data in a database according to one embodiment of an encoding system according to the present invention. As shown there, a database management system (DBMS) 102 accepts queries and responds to those queries with data from a database 104. Since the data in database 104 is encrypted with a database key, data read from database 104 should be decrypted before providing a response to a query and data written to database 104 should be encrypted before storing the data in database 104. DBMS 102 is shown including an input output (I/O) section 106, which handles queries and responses. I/O section 106 also handles the process of quickly passing data through an encoder/decoder 110. I/O section 106 provides and input block to encoder/decoder 110 and encoder/decoder 110 returns an output block. Where data is being written into database 104, the input blocks are plaintext (more likely in binary, rather than text, form) and the output blocks are the ciphertext to be written into database 104 and encoder/decoder 110 operates as an encoder. Where data is being read from database 104, the input blocks are ciphertext and the output blocks are plaintext to be provided by DBMS 102 and encoder/decoder 110 operates as a decoder.
Encoder/decoder 110 operates on the input block according to the DES input permutation, iteration, and output permutation processes, using a key schedule, KS, stored in key schedule storage 112. In the preferred embodiment, each page of data in database 104 is encrypted using the same key and key schedule KS is calculated once per database access "session" with database 104. Here, a session refers to the period between a "open" on the database and a "close" on the database. Preferably, for security reasons, DBMS 102 erases and forgets the database key and the key schedule KS once a database session is over and the database is closed for access.
When DBMS 102 receives a request to open a database for access, if the database is an encrypted database, the request should include a database key for use with
that encrypted database. When such a request is received, DBMS 102 stores the key in a key storage 120 and triggers a schedule generator 122 to generate key schedule KS from that key. In some secure embodiments, the key is deleted from key storage 120 once the key schedule is generated. Schedule generator 122 operates according to the flowchart shown in Fig.
3 to generate a key schedule KS from a key K. Source code for the function desSetKey(key) is shown in the Appendix. That function is a specific implementation of the schedule generator. Schedule generator 122 operates on a 56-bit key stored in key storage 120 and the resulting key schedule is a set of sixteen 56-bit values. As shown in Fig. 3, schedule generator 122 inputs a 64-bit DES key, stπps off the eight parity bits and uses the PCI table defined in the DES standard to generate choices. Those choices are then shifted to generate intermediate subvalues C and D for each iteration and those C and D values are permuted using the PC2 table defined by the DES standard to generate the key schedule KS. A system for efficiently encrypting and decrypting data has now been described. Such a system can be used in connection with database access. A database might contain gigabytes of data, stored as a plurality of pages. As many pages need to be encrypted and decrypted from time to time, where the pages are all encrypted using the same key, precomputing the key schedule for use in encrypting and decrypting many pages saves considerable computation effort and time. Precomputing the key schedule once for the initial encryption of a large database also saves computational effort and makes the creation of the encrypted database much faster than if the key schedule is generated for each encryption operation.
When a database is encrypted on the storage medium where it is stored, data must be decrypted each time the data is referenced, searched, retrieved or otherwise used. Consequently, any given page in the plurality of database pages might be decrypted many times during the operation of an application that is using the database. When the pages of the database are all encrypted using the same key, precomputing the key schedule saves substantial time and speeds access to information stored in the encrypted database. Similarly, much time is saved in the encryption process each time data is written to the database.
The above description is illustrative and not restrictive. Many variations of the invention will become apparent to those of skill in the art upon review of this
disclosure. The scope of the invention should, therefore, be determined not with reference to the above description, but instead should be determined with reference to the appended claims along with their full scope of equivalents.
APPENDIX Source code listing for dessrc.c
/*
EXTERNAL INTERFACE FUNCTION
Library supporting the NBS Data Encryption Standard (DES) DESCRIPTION
The following functions are available. desDecrypt (ubl* block), // In-place decription of 64 -bit block desDone (void) ; // End current decription stream desEncrypt (ubl* block), // In-place encryption of 64-bit block deslmtdnt mode), // Start new decription stream desSetKey(ubl* key), // Set key for current decription stream RETURN Returns 0 if successful; otherwise returns an error
OVERVIEW OF OPERATION
- Before each encrypt/αecrypt operation deslnit (DESMODE128BYTΞ) , - Initialize for 128-byte key desSetKey (& (ubl) key [128] ) , - Seed with 128-byte key
To encrypt (or decrypt) multiples of 8-bytes : desEncode ( (ubl*) block) - to encrypt 8-bytes or desDecode ( (ubl*) block) ) - to decrypt 8-bytes
When done encrypting/decrypting a block of text: desDoneO; - Deimtialize (release memory)
includes
* / ttmclude " sys . h"
# include "desdef . h"
#mclude "desprt . h "
#mclude " sysprt . h"
#ιfdef NULL #undef NULL #endιf
#defme NULL 0 #lf SYSCAB2==SYSAR12 /* byte format. LSB | MSB fdefine LITTLE_ENDIAN unsigned long byteswapO ttendif /* Prototypes for internal functions */ static int spimtdong (*) [64]); static void permimt (char (*) [16] [8], char [64]); static void permute (char* , char (*) [16] [8], char*); static void round (mt num, unsigned long *block, unsigned char (*) [8] long (*) [64] ) ,
8
/* Tables defined m the Data Encryption Standard documents *,
/* initial permutation IP */ static char lp [] = {
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
10 59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7
15 /* final permutation IP^-1 */ static char fp[] = {
40, 8, 48, s, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
20 37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25
25 },
/* expansion operation matrix
* This is for reference only; it is unused in the code
* as the f () function performs it implicitly for speed 30 */
#ιfdef notdef static char ei [] = {
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
35 8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
40 28, 29, 30, 31, 32, 1
};
#endιf
/* permuted choice table (key) */ 45 static char pel [] = {
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3 , 60, 52, 44 , 36,
50
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4
->:>
/* number left rotations of pel */ static char totrot [] = {
1,2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 8
} ;
/ * permuted choice key ( table ) */ static char pc2 [] = {
14, 17, 11, 24, 1, 5,
3 , 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
}; /* The S -boxes */ static char si [8] [64] = • /* Ξl */
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
/* S2 */
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,
/* S3 */ 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, /* S4 */
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,
/* S5 */
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,
/ * S6 */
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 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,
/* S7 */
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, S, 0, 15, 14, 2, 3, 12,
/* S8 */
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
};
/* 32 -bit permutation function P used on the output of the S-boxes
*/ static char p32ι[] = {
16, 7, 20, 21,
29, 12, 28, 17,
1, 15, 23, 26,
5, 18, 31, 10,
2, 8, 24, 14,
32, 27, 3, 9,
19, 13, 30, 6,
22, 11, 4 , 25
}-
/* End of DES' -def ined tables
/* bit 0 is left-most m byte */ static mt bytebit [] = {
0200, 0100, 040, 020, 010, 04, 02, 01
static mt nibblebit [] = { 010, 04,02,01
};
/*
FUNCTION NAME deslnit - DES cryptography INITialize
EXTERNAL INTERFACE FUNCTION
Initialize DES cryptography to encode/decode new blocks of bits, allocate space and initialize DES lookup arrays SYNOPSIS
(int) deslni (mode) int mode; // mode to initialize for
DESCRIPTION Before bits can be encrypted or decrypted, deslnit must be called with one of the following three operating modes :
DEΞM0DE8BYTE - Standard, vanilla DES with 8-byte key. DESMODE8BYTEFAST - DES with the initial and final permutations removed. As these permutations do not strengthen the algorithm, they are widely regarded as having no purpose other than to slow down software implementations. Removing them speeds it up but of course the algorithm is no longer standard and it will not be compatible with hardware DES chips
DESMODE128BYTE - DES with the initial and final permutations removed, and with independent 48-bit subkeys for each of the 16 rounds
RETURN
This function returns:
== 0: The operation was successful != 0- Indicates that an error was encountered.
*/ int deslnit (mode, desp) desdef** desp;
{ desdef* des; if ('(des = *desp = (desdef*) sysalo (DESSIZ) ) ) return (-1) ; des->desmode = mode; if ( (des->dessp =(long (*) [64] ) sysalo (sizeof (long) *8*64))== NULL) { return -1;
} spinit (des->dessp) ; des->deskn = (unsigned char (*) [8] ) sysalo (sizeof (char) *8*(16+1)); if (des->deskn == NULL) { sysdea((char *) des->dessp) ; sysdea ( ( char* ) des ) ; return -1; } des->desιperm = NULL; des ->desfperm = NULL; if (mode == 1 | | mode == 2) /* No permutations return 0 ; des->desιperm = (char (*) [16] [8] ) sysalo (sizec char) *16*16*8) ; if (des->desιperm == NULL) { sysde ((char *) des->dessp) ; sysdea((char *) des->deskn) ; sysdea ( (char*) des) ,- return -1;
} perminit (des->desιperm, lp) ; des ->desfperm = (char (*) [16] [8] ) sysalo (sizeof (char) * 16*16*8); if (des->desfperm == NULL) { sysdea ((char *) des->dessp) ; sysdea ((char *) des->deskn) ; sysdea((char *) des->desιperm) ; sysdea ( (char*) des) ; return -1;
} perminit (des->desfperm, fp) ; return 0 ;
/*
FUNCTION NAME desDone - DES cryptography DONE with current stream of bits EXTERNAL INTERFACE FUNCTION
Deinitialize DES cryptography; free up storage used by DES SYNOPSIS
(void) desDone (void) ; DESCRIPTION
Once a stream of bits has been encrypted or decrypted, desDone must be called to free up memory dynamically allocated by deslnit. If further encryption or decryption is needed, deslnit and desSetKey must be called again. RETURN
This function does not return a value.
'/ void desDone (des) desdef* des;
{ if (des == NULL) return; /* Already done */ sysdea ((char *) des->dessp) ; sysdea ((char *) des->deskn) ; if (des->desιperm '= NULL) sysdea ((char *) des->desιperm) ,- if (des ->desfperm '= NULL) sysdea ((char *) des- >desfperm) ; sysde ( (char*) des) ; des = NULL;
/*
FUNCTION NAME desSetKey - DES cryptography set key for next encrypt/decrypt run
EXTERNAL INTERFACE FUNCTION
Set DES cryptography key to use to encode/decode new blocks of bits, set key (initialize key schedule array) . SYNOPSIS
(void) desSetKey (key) ubl* key; // -> proper length key to initialize
DESCRIPTION
After calling deslnit the user next calls desSetKey. In modes DESMODE8BYTE and DESMODE8BYTEFAST , 8 key bytes are expected, with the low order bit of each key byte ignored (parity is not checked) . This gives a 56-bit key.
In mode DESMODE128BYTE, 128 key bytes are expected; the high order 2 bits of each byte are ignored, giving a 768 bit key. In this mode, the first 8 bytes will be used m the first
round, the second 8 bytes in the second round, and so on.
Once the key is set, the user may perform m-place encryption and decryption of 8-byte blocks of data with calls to desEncode or desDecode. RETURN
This function does not return a value.
*/ void desSetKey (des, key) desdef* des; ubl *key; /* 64 bits (will use only 56) */
{ char pclm[56] ; /* place to modify pel into */ char per [56]; /* place to rotate pel into */ register int 1,3,1, mt m; unsigned char (*kn) [8] = des->deskn; t desmode = des->desmode ;
/* In mode 2, the 128 bytes of subkey are set directly from the
* user's key, allowing him to use completely independent
* subkeys for each round. Note that the user MUST specify a * full 128 bytes.
*/ if (desmode == 2) { for (1=0; 1<16 ; 1++) for ( =0 ; ] < 8 ; 3 ++) kn [ι] [3 ] = *key++ ; return ;
}
/* Clear key schedule */ for (ι=0; ι<16; 1++) for (3=0, 3<8, 3++) kn[ι] []]=0; for (3=0, ]<56, 3++) { I * convert pel to bits of key */ l=pcl[]]-l; /* integer bit location */ m = 1 & 07; /* find bit */ pclm.3] = (key [1>>3] S. /* find which key byte 1 is in */ bytebit [m] ) /* and which bit of that byte */ ? 1 : 0, /* and store 1-bit result */
} for (ι=0; ι<16; ι++) { /* key chunk for each iteration */ for (j=0; 3<56; 3++) /* rotate pel the right amount */ pert}] = pclm[ (l=3+totrot [1] ) < (3<28? 28 : 56)?l:l-28];
/* rotate left and right halves independently */ for (3=0,- 3<48, 3++) { /* select bits individually */ /* check bit that goes to kn-3] */ if (pcr[pc2[]]-l]){
/* mask it in if it's there */
1= 3 % 6; kn [ ι ] [3 / 6 ] | = bytebit [1] > > 2 ;
/*
FUNCTION NAME desEncrypt - DES cryptography m-place encryption of 64 -bit block
EXTERNAL INTERFACE FUNCTION
Encrypt next 64 -bit block of data SYNOPSIS
(void) desEncryp (block) ubl* block; // -> 64 bit block of data to be encrypted next DESCRIPTION
Once deslnit and desSetKey are called, desEncrypt is repeatedly called to encrypt ( place) successive 64-bit blocks of data.
When done, desDone is called. RETURN
This function does not return a value.
'/ void desEncrypt (des , block) desdef* des; ubl *block;
{ register int l; unsigned long work [2]; /* Working data storage long tmp; char (*ιperm) [16] [8] = des->desιperm; char (*fperm) [16] [8] = des ->desf erm; unsigned char (*kn) [8] = des->deskn; long (*sp) [64] = des->dessp; permute (block, iperm, (char *)work) /* Initial Permutation #ιfdef LITTLE_ENDIAN work[0] = byteswap (work [0] ) ; work.l] = byteswap (work [1] ) ; #endif
/* Do the 16 rounds */ for (1=0; l<16; l++) round (l , work, kn, sp) ;
/* Left/right half swap */ tmp = work [0] ; work [0] = wor [1] ; work [1] = tmp ;
#ιfdef LITTLE_ENDIAN work[0] = byteswap (work [0] ) ; work[l] = byteswap (work [1] ) ,- #endιf permute ( (char *) work, fperm, block) /* Inverse initial permutation */ }
/*
FUNCTION NAME desDecrypt - DES cryptography in-place decryption of 64-bit block
EXTERNAL INTERFACE FUNCTION
Decrypt next 64-bit block of data SYNOPSIS (void) desDecrypt (block) ubl* block; // -> 64 bit block of data to be decrypted next DESCRIPTION
Once deslnit and desSetKey are called, desDecrypt is repeatedly called to decrypt (in place) successive 64-bit blocks of data.
When done, desDone is called. RETURN
This function does not return a value. */ void desDecrypt (des, block) desdef* des; ubl *block; { register int i; unsigned' long wor [2]; /* Working data storage long tmp; char (*iperm) [16] [8] = des->desiperm; char (*fperm) [16] [8] = des ->desfperm; unsigned char (*kn) [8] = des->deskn; long (*sp) [64] = des->dessp; permute (block, iper , (char *)work); /* Initial permutation */
#ifdef LITTLE_ENDIAN work[0] = byteswap (work [0] ) ; work.l] = byteswap (work [1] ) ; #endif
/* Left/right half swap */ tmp = work [0] ; work [0] = wor [1] ; wor [1] = tmp;
/* Do the 16 rounds in reverse order */ for (i=15; i >= 0; i--) round (i, work, kn, sp) ; #ifdef LITTLE_ENDIAN work[0] = byteswap (work [0] ) ; wor fl] = byteswap (work [1] ) ; #endif permute ( (char *) work, fperm, block) ; /* Inverse initial permutation */ }
/* Permute inblock with perm */
static void permute ( inblock, perm, outblock) char *inblock, *outblock; /* result into outblock, 64 bits char ( *perm) [16] [8] ; /* 2K bytes defining perm.
{ register int i,j; register char *ib, *ob; /* ptr to input or output block register char *p, *q; if (perm == NULL) {
/* No permutation, just copy */ for(i=8; i!=0; i--)
*outblock++ = *inblock++; return;
}
/* Clear output block */ for (i=8, ob = outblock; i != 0; i--) *ob++ = 0; ib = inblock; for (j = 0; j < 16; j += 2, ib++) { /* for each input nibble ob = outblock; p = perm[j] [ (*ib >> 4) & 017] ; q = perm[j + 1] [*ib & 017] ; for (i = 8; i != 0; i--){ /* and each output byte
*ob++ |= *p++ I *q++; /* OR the masks together
}
}
}
/* Do one DES cipher round */ static void round (num, lock, kn, sp) int num,- /* i.e. the num-th one */ unsigned long *block; unsigned char (*kn) [8] ; long (*sp) [64] ,-
{ long f ( ) ;
/* The rounds are numbered from 0 to 15. On even rounds
* the right half is fed to f() and the result exclusive-ORs
* the left half; on odd rounds the reverse is done.
*/ if (num s. 1) { block [1] A= f (block [0 ] , n [num] , sp) ; } else { block [0] Λ= f (block [1] , kn [num] , sp) ;
} }
/* The nonlinear function f(r,k) */ static long f (r, subkey, sp) unsigned long r; /* 32 bits */ unsigned char subkey[8]; /* 48-bit key for this round long (*sp) [64] ;
{ register unsigned long rval , rt ;
/* Run E(R) A K through the combined S & P boxes
* This code takes advantage of a convenient regularity in
* E, namely that each group of 6 bits in E(R) feeding
* a single S -box is a contiguous segment of R.
*/ rt = (r >> 1) (r & 1) 0x80000000 0) ; rval = 0; rval = sp[0~ [((rt >> 26) Λ *subkey++) S. 0x3 f] rval = sp[l [((rt >> 22) Λ *subkey++) & 0x3 f] rval = sp[2 [((rt >> 18) Λ *subkey++) £. 0x3 f] rval = sp[3 [((rt >> 14) Λ *subkey++) & 0x3 f] rval = sp [4 [((rt >> 10) Λ *subkey++) S 0x3f] rval = sp[5 [((rt >> 6) A *subkey++) & 0x3 f] ; rval = sp [6 [((rt >> 2) Λ *subkey++) Sc 0x3 f] ; rt = (r << 1 ( (r & 0x80000000) ? 1 : 0) ; rval |= sp[7 [(rt subkey) & 0x3 f] ; return rval;
/* initialize a perm array */ static void perminit (perm,p) char (*perm) [16] [8] ,- /* 64-bit, either mit or final char *p;
{ register int 1, j, k; mt l , m;
/* Clear the permutation array */ for (l=0; 1<16; 1++) for (3=0; 3<16; 3++) for (k=0; k<8; k++) perm[i] [j] [k] =0; for (1=0; 1<16; 1++) /* each input nibble position */ for (3 = 0; 3 < 16; 3++)/* each possible input nibble */ for (k = 0; k < 64; k++)/* each output bit position */
1 = p[k] - 1; / * where does this bit come from */ If ( (1 >> 2) '= l) /* does it come from input posn? */ continue; / * if not, bit k is 0 */ if ( ' (3 Sc mbblebit [1 & 3] ) ) continue; /* any such bit m input? '/ m = k & 07; /* which bit is this n the byte perm[ι] [3] [k>>3] |= bytebit [m] ;
} /* Initialize the lookup table for the combined S and P boxes */ static int spmit (sp) long (*sp) [64] , { char pbox [32] ,- mt p, 1, s, 3 , rowcol ; long val,
/* Compute pbox, the inverse of p32i. * This is easier to work with
*/ for (p=0;p<32;p++) { for (i=0 ; i<32; i++) { if (p32i[i] -1 == p) { pbox[p] = i; break; }
} for(s = 0; s < 8; s++) { /* For each S-box */ for(i=0; i<64; i++) { /* For each possible input */ val = 0 ; /* The row number is formed from the first and last
* bits; the column number is from the middle 4
*/ rowcol = (i Sc 32) I ( (i Sc 1) ? 16 : 0) I ( (i >> 1) ScOxf) ; for (j=0 ; j<4 ; j++) { /* For each output bit */ if (si [s] [rowcol] Sc (8 >> j ) ) { val |= 1L << (31 - pbox[4*s + j]);
} } sp [s] [i] = val; }
} return 0 ;
}
#ifdef LITTLE_ENDIAN /* Byte swap a long */ static unsigned long byteswap (x) unsigned long x; { register char *cp,tmp; cp = (char *) S-x; tmp = cp [3] ; cp[3] = cp[0] ; cp[0] = tmp; tmp = cp[2] ; cp[2] = cp[l] ; cp[l] = tmp; return x;
} #endif