openssl des

转载自:http://blog.fpmurphy.com/2010/04/openssl-des-api.html

OpenSSL DES APIs

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.

Feistel structure

The algorithmic implementation of DES is known as Data Encryption Algorithm (DEA). DEA uses sixteen iterations of a pair of transposition and substitution operations to encrypt or decrypt an input block. All computations are linear except for the Substitution-boxes (S-boxes) which provide the non-linear substitution component of the algorithm. Linear algorithms can be easily broken using a known plaintext attack. The S-boxes in DEA effectively hinder this form of attack (Claude Shannon‘s diffusion property.) The number of rounds (16) is important also. An 8-round DEA can be 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 is that it can be implemented very efficiently in software (or in hardware for that matter) using table look-up. DES uses a 56-bit encryption key and a 64-bit block. The key itself is specified with 8 bytes (64-bits), but the last bit of each byte is used as a parity check of the other 7 bits. Round keys 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. Generally speaking, these can be classified into either block or stream methods. In addition a number of modes of operation are specified by the FIPS 81 (DES Modes of Operation) standard. The modes specify 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.
  • 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 encrypt or decrypt a single 64-bit block of plaintext to electronic code book (ECB) mode. If the encrypt 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/des.h>
#include <openssl/rand.h>
 
#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(&key);
 
    DES_set_key((C_Block *)key, &keysched);
 
    /* 8 bytes of plaintext */
    strcpy(in, "HillTown");
 
    printf("Plaintext: [%s]\n", in);
 
    DES_ecb_encrypt((C_Block *)in,(C_Block *)out, &keysched, DES_ENCRYPT);
 
    printf("Ciphertext:");
    while (*e) printf(" [%02x]", *e++);
    printf("\n");
 
    DES_ecb_encrypt((C_Block *)out,(C_Block *)back, &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 to using. If you are writting new code for modern platforms, you should use DES_cblock rather than C_Block or des_cblock. See des.h for the defintion of DES_cblock, i.e. typedef unsigned char DES_cblock[8].

Examining the above code you will see that there are two parts to using DES encryption. The first is the generation of a DES_key_schedule from a key, the second is the actual encryption or decryption. A DES key is of type DES_cblock which consists of 8 bytes with odd parity. The least significant bit in each byte is the parity bit. The key schedule is an expanded platform-dependent form 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 that the 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 block cipher. Note that if you compile and run this example, you will not get the same ciphertext as 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 are unaware 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.52 defines 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 usage mode, 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/des.h>
#include <openssl/rand.h>
 
#define BUFSIZE 1024
 
int 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(&key1);
    DES_random_key(&key2);
    DES_random_key(&key3);
 
    DES_set_key((C_Block *)key1, &ks1);
    DES_set_key((C_Block *)key2, &ks2);
    DES_set_key((C_Block *)key3, &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 < 63; i += 8) {
        DES_ecb3_encrypt((C_Block *)(in + i),(C_Block *)(out + i), &ks1, &ks2, &ks3, DES_ENCRYPT);
    }
 
    printf("Ciphertext:");
    while (e++) printf(" [%02x]", *e++);
    printf("\n");
 
    for (i = 0; i < 63; i += 8) {
        DES_ecb3_encrypt((C_Block *)(out + i),(C_Block *)(back + i), &ks1, &ks2, &ks3, DES_DECRYPT);
    }
 
    printf("Decrypted Text: [%s]\n", back);
 
    exit(0);
}


Read more: http://blog.fpmurphy.com/2010/04/openssl-des-api.html#ixzz2jNzzbaWR

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

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

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


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/des.h>
#include <openssl/rand.h>
 
#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(&key);
    DES_set_odd_parity(&key);
    if (DES_set_key_checked((C_Block *)key, &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, &keysched, &ivec, DES_ENCRYPT);
 
    printf("Ciphertext:");
    while (*e) printf(" [%02x]", *e++);
    printf("\n");
 
    memcpy(ivec, ivsetup, sizeof(ivsetup));
    DES_ncbc_encrypt(out, back, len, &keysched, &ivec, DES_DECRYPT);
 
    printf("Decrypted Text: [%s]\n", back);
 
    exit(0);
}


Read more: http://blog.fpmurphy.com/2010/04/openssl-des-api.html#ixzz2jO0BbAJc

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

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


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/des.h>
#include <openssl/rand.h>
 
#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(&key1);
    DES_random_key(&key2);
    DES_random_key(&key3);
 
    DES_set_key((C_Block *)key1, &ks1);
    DES_set_key((C_Block *)key2, &ks2);
    DES_set_key((C_Block *)key3, &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, &ks1, &ks2, &ks3, &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, &ks1, &ks2, &ks3, &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 first 64 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 Cipher Block Chaining with Output Feedback Masking. This mode provides stronger protection against dictionary attacks and matching ciphertext attacks that exploit the DES blocksize of 64 bits through the introduction of secret masking values that are XOR-ed with the intermediate outputs of each triple-DES encryption operation. Apparantly, however, Eli Biham and Lars Knudsen have developed an attack on this mode but it requires a lot of work.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/des.h>
#include <openssl/rand.h>
 
#define BUFSIZE 512 
#define CBCM_ONE
 
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 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(&key1);
    DES_random_key(&key2);
    DES_random_key(&key3);
 
    DES_set_key((C_Block *)key1, &ks1);
    DES_set_key((C_Block *)key2, &ks2);
    DES_set_key((C_Block *)key3, &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,'\0',sizeof(ivec2));
    len = strlen(in) + 1;
 
#ifdef CBCM_ONE
    DES_ede3_cbcm_encrypt(in, out, len, &ks1, &ks2, &ks3, &ivec2, &ivec1, DES_ENCRYPT);
#else
    DES_ede3_cbcm_encrypt(in, out, 16, &ks1, &ks2, &ks3, &ivec2, &ivec1, DES_ENCRYPT);
    DES_ede3_cbcm_encrypt(&in[16], &out[16],len-16, &ks1, &ks2, &ks3, &ivec2, &ivec1, DES_ENCRYPT);
#endif
 
    printf("Ciphertext:");
    while (*e) printf(" [%02x]", *e+);
    printf("\n");
 
    len = strlen(out) + 1;
    memcpy(ivec2, ivecstr, sizeof(ivecstr));
    memset(ivec1,'\0',sizeof(ivec2));
 
    DES_ede3_cbcm_encrypt(out, back, len, &ks1, &ks2, &ks3, &ivec2, &ivec1, DES_DECRYPT);
 
    printf("Decrypted Text: [%s]\n", back);
 
    exit(0);


Read more: http://blog.fpmurphy.com/2010/04/openssl-des-api.html#ixzz2jO0OJfue

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

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


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/des.h>
#include <openssl/rand.h>
 
#define BUFSIZE 256
#define CFBMODE 1
 
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 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(&key);
    DES_set_key((C_Block *)key, &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, &ks, &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, &ks, &ivec, DES_DECRYPT);
 
    printf("Decrypted Text: [%s]\n", back);
 
    exit(0);
}


Read more: http://blog.fpmurphy.com/2010/04/openssl-des-api.html#ixzz2jO0Yo5gi

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

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/des.h>
 
#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, &ks);
 
    printf("Plaintext: [%s]\n", in);
 
    memcpy(ivec, (C_Block *)ivecstr, sizeof(ivec));
    len = strlen(in) + 1;
 
    DES_cfb64_encrypt(in, out, len, &ks, &ivec, &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, &ks, &ivec, &n, DES_DECRYPT);
 
    printf("Decrypted Text: [%s]\n", back);
 
    exit(0);
}


Read more: http://blog.fpmurphy.com/2010/04/openssl-des-api.html#ixzz2jO0mMiov

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

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



#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/des.h>
#include <openssl/rand.h>
 
#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, &key);
 
    if ((result = DES_set_key_checked((C_Block *)key, &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, &ks, &ivec);
 
    n = 0;
    printf("Ciphertext:");
    while (*e) {
        printf(" [%02x]", *e++);
        n++;
    }
    printf("\n");
    printf("Ciphertext Length: %d\n", n);
 
    len = strlen(out);
    memcpy(ivec, ivecstr, sizeof(ivecstr));
 
    DES_ofb_encrypt(out, back, 8, len, &ks, &ivec);
 
    printf("Decrypted Text: [%s]\n", back);
 
    exit(0);
}


Read more: http://blog.fpmurphy.com/2010/04/openssl-des-api.html#ixzz2jO0rUqYv

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, I set  k1 = k2 = k3 . I will leave it up to you to modify the example to support the case where  k1 != k2 != k3 .

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/des.h>
 
#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, &key);
 
    if ((result = DES_set_key_checked((C_Block *)key, &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 < len; i++) {
        DES_ede3_ofb64_encrypt(&(in[i]), &(out[i]), 1, &ks, &ks, &ks, &ivec, &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 < len; i++) {
        DES_ede3_ofb64_encrypt(&(out[i]), &(back[i]), 1, &ks, &ks, &ks, &ivec, &num);
    }
 
    printf("Decrypted Text: [%s]\n", back);
 
    exit(0);
}


Read more: http://blog.fpmurphy.com/2010/04/openssl-des-api.html#ixzz2jO13z2XP


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值