Okay to use OpenSSL to encrypt then sign a message? I am planning on encrypting a message then signing the message so the recipient can authenticate the source. Reading this article has me concerned that I'm doing something wrong.

My current plan is to use OpenSSL to do the following:


Create a random key
Use key to encrypt message with a block cypher
Encrypt key with recipient's public RSA key
tar the encrypted message and encrypted key
sign the encrypted package using openssl dgst
tar the signature and encrypted package for delivery


Is there anything wrong with this approach?

This is being used for transferring firmware for an embedded device. The firmware includes an entire filesystem, including a private key. It needs to be encrypted so the private key is not exposed, and it needs to be authenticated so that a third party cannot install their own firmware and have access to the device (and the private key within).
I see a few issues with this approach:


First, since you're signing the ciphertext and sending the signature in plain, anyone who has your public key can verify that you did, in fact, sign that message, even if they won't be able to actually decrypt it.  This may or may not be something you want.
More importantly, anyone who intercepts the message can strip your signature and substitute their own (or, if the protocol allows it, leave the message unsigned).
Further, if the symmetric cipher used to encrypt the actual message is malleable (as e.g. many common non-authenticating block cipher modes are, at least to some extent), the interceptor might also be able to modify the message before re-signing it, for example replacing an embedded copy of your name or public key with their own.


The obvious solution to these problems is to follow the advice in the article you linked to:


Combine (e.g. tar) the plaintext and the public key of the recipient.
Sign the combined plaintext and recipient's public key.
Combine (e.g. tar) the signature and the signed message.
Generate a random key and encrypt the combined message and signature with a symmetric cipher using that key.
Encrypt the random key with the recipient's public key.
Combine the encrypted message from step 4 and the encrypted key from step 5.


I've followed your example above in keeping the symmetric and asymmetric encryption steps (4 and 5) separate &mdash; I'm not familiar with the OpenSSL tools, but many public key crypto implementations provide a way to do both in one step, since it's the only practical way to encrypt large messages with asymmetric crypto.  Similarly, the signing step typically involves first hashing the message and then signing the hash, but I haven't explicitly separated those steps since you didn't either.

Ps. It would also be possible (and perhaps preferable) to use key encapsulation (KEM) in steps 4 and 5, if your crypto toolchain supports it.  Basically, instead of generating a random symmetric key and then encrypting it with the recipient's public key (which generally involves padding and other complex details), you generate a random chunk of data within the message space of the asymmetric cipher (e.g. a random number less than the modulus, for RSA), encrypt it using the plain "textbook" version of the asymmetric cipher (with no padding or other complications), and also hash it to obtain the key for the symmetric cipher.  The recipient then decrypts the random data with their private key and hashes it to obtain the symmetric key.  The advantage of KEM is mainly one of simplicity, though, so if you're already working with a toolchain that supports normal asymmetric encryption with padding, but not KEM, then it's probably not worth it.