An encryption and decryption algorithm and mode is selected with one of the following:
Algorithm options:
The mecevp engine wraps the EVP API with four new functions:
All cipher data is written and read in base64 format.
A higher-level interface for message encryption/decryption in parts (such as individual XML elements) is defined by two new functions:
Compile all source codes with -DWITH_OPENSSL and link with ssl and crypto libraries.
Here is an example to encrypt a message while streaming it to the output. The example uses the public key of the recipient/reader of the message. The recipient/reader uses its private key to decrypt. Envelope encryption is used with SOAP_MEC_ENV_ENC_DES_CBC, which means an ephemeral secret key is generated and encrypted with the public key. This encrypted secret key should be communicated to the recipient/reader with the message to decrypt:
#include "mecevp.h" soap_mec_data mec; ns__Object object; int alg = SOAP_MEC_ENV_ENC_DES_CBC; FILE *fd = fopen("key.pem", "r"); EVP_PKEY *pubk; unsigned char *key; int keylen; if (...) // key file contains public key? pubk = PEM_read_PUBKEY(fd, NULL, NULL, NULL); else // key file contains certificate { X509 *cert = PEM_read_X509(fd, NULL, NULL, NULL); pubk = X509_get_pubkey(cert); X509_free(cert); } fclose(fd); key = soap_malloc(soap, soap_mec_size(alg, pubk)); if (soap_begin_send(soap) || soap_mec_begin(soap, &mec, alg, pubk, key, &keylen) || soap_mec_start(soap, NULL) || soap_out_ns__Object(soap, "ns:Object", 0, &object, NULL) || soap_mec_stop(soap) || soap_smd_end(soap, &mec) || soap_end_send(soap)) { soap_mec_cleanup(soap, &mec); // clean up when error soap_print_fault(soap, stderr); } EVP_PKEY_free(pubk);
The decryption by the recipient/reader requires the ephemeral encrypted secret key generated by soap_mec_begin by the sender (as set above) to decrypt the message using envelope decryption with SOAP_MEC_ENV_DEC_DES_CBC.
#include "mecevp.h" soap_mec_data mec; ns__Object object; int alg = SOAP_MEC_ENV_DEC_DES_CBC; FILE *fd = fopen("key.pem", "r"); EVP_PKEY *privk = PEM_read_PrivateKey(fd, NULL, NULL, "password"); unsigned char *key; int keylen; fclose(fd); key = ... // value set as above by sender keylen = ... // value set as above by sender if (soap_begin_recv(soap) || soap_mec_begin(soap, &mec, alg, privk, key, &keylen) || soap_mec_start(soap) || soap_in_ns__Object(soap, "ns:Object", &object, NULL) == NULL || soap_mec_stop(soap) || soap_mec_end(soap, &mec) || soap_end_recv(soap)) { soap_mec_cleanup(soap, &mec); // clean up when error soap_print_fault(soap, stderr); } EVP_PKEY_free(privk);
Note that the encrypted secret key can be send in the clear or stored openly, since only the recipient/reader will be able to decode it for use in message decryption.
Symmetric encryption and decryption can be used if both parties can safely share a secret symmetric key that no other party has access to. We use SOAP_MEC_ENC_DES_CBC for encryption and SOAP_MEC_DEC_DES_CBC for decryption using a 160-bit triple DES key.
Here is an example to encrypt a message using a shared secret key while streaming it to the output.
#include "mecevp.h" soap_mec_data mec; ns__Object object; int alg = SOAP_MEC_ENC_DES_CBC; unsigned char key[20] = { ... }; // shared secret triple DES key int keylen = 20; if (soap_begin_send(soap) || soap_mec_begin(soap, &mec, alg, NULL, key, &keylen) || soap_mec_start(soap, NULL) || soap_out_ns__Object(soap, "ns:Object", 0, &object, NULL) || soap_mec_stop(soap) || soap_smd_end(soap, &mec) || soap_end_send(soap)) { soap_mec_cleanup(soap, &mec); // clean up when error soap_print_fault(soap, stderr); }
The decryption by the recipient/reader requires the same shared secret key to decrypt the message using envelope decryption with SOAP_MEC_DEC_DES_CBC. This key is secret and unencrypted, so it should never be shared with any other party besides the sender/writer and recipient/reader.
#include "mecevp.h" soap_mec_data mec; ns__Object object; int alg = SOAP_MEC_DEC_DES_CBC; unsigned char key[20] = { ... }; // shared secret triple DES key int keylen = 20; if (soap_begin_recv(soap) || soap_mec_begin(soap, &mec, alg, NULL, key, &keylen) || soap_mec_start(soap) || soap_in_ns__Object(soap, "ns:Object", &object, NULL) == NULL || soap_mec_stop(soap) || soap_mec_end(soap, &mec) || soap_end_recv(soap)) { soap_mec_cleanup(soap, &mec); // clean up when error soap_print_fault(soap, stderr); }
Note: the mecevp engine uses callbacks of the gSOAP engine that were introduced in version 2.8.1. Earlier gSOAP version releases are not compatible with the mecevp plugin and engine.