I've seen many questions on OpenSSL and EVP, but not very many clear answers, but I figured I'd still post my question here and hope for better feedback.
The materials given to me are a signed file "symmetrickey.bin", an RSA key set "privatekey_A.pem", "publickey_A.pem", and the other user's public key "publickey_B.pem".
What I need to do is:
symmetrickey.bin
and store it into a text file.message.txt
using the symmetrickey.txt
and some algorithm like AES for example.privatekey_A.pem
and write to a file cipher.bin
.cipher.bin
.The issues I'm having are understanding how to implement the OpenSSL EVP libraries. The API page is not very clear about where the values for each function comes from. For example, EVP_OpenInit()
where am I getting ek
or the length of ek
"ekl"? Is "prvi" a private key? And how am I to know the type? These are things I'm not given.
I've looked at many implementations and most don't answer my questions or they give crazy code with little to no explanation of what's going on or where values are coming from. I'm posting here as a last resort...
For the sign/unsign key part I need further information, how is this signature done? For example, is this signature an X byte length at the end of the file and can then easily be removed?
For items 2-5 in your list the following code will surely assist, it is based on the examples from openssl documentation with more comments and adaptations for your needs. Feel free to ask if you have any questions that are not commented!
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <openssl/evp.h>
#define APPNAME "C"
#define CHUNK_SIZE 512
int do_crypt(FILE *in, FILE *out, int do_encrypt)
{
/* Allow enough space in output buffer for additional block */
unsigned char inbuf[CHUNK_SIZE];
unsigned char outbuf[CHUNK_SIZE + EVP_MAX_BLOCK_LENGTH];
int inlen;
int outlen;
EVP_CIPHER_CTX ctx;
/* Bogus key and IV: we'd normally set these from
* another source.
*/
unsigned char key[] = { 0x13, 0xa3, 0xb4, 0xc1, 0x24, 0x19, 0xf5, 0x23, 0x18, 0xef, 0xca, 0x12, 0x4c, 0x9f, 0x14, 0xfe };
unsigned char iv[] = { 0x92, 0x1c, 0x23, 0x3f, 0x5e, 0x10, 0x3d, 0x9a };
/* Don't set key or IV because we will modify the parameters */
EVP_CIPHER_CTX_init(&ctx);
/* Using Blowfish encryption with cbc algorithm, you can use whichever is supported in openssl if you wish */
EVP_CipherInit_ex(&ctx, EVP_bf_cbc(), NULL, NULL, NULL, do_encrypt);
EVP_CIPHER_CTX_set_key_length(&ctx, 16);
/* We finished modifying parameters so now we can set key and IV */
EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, do_encrypt);
for(;;)
{
inlen = fread(inbuf, 1, CHUNK_SIZE, in);
if(inlen <= 0) break;
if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen))
{
/* Error */
EVP_CIPHER_CTX_cleanup(&ctx);
return -1;
}
fwrite(outbuf, 1, outlen, out);
}
if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen))
{
/* Error */
EVP_CIPHER_CTX_cleanup(&ctx);
return -1;
}
fwrite(outbuf, 1, outlen, out);
EVP_CIPHER_CTX_cleanup(&ctx);
rewind(in);
rewind(out);
return 0;
}
/* This is the standalone encryptor entry point */
int main(int argc, char** argv)
{
FILE *encode_file;
FILE *decode_file;
int enc_or_dec;
if (argc < 4)
{
printf("Usage: %s [plain file] [encrypted file] [0/1 deccrypt/encrypt]\n", argv[0]);
return -1;
}
encode_file = fopen(argv[1], "r");
decode_file = fopen(argv[2], "w+");
/* Stupid decimal translation */
enc_or_dec = *argv[3]-48;
do_crypt(encode_file, decode_file, enc_or_dec);
return 0;
}
And the Makefile:
all:
gcc cryptor.c -o cryptor -g -lcrypto -I ../openssl-1.0.1f-host/include
clean:
rm cryptor
This code does not use EVP_OpenInit()
because it is used only for decryption, while my method (and your needs) require both encryption or decryption. While you can use EVP_OpenInit()
to initialize a decryption context, I replaced the single call suitable only for decryption with two calls suitable for both encryption and decryption.
From the man page:
EVP_OpenInit()
initializes a cipher contextctx
for decryption with cipher type. It decrypts the encrypted symmetric key of lengthekl
bytes passed in theek
parameter using the private keypriv
. The IV is supplied in theiv
parameter.EVP_OpenUpdate()
andEVP_OpenFinal()
have exactly the same properties as theEVP_DecryptUpdate()
andEVP_DecryptFinal()
routines, as documented on theEVP_EncryptInit(3)
manual page.
EVP_OpenInit()
for key files
If the signed file you are referring to is a public key file in RSA/DSA or similar format, you can use this StackOverflow question for a better method than mine as it does the key extraction from the file automatically (and uses EVP_OpenInit()
like you require)