157
Note that the number of bytes written by
EVP_EncryptFinal
should always be 8 when using 64-bit blocks and when padding is enabled.
6.2.5 Decryption
As expected, the decryption API looks similar to the encryption API. After cipher initialization, two methods are involved,
EVP_DecryptUpdate
and
EVP_DecryptFinal
. You can pass as much data as you want into
EVP_DecryptUpdate
. When using a block-based mode ECB or CBC, you can pass in partial blocks of text, but
EVP_DecryptUpdate
will output only whole blocks. The rest will be stored until there is more data to be processed, or until
EVP_DecryptFinal
is called. Moreover, if the contexts cached ciphertext plus the length of the new ciphertext is exactly block-aligned, the entire final block will
be held in the context instead of getting output. With CFB and OFB modes and with stream ciphers, theres no padding, so the size of the resulting ciphertext will be equal to the size of the
plaintext.
If using a block-based mode,
EVP_DecryptFinal
first checks to see if the padding on the last block is in the right format. If not, the function returns 0, signifying failure. Otherwise, it flushes
any remaining data to the buffer passed in as the second argument, and writes the number of bytes flushed into the third argument, a reference parameter. For other modes, this call does nothing.
Example 6-5 shows a simple function that decrypts a block of encrypted text into a dynamically
allocated buffer and returns it. This function can be used to incrementally decrypt, and thus requires
EVP_DecryptFinal
to be called when a block-based mode is used. Of course,
EVP_DecryptInit
should always be called before passing a context to this function.
Example 6-5. Decrypting ciphertext
char decrypt_exampleEVP_CIPHER_CTX ctx, char ct, int inl {
Were going to null-terminate the plaintext under the assumption its
non-null terminated ASCII text. The null can be ignored otherwise.
char pt = char mallocinl + EVP_CIPHER_CTX_block_sizectx + 1;
int ol; EVP_DecryptUpdatectx, pt, ol, ct, inl;
if ol theres no block to decrypt {
freept; return NULL;
} pt[ol] = 0;
return pt; }
As is the case with encryption, factoring in the ciphers block length is strictly only necessary when using a block-based cipher mode.
Using the above function, and the ones we previously developed, lets look at Example 6-6
, which encrypts a 15-byte string using Blowfish in CBC mode, then passes it into
decrypt_example
in two parts. Note, we use the macro
EVP_MAX_BLOCK_LENGTH
, which exists only in 0.9.7 and
158
later. If you are using an earlier version of OpenSSL, you can define this macro to the value 64, which is the largest possible block size in 0.9.6c and earlier.
Example 6-6. Using the example encryption and decryption functions
int mainint argc, char argv[] {
EVP_CIPHER_CTX ctx; char key[EVP_MAX_KEY_LENGTH];
char iv[EVP_MAX_IV_LENGTH]; char ct, out;
char final[EVP_MAX_BLOCK_LENGTH]; char str[] = 123456789abcdef;
int i; if seed_prng
{ printfFatal Error Unable to seed the PRNG\n;
abort; }
select_random_keykey, EVP_MAX_KEY_LENGTH; select_random_iviv, EVP_MAX_IV_LENGTH;
EVP_EncryptInitctx, EVP_bf_cbc, key, iv; ct = encrypt_examplectx, str, strlenstr, i;
printfCiphertext is d bytes.\n, i; EVP_DecryptInitctx, EVP_bf_cbc, key, iv;
out = decrypt_examplectx, ct, 8; printfDecrypted: s\n, out;
out = decrypt_examplectx, ct + 8, 8; printfDecrypted: s\n, out;
if EVP_DecryptFinalctx, final, i {
printfPadding incorrect.\n; abort;
} final[i] = 0;
printfDecrypted: s\n, final; }
If we run this example, the first time we try to output decrypted plaintext, we will see nothing, even though we fed the decryption routine a full block of data. Note that when we feed the
remainder of the data, we are passing in eight bytes, because the encryption routine padded the data to a block-aligned length. At that point, one block will be output, and the second block will
be held in reserve until there is more data, or until
EVP_DecryptFinal
is called. If we were to change the cipher to RC4, the above example would compile, but give slightly
incorrect output. The length of the encrypted text would be 15 bytes, not 16, due to the lack of padding. As a result, passing in 16 bytes of ciphertext to the decrypt routine will cause a block of
garbage to be decrypted. Changing the third argument in the second call to
decrypt_example
to seven fixes the problem.
6.2.6 Handling UDP Traffic with Counter Mode