Top Banner
OpenSSL DES APIs OpenSSL DES APIs Finnbarr P. Murphy ([email protected]) Now that OpenSSL has finally reached version 1.0.0, I decided to take another look how the various Data Encryption Standard (DES) application programming interfaces (routines) included in OpenSSL can be used to encrypt and decrypt data. Since there is also a lack of simple examples available on the Internet of how to actually use the OpenSSL DES routines, I have included a number of examples in this post to encourage readers to experiment with these routines. The original author of the DES routines in OpenSSL’s libcrypto was Eric Young. Young and Tim Hudson posted the first version of of a free cryptographic library called SSLeay (eay stands for Eric A, Young) to the Internet in 1995. Amazingly Young managed to single-handedly implement the full suite of cryptosystems used in SSLeay. Since then the SSLeay library has become part of OpenSSL. However you will still frequently come across references to SSLeay in both man pages and the source code. Young is still involved in cryptography and currently works for RSA, the security division of EMC. Some background information on DES is probably in order for those who have forgotten their college course on cryptography. DES has been around for quite a long time. It was developed by IBM as enhancement to an existing key generator algorithm called Lucifer that was primarily developed by Horst Feistel. It became a standard in 1977 when the National Bureau of Standards (now called NIST) issued Federal Information Processing Standards Publication 46 (FIPS 46). That standard specified that DES be used within the Federal Government for the cryptographic protection of sensitive, but unclassified, computer data. DES is a member of the class of ciphers (British English: cyphers) called a block cipher. In a block cipher, a block of N bits from the plaintext is replaced with a block of N bits from the ciphertext. Ideally the relationship between the input block and the output block is completely random but invertible. This implies a one-to- one relationship with each input block being mapped to a unique output block. Mathematically, DES maps the set of all possible 64-bit vectors onto itself. Selecting a DES cryptographic key allows a user to select one of the possible mappings Technically speaking, DES is an iterative, block, product cipher system (encryption algorithm). A product cipher system mixes transposition and substitution operations in an alternating manner. Iterations refers to the use of the output of an operation as the input for another iteration of the same procedure. This is known as a Feistel structure or Feistel network. A cryptographic system based on a Feistel structure uses the same basic algorithm for both encryption and decryption. A large proportion of block ciphers, including DES, use a Festel structure. For personnal use only 03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 1/12
12
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: OpenSSL DES API

OpenSSL DES APIs

OpenSSL DES APIsFinnbarr P. Murphy

([email protected])

Now that OpenSSL has finally reached version 1.0.0, I decided to take another look how thevarious Data Encryption Standard (DES) application programming interfaces (routines) includedin OpenSSL can be used to encrypt and decrypt data. Since there is also a lack of simple examplesavailable on the Internet of how to actually use the OpenSSL DES routines, I have included anumber of examples in this post to encourage readers to experiment with these routines.

The original author of the DES routines in OpenSSL’s libcrypto was Eric Young. Young and TimHudson posted the first version of of a free cryptographic library called SSLeay (eay stands forEric A, Young) to the Internet in 1995. Amazingly Young managed to single-handedly implementthe full suite of cryptosystems used in SSLeay. Since then the SSLeay library has become part ofOpenSSL. However you will still frequently come across references to SSLeay in both man pagesand the source code. Young is still involved in cryptography and currently works for RSA, thesecurity division of EMC.

Some background information on DES is probably in order for those who have forgotten theircollege course on cryptography. DES has been around for quite a long time. It was developed byIBM as enhancement to an existing key generator algorithm called Lucifer that was primarilydeveloped by Horst Feistel. It became a standard in 1977 when the National Bureau of Standards(now called NIST) issued Federal Information Processing Standards Publication 46 (FIPS 46). Thatstandard specified that DES be used within the Federal Government for the cryptographicprotection of sensitive, but unclassified, computer data.

DES is a member of the class of ciphers (British English: cyphers) called a block cipher. In a blockcipher, a block of N bits from the plaintext is replaced with a block of N bits from the ciphertext.Ideally the relationship between the input block and the output block is completely random butinvertible. This implies a one-to- one relationship with each input block being mapped to a uniqueoutput block. Mathematically, DES maps the set of all possible 64-bit vectors onto itself. Selectinga DES cryptographic key allows a user to select one of the possible mappings

Technically speaking, DES is an iterative, block, product cipher system (encryption algorithm). Aproduct cipher system mixes transposition and substitution operations in an alternating manner.Iterations refers to the use of the output of an operation as the input for another iteration of thesame procedure. This is known as a Feistel structure or Feistel network. A cryptographic systembased on a Feistel structure uses the same basic algorithm for both encryption and decryption. Alarge proportion of block ciphers, including DES, use a Festel structure.Fo

r pers

onna

l use

only

03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 1/12

Page 2: OpenSSL DES API

OpenSSL DES APIs

The algorithmic implementation of DES is known as Data Encryption Algorithm (DEA). DEA usessixteen iterations of a pair of transposition and substitution operations to encrypt or decrypt aninput block. All computations are linear except for the Substitution-boxes (S-boxes) which providethe non-linear substitution component of the algorithm. Linear algorithms can be easily brokenusing a known plaintext attack. The S-boxes in DEA effectively hinder this form of attack (ClaudeShannon‘s diffusion property.) The number of rounds (16) is important also. An 8-round DEA canbe broken in a few minutes on a PC using a chosen plaintext attack, i.e. differential cryptoanalysis.When DEA was proposed, there was considerable criticism with most of it directed at the S-boxes.It was even suggested the the S-boxes might contain a trapdoor. One useful property of DEA isthat it can be implemented very efficiently in software (or in hardware for that matter) using tablelook-up. DES uses a 56-bit encryption key and a 64-bit block. The key itself is specified with 8bytes (64-bits), but the last bit of each byte is used as a parity check of the other 7 bits. Roundkeys are 48-bits and are generated from the 56-bit encryption key by a sequence of permutations.

Several methods of incorporating DES into a cryptographic system are possible. Generallyspeaking, these can be classified into either block or stream methods. In addition a number ofmodes of operation are specified by the FIPS 81 (DES Modes of Operation) standard. The modesspecify how data will be encrypted and decrypted. These are summarized below.

Electronic Codebook Mode (ECB)

64 bits (i.e. a block) are enciphered at a time.●

The order of the blocks can be rearranged without detection.●

A plaintext block always produces the same ciphertext block for the same key.●

An error only affects one ciphertext block. ●

For p

erson

nal u

se on

ly

03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 2/12

Page 3: OpenSSL DES API

OpenSSL DES APIs

Use discouraged as vulnerable to a directory attack●

Cipher Block Chaining Mode (CBC)

Multiples of 64 bits are enciphered at a time.●

Blocks cannot be rearranged. Each ciphertext block depends on the current and all preceding●

plaintext blocks.A plaintext block always produces the same ciphertext block for the same key and starting●

variable.Different starting variables prevent the same plaintext enciphering to the same ciphertext.●

An error affects the current and following ciphertext blocks.●

Cipher Feedback Mode (CFB)

Only blocks of j <= 64 bits are enciphered at a time.●

A small j requires more cycles through the encipherment algorithm per unit of plaintext and thus●

greater processing overhead.A plaintext block always produces the same ciphertext block for the same key and starting●

variable.Blocks cannot be rearranged. Each ciphertext block depends on the current and all preceding●

plaintext blocks.Different starting variables are used to prevent the same plaintext enciphering to the same●

ciphertext.The strength of this mode depends on the size of the key k (best if j == k).●

An error will affect the current and the following ciphertext blocks.●

Output Feedback Mode (OFB)

Only blocks of j <= 64 bits are enciphered at a time.●

A small j requires more cycles through the encipherment algorithm per unit of plaintext and thus●

greater processing overhead.A plaintext block always produces the same ciphertext block for the same key and starting●

variable.Different starting variables are used to prevent the same plaintext enciphering to the same●

ciphertext.Absence of chaining makes this mode vulnerable to specific attacks.●

Different start variable values prevent the same plaintext enciphering to the same ciphertext, by●

producing different key streams.An error bit in the ciphertext causes only one bit to be in error in the deciphered plaintext.●

It is not self-synchronizing.●

Triple-DES ECB Mode

Encrypt with key1, decrypt with key2 and encrypt with key3 again. ●

As for ECB encryption but increases the key length to 168 bits.●

If all keys are the same it is equivalent to encrypting once with just one key.●

If the first and last key are the same, the key length is 112 bits.●

If all 3 keys are the same, this is effectively the same as normal ECB mode.●

Triple-DES CBC Mode

Encrypt with key1, decrypt with key2 and then encrypt with key3.●

As for CBC encryption but increases the key length to 168 bits with the same restrictions as the●

Triple-DES ESB mode

Our first example shows how to use the basic DES encryption routine, DES_ecb_encrypt(), to

For p

erson

nal u

se on

ly

03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 3/12

Page 4: OpenSSL DES API

OpenSSL DES APIs

encrypt or decrypt a single 64-bit block of plaintext to electronic code book (ECB) mode. If theencrypt argument is DES_ENCRYPT, the input (plaintext) is encrypted into the output (ciphertext)using the specified key_schedule. If the encrypt argument is DES_DECRYPT, the input (ciphertext)is decrypted into the output (plaintext). Note that input and output may overlap.

#include &lt;stdio.h&gt;#include &lt;string.h&gt;#include &lt;stdlib.h&gt;#include &lt;openssl/des.h&gt;#include &lt;openssl/rand.h&gt;#define BUFSIZE 64 int main(void){ unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE]; unsigned char *e = out; DES_cblock key; DES_cblock seed = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}; DES_key_schedule keysched; memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); memset(back, 0, sizeof(back)); RAND_seed(seed, sizeof(DES_cblock)); DES_random_key(&amp;key); DES_set_key((C_Block *)key, &amp;keysched); /* 8 bytes of plaintext */ strcpy(in, "HillTown"); printf("Plaintext: [%s]\n", in); DES_ecb_encrypt((C_Block *)in,(C_Block *)out, &amp;keysched, DES_ENCRYPT); printf("Ciphertext:"); while (*e) printf(" [%02x]", *e++); printf("\n"); DES_ecb_encrypt((C_Block *)out,(C_Block *)back, &amp;keysched, DES_DECRYPT); printf("Decrypted Text: [%s]\n", back); return(0);}

Note the use of C_Block. The examples in this post use C_Block because that is what I am used tousing. If you are writting new code for modern platforms, you should use DES_cblock rather thanC_Block or des_cblock. See des.h for the defintion of DES_cblock, i.e. typedef unsigned charDES_cblock[8].

Here the output when the program is compiled and executed.

$ gcc -o example1 example1.c -lcrypto$ ./example1Plaintext: [HillTown]Ciphertext: [34] [bc] [85] [30] [14] [95] [43] [00]Decrypted Text: [HillTown]$

Examining the above code you will see that there are two parts to using DES encryption. The firstis the generation of a DES_key_schedule from a key, the second is the actual encryption ordecryption. A DES key is of type DES_cblock which consists of 8 bytes with odd parity. The leastsignificant bit in each byte is the parity bit. The key schedule is an expanded platform-dependentform of the key which is used to speed the encryption process. The example uses a seeded PRNG (RAND_seed()) to generate a random 64-bit DES key. Notice that I explicitly zero all storage thatthe example uses; always a good idea when using OpenSSL library routines. Examining the output,you will see that the size of the ciphertext is the same as the plaintext. This is a characteristic of a

For p

erson

nal u

se on

ly

03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 4/12

Page 5: OpenSSL DES API

OpenSSL DES APIs

block cipher. Note that if you compile and run this example, you will not get the same ciphertextas I got due to the fact that the example uses a randomly generated key.

Our next example demonstrates the Triple-DES mode. For some reason a lot of people areunaware that FIPS-46 actually specifies two modes for Triple-DES:

EDE (Encrypt-Decrypt-Encrypt) where ciphertext = Ek3(Dk2(Ek1(plaintext)))●

EEE (Encrypt-Encrypt-Encrypt) where ciphertext = Ek3(Ek2(Ek1(pliantext)))●

where Ek and Dk denote DES encryption and decryption respectively. In addition, ANSI X9.52defines three key options for Triple-DES:

k1 != k2 != k3●

k1 != k2, k1 = k3, k2 != k3●

k1 = k2 = k3●

The third option makes Triple-DES backwardly compatible with DES. The recommended usagemode, per FIPS-46, for Triple-DES is EEE or EDE with three independently generated keys, i.e.168 key bits in total. OpenSSL uses the EDE mode.

#include &lt;stdio.h&gt;#include &lt;string.h&gt;#include &lt;stdlib.h&gt;#include &lt;openssl/des.h&gt;#include &lt;openssl/rand.h&gt;#define BUFSIZE 1024int main(void){ unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE]; unsigned char *e = out; int i; DES_cblock key1, key2, key3; DES_cblock seed = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}; DES_key_schedule ks1, ks2, ks3; memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); memset(back, 0, sizeof(back)); RAND_seed(seed, sizeof(DES_cblock)); DES_random_key(&amp;key1); DES_random_key(&amp;key2); DES_random_key(&amp;key3); DES_set_key((C_Block *)key1, &amp;ks1); DES_set_key((C_Block *)key2, &amp;ks2); DES_set_key((C_Block *)key3, &amp;ks3); /* 64 bytes of plaintext */ strcpy(in, "Now is the time for all men to stand up and be counted"); printf("Plaintext: [%s]\n", in); for (i = 0; i &lt; 63; i += 8) { DES_ecb3_encrypt((C_Block *)(in + i),(C_Block *)(out + i), &amp;ks1, &amp;ks2, &amp;ks3, DES_ENCRYPT); } printf("Ciphertext:"); while (e++) printf(" [%02x]", *e++); printf("\n"); for (i = 0; i &lt; 63; i += 8) { DES_ecb3_encrypt((C_Block *)(out + i),(C_Block *)(back + i), &amp;ks1, &amp;ks2, &amp;ks3, DES_DECRYPT); } printf("Decrypted Text: [%s]\n", back); exit(0);}

For p

erson

nal u

se on

ly

03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 5/12

Page 6: OpenSSL DES API

OpenSSL DES APIs

As you can see, this example uses three different keys (k1 != k2 != k3) which is the recommendedway of using Triple-DES. Here is the output when this example is compiled and executed:

[fpm@ultra ~]$ ./example2Plaintext: [Now is the time for all men to stand up and be counted]Ciphertext: [b4] [31] [40] [aa] [41] [7d] [fc] [72] [4b] [f7] [46] [b5] [24] [83] [95] [03] [38] [1a] [50] [4e] [65] [5e] [83] [19] [b4] [0f] [74] [8b] [0c] [de] [5f] [34] [bf] [ee] [65] [4a] [b1] [0d] [33] [b4] [db] [cd] [02] [2c] [6c] [39] [7e] [57] [0d] [99] [18] [69] [23] [56] [fb] [00]Decrypted Text: [Now is the time for all men to stand up and be counted][fpm@ultra ~]$

The next example demonstrates the Cipher Block Chaining mode. In this mode each block isXOR-ed with the previous cipherblock before encryption.

Because changes in the plaintext propagate forever in the ciphertext, encryption cannot beparallelized. For the first block we start with an initiallization vector (ivec). Note that it is notunusual to start with a zero vector as the initialization vector. Note that there is both aDES_cbc_encrypt() and a DES_ncbc_encrypt() in libcrypto. I recommend you only use the ncbcversion (n stands for new). See the BUGS section of the OpenSSL DES manpage and the sourcecode for these functions.

#include &lt;stdio.h&gt;#include &lt;string.h&gt;#include &lt;stdlib.h&gt;#include &lt;openssl/des.h&gt;#include &lt;openssl/rand.h&gt;#define BUFSIZE 512 int main(void){ unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE]; unsigned char *e = out; int len; DES_cblock key; DES_cblock seed = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}; DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8}; DES_key_schedule keysched; DES_cblock ivec; memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); memset(back, 0, sizeof(back)); RAND_seed(seed, sizeof(DES_cblock)); DES_random_key(&amp;key); DES_set_odd_parity(&amp;key); if (DES_set_key_checked((C_Block *)key, &amp;keysched)) { fprintf(stderr, "ERROR: Unable to set key schedule\n"); exit(1); } /* 64 bytes of plaintext */ strcpy(in, "Now is the time for all men to stand up and be counted"); printf("Plaintext: [%s]\n", in); len = strlen(in); memcpy(ivec, ivsetup, sizeof(ivsetup)); DES_ncbc_encrypt(in, out, len, &amp;keysched, &amp;ivec, DES_ENCRYPT); printf("Ciphertext:"); while (*e) printf(" [%02x]", *e++); printf("\n"); memcpy(ivec, ivsetup, sizeof(ivsetup)); DES_ncbc_encrypt(out, back, len, &amp;keysched, &amp;ivec, DES_DECRYPT);

For p

erson

nal u

se on

ly

03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 6/12

Page 7: OpenSSL DES API

OpenSSL DES APIs

printf("Decrypted Text: [%s]\n", back); exit(0);}

Note that I reinitialize ivec before decrypting the ciphertext. If you do not reinitialize ivec yourdecrypted text will be incorrect.

The next example uses DES_ede3_ncbc_encrypt() to implement outer triple CBC DES encryptionwith three keys. This means that each DES operation inside the CBC mode isC=E(ks3,D(ks2,E(ks1,M))) . This is the mode is used by SSL.

#include &lt;stdio.h&gt;#include &lt;string.h&gt;#include &lt;stdlib.h&gt;#include &lt;openssl/des.h&gt;#include &lt;openssl/rand.h&gt;#define BUFSIZE 512 int main(void){ unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE]; unsigned char *e = out; int len; DES_cblock key1, key2, key3; DES_cblock seed = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}; DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8}; DES_cblock ivec; DES_key_schedule ks1, ks2, ks3; memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); memset(back, 0, sizeof(back)); RAND_seed(seed, sizeof(DES_cblock)); DES_random_key(&amp;key1); DES_random_key(&amp;key2); DES_random_key(&amp;key3); DES_set_key((C_Block *)key1, &amp;ks1); DES_set_key((C_Block *)key2, &amp;ks2); DES_set_key((C_Block *)key3, &amp;ks3); /* 64 bytes of plaintext */ strcpy(in, "Now is the time for all men to stand up and be counted"); printf("Plaintext: [%s]\n", in); len = strlen(in); memcpy(ivec, ivsetup, sizeof(ivsetup)); DES_ede3_cbc_encrypt(in, out, len, &amp;ks1, &amp;ks2, &amp;ks3, &amp;ivec, DES_ENCRYPT); printf("Ciphertext:"); while (*e) printf(" [%02x]", *e++); printf("\n"); len = strlen(out); memcpy(ivec, ivsetup, sizeof(ivsetup)); DES_ede3_cbc_encrypt(out, back, len, &amp;ks1, &amp;ks2, &amp;ks3, &amp;ivec, DES_DECRYPT); printf("Decrypted Text: [%s]\n", back); exit(0);}

Note the need to reinitialize ivec before decrypting the ciphertext. If you do not do this, the first64 bits of the resultant plaintext will be incorrect.

The next example shows the use of a modified form of the CBC mode called Triple DES CipherBlock Chaining with Output Feedback Masking. This mode provides stronger protection againstdictionary attacks and matching ciphertext attacks that exploit the DES blocksize of 64 bits

For p

erson

nal u

se on

ly

03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 7/12

Page 8: OpenSSL DES API

OpenSSL DES APIs

through the introduction of secret masking values that are XOR-ed with the intermediate outputsof each triple-DES encryption operation. Apparantly, however, Eli Biham and Lars Knudsen havedeveloped an attack on this mode but it requires a lot of work.

#include &lt;stdio.h&gt;#include &lt;string.h&gt;#include &lt;stdlib.h&gt;#include &lt;openssl/des.h&gt;#include &lt;openssl/rand.h&gt;#define BUFSIZE 512#define CBCM_ONEint main(void){ unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE]; unsigned char *e = out; int len; DES_cblock key1, key2, key3; DES_cblock seed = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}; DES_cblock ivecstr = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8}; DES_cblock ivec2, ivec1; DES_key_schedule ks1, ks2, ks3; memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); memset(back, 0, sizeof(back)); RAND_seed(seed, sizeof(DES_cblock)); DES_random_key(&amp;key1); DES_random_key(&amp;key2); DES_random_key(&amp;key3); DES_set_key((C_Block *)key1, &amp;ks1); DES_set_key((C_Block *)key2, &amp;ks2); DES_set_key((C_Block *)key3, &amp;ks3); /* 64 bytes of plaintext */ strcpy(in, "Now is the time for all men to stand up and be counted"); printf("Plaintext: [%s]\n", in); memcpy(ivec2, ivecstr, sizeof(ivecstr)); memset(ivec1,'&#92;&#48;',sizeof(ivec2)); len = strlen(in) + 1;#ifdef CBCM_ONE DES_ede3_cbcm_encrypt(in, out, len, &amp;ks1, &amp;ks2, &amp;ks3, &amp;ivec2, &amp;ivec1, DES_ENCRYPT);#else DES_ede3_cbcm_encrypt(in, out, 16, &amp;ks1, &amp;ks2, &amp;ks3, &amp;ivec2, &amp;ivec1, DES_ENCRYPT); DES_ede3_cbcm_encrypt(&amp;in[16], &amp;out[16],len-16, &amp;ks1, &amp;ks2, &amp;ks3, &amp;ivec2, &amp;ivec1, DES_ENCRYPT);#endif printf("Ciphertext:"); while (*e) printf(" [%02x]", *e+); printf("\n"); len = strlen(out) + 1; memcpy(ivec2, ivecstr, sizeof(ivecstr)); memset(ivec1,'&#92;&#48;',sizeof(ivec2)); DES_ede3_cbcm_encrypt(out, back, len, &amp;ks1, &amp;ks2, &amp;ks3, &amp;ivec2, &amp;ivec1, DES_DECRYPT); printf("Decrypted Text: [%s]\n", back); exit(0);

The above example showns you two variations for encrypting the plaintext and vice-versa. Thetwo-step approach is useful in some situations.

The next example shows the use of the Cipher Feedback (CFB) mode. CFB is a close relative ofCBC but is a self-synchronizing stream cipher if the 1-bit mode is selected.

For p

erson

nal u

se on

ly

03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 8/12

Page 9: OpenSSL DES API

OpenSSL DES APIs

#include &lt;stdio.h&gt;#include &lt;string.h&gt;#include &lt;stdlib.h&gt;#include &lt;openssl/des.h&gt;#include &lt;openssl/rand.h&gt;#define BUFSIZE 256#define CFBMODE 1int main(void){ unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE]; unsigned char *e = out; int len; DES_cblock key; DES_cblock seed = {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}; DES_cblock ivecstr = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8}; DES_cblock ivec; DES_key_schedule ks; memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); memset(back, 0, sizeof(back)); RAND_seed(seed, sizeof(DES_cblock)); DES_random_key(&amp;key); DES_set_key((C_Block *)key, &amp;ks); /* 11 bytes of plaintext */ strcpy(in, "Philippines"); printf("Plaintext: [%s]\n", in); memcpy(ivec, ivecstr, sizeof(ivecstr)); len = strlen(in); DES_cfb_encrypt(in, out, CFBMODE, len, &amp;ks, &amp;ivec, DES_ENCRYPT); printf("Ciphertext:"); while (*e) printf(" [%02x]", *e+); printf("\n"); len = strlen(out); memcpy(ivec, ivecstr, sizeof(ivecstr)); DES_cfb_encrypt(out, back, CFBMODE, len, &amp;ks, &amp;ivec, DES_DECRYPT); printf("Decrypted Text: [%s]\n", back); exit(0);}

Here is an example which uses the CBF64 mode and also, for the first time, uses ASCII strings forthe initialization vector and DES key.

#include &lt;stdio.h&gt;#include &lt;string.h&gt;#include &lt;stdlib.h&gt;#include &lt;openssl/des.h&gt;#define BUFSIZE 256 int main(void){ unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE]; unsigned char *e = out; int len; int n = 0; static char *keystr = "0123456789abcdef"; static char *ivecstr = "0123456789abcdef"; DES_cblock ivec; DES_key_schedule ks; memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); memset(back, 0, sizeof(back)); strcpy(in,"Now is the time for all."); DES_set_key((C_Block *)keystr, &amp;ks); printf("Plaintext: [%s]\n", in);

For p

erson

nal u

se on

ly

03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 9/12

Page 10: OpenSSL DES API

OpenSSL DES APIs

memcpy(ivec, (C_Block *)ivecstr, sizeof(ivec)); len = strlen(in) + 1; DES_cfb64_encrypt(in, out, len, &amp;ks, &amp;ivec, &amp;n, DES_ENCRYPT); printf("Ciphertext:"); while (*e) printf(" [%02x]", *e++); printf("\n"); memcpy(ivec, (C_Block *)ivecstr, sizeof(ivec)); DES_cfb64_encrypt(out, back, len, &amp;ks, &amp;ivec, &amp;n, DES_DECRYPT); printf("Decrypted Text: [%s]\n", back); exit(0);}

Note the use of DES_string_to_key() to convert a string into a key. The inputted string should be atleast 16 characters in length.DES_string_to_key() sets odd parity so there is no need to invokeDES_set_odd_parity().

The next example demonstrates the use of 8-bit OFB mode. This mode is an additive stream cipherin which errors in the ciphertext are not extended to cause additional errors in the decryptedplaintext. Thus a single bit in error in the ciphertext causes only one bit to be in error in thedecrypted plaintext. According to the OpenSSL man page, this mode should only be used for smallsizes of plaintext. From experimenting with numbits and the BUGS section of the DES manpage, Isuggest you always use a value of 8 for numbits.

#include &lt;stdio.h&gt;#include &lt;string.h&gt;#include &lt;stdlib.h&gt;#include &lt;openssl/des.h&gt;#include &lt;openssl/rand.h&gt;#define BUFSIZE 256 int main(void){ unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE]; unsigned char *e = out; char *keystr = "Philippines06235"; int len, n, result; DES_cblock key; DES_cblock ivecstr = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8}; DES_cblock ivec; DES_key_schedule ks; memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); memset(back, 0, sizeof(back)); DES_string_to_key(keystr, &amp;key); if ((result = DES_set_key_checked((C_Block *)key, &amp;ks)) != 0) { if (result == -1) { printf("ERROR: key parity is incorrect\n"); } else { printf("ERROR: weak or semi-weak key\n"); } exit(1); } strcpy(in,"The Chocolate Hills of Bohol are wonderful."); printf("Plaintext: [%s]\n", in); memcpy(ivec, ivecstr, sizeof(ivecstr)); len = strlen(in); printf("Plaintext Length: %d\n", len); DES_ofb_encrypt(in, out, 8, len, &amp;ks, &amp;ivec); n = 0; printf("Ciphertext:"); while (*e) { printf(" [%02x]", *e++); n++; }

For p

erson

nal u

se on

ly

03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 10/12

Page 11: OpenSSL DES API

OpenSSL DES APIs

printf("\n"); printf("Ciphertext Length: %d\n", n); len = strlen(out); memcpy(ivec, ivecstr, sizeof(ivecstr)); DES_ofb_encrypt(out, back, 8, len, &amp;ks, &amp;ivec); printf("Decrypted Text: [%s]\n", back); exit(0);}

The final example in this post uses ede3_ofb64_encrypt() to perform the encryption and decryption.It also reads in the plaintext from an external file. To simplify things and shorten the example, Iset k1 = k2 = k3. I will leave it up to you to modify the example to support the case where k1 !=k2 != k3.

#include &lt;stdio.h&gt;#include &lt;string.h&gt;#include &lt;stdlib.h&gt;#include &lt;openssl/des.h&gt;#define BUFSIZE 1024 int main(int argc, char *argv[]){ unsigned char in[BUFSIZE], out[BUFSIZE], back[BUFSIZE]; char buf[201]; char *keystr = "Victoria Harbour"; unsigned char *e = out; FILE *fin; int i, num, len, result; int n = 0; DES_cblock key; DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8}; DES_key_schedule ks; DES_cblock ivec; if (argc != 2) { printf("ERROR: plaintext filename required\n"); exit(1); } memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); memset(back, 0, sizeof(back)); DES_string_to_key(keystr, &amp;key); if ((result = DES_set_key_checked((C_Block *)key, &amp;ks)) != 0) { if (result == -1) { printf("ERROR: key parity is incorrect\n"); } else { printf("ERROR: weak or semi-weak key\n"); } exit(1); } fin = fopen(argv[1], "r"); if (!fin) { printf(" ERROR: opening input file\n"); exit(1); } while(fgets(buf, 200, fin) != NULL) { strcat(in, buf); } fclose(fin); printf("Plaintext: [%s]\n", in); len = strlen(in); printf("Plaintext Length: %d\n", len); memcpy(ivec, ivsetup, sizeof(ivsetup)); num = 0; for (i = 0; i &lt; len; i++) { DES_ede3_ofb64_encrypt(&amp;(in[i]), &amp;(out[i]), 1, &amp;ks, &amp;ks, &amp;ks,

For p

erson

nal u

se on

ly

03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 11/12

Page 12: OpenSSL DES API

OpenSSL DES APIs

&amp;ivec, &amp;num); } n = 0; printf("Ciphertext:"); while (*e) { printf(" [%02x]", *e++); n++; } printf("\n"); printf("Ciphertext Length: %d\n", n); memcpy(ivec, ivsetup, sizeof(ivsetup)); num = 0; for (i = 0; i &lt; len; i++) { DES_ede3_ofb64_encrypt(&amp;(out[i]), &amp;(back[i]), 1, &amp;ks, &amp;ks, &amp;ks, &amp;ivec, &amp;num); } printf("Decrypted Text: [%s]\n", back); exit(0);}

Here is sample output:

$ echo -n "Now is the time to finish this post" &gt; plaintext$ ./example9 plaintextPlaintext: [Now is the time to finish this post]Plaintext Length: 35Ciphertext: [92] [cb] [29] [fe] [aa] [94] [d7] [ba] [07] [a5] [8f] [78] [4f] [13] [fa] [c4] [4f] [22] [0d] [fd] [b7] [33] [81] [3e] [3a] [e4] [f5] [c6] [52] [c9] [2b] [4f] [d5] [b8] [00]Ciphertext Length: 35Decrypted Text: [Now is the time to finish this post]$

Well, I think I have covered the OpenSSL v1.0 DES routines in sufficient detail for most readers.There are a number of other routines but these are infrequently used or are slight variations onthe routines used in the above examples. You may come across many references to DES routineswhich start with des_. These are essentially the same as the DES_ routines but are from olderversions of libcrypto. The move to DES_ occurred several years ago. You should always use theDES_ version of a routine if it is available.

Armed with your new knowledge, you should now be able to go away and use DES within yourapplications. Feel free to use any source code included in this post. If you want to learn moreabout DES, Douglas Stinson does an excellent job in Chapter 3 of his book Crytography Theoryand Practice (ISBN 0-8493-8521-0). Another excellent book, with lots of C source code, is BruceSchneir’s Applied Cryptography (ISBN 0-471-59756-2). Unfortunately, currently the OpenSSL manpages are poor at best and downright inaccurate at worst so you may frequently find yourselfexamining the libcrypto source code. All of the relevant DES code is in the ../crypto/dessubdirectory.

Enjoy!

For p

erson

nal u

se on

ly

03-03-2011 Copyright 2004-2011 Finnbarr P. Murphy. All rights reserved. 12/12