gSOAP WS-Security: The smdevp engine

Main Page | Class List | File List | Class Members | File Members | Related Pages

# The smdevp engine

The gSOAP smdevp engine computes (signed) message digests over any type of data using the EVP interface of OpenSSL. It currently supports MD5, SHA1, HMAC_SHA1, DSA_SHA1, and RSA_SHA1.

A digest or signature algorithm is selected with one the following constants:

- SOAP_SMD_DGST_MD5 to compute MD5 128-bit digests
- SOAP_SMD_DGST_SHA1 to compute MD5 160-bit digests
- SOAP_SMD_HMAC_SHA1 to compute HMAC-SHA1 message authentication code
- SOAP_SMD_SIGN_DSA_SHA1 to compute DSA-SHA1 signatures
- SOAP_SMD_SIGN_RSA_SHA1 to compute RSA-SHA1 signatures
- SOAP_SMD_VRFY_DSA_SHA1 to verify DSA-SHA1 signatures
- SOAP_SMD_VRFY_RSA_SHA1 to verify RSA-SHA1 signatures

The smdevp engine wraps the EVP API with three new functions:

- soap_smd_init to initialize the engine
- soap_smd_update to update the state with a message part
- soap_smd_final to compute the digest, signature, or verify a signature

A higher-level interface for computing (signed) message digests over messages produced by the gSOAP enginre is defined by two new functions:

- soap_smd_begin to start a digest or signature computation/verification
- soap_smd_end to complete a digest/signature computation/verification

Here is an example to sign an XML serialized C++ object using an RSA private key applied to the SHA1 digest of the serialized object:

        ns__Object *object = ...;
        int alg = SOAP_SMD_SIGN_RSA_SHA1;
        FILE *fd = fopen("key.pem", "r");
        EVP_PKEY *key = PEM_read_PrivateKey(fd, NULL, NULL, "password");
        char *sig = (char*)soap_malloc(soap, soap_smd_size(alg, key));
        int siglen;
        fclose(fd);
        if (soap_smd_begin(soap, alg, key, 0)
         || soap_out_ns__Object(soap, "ns:Object", 0, object, NULL)
         || soap_smd_end(soap, sig, &siglen))
          soap_print_fault(soap, stderr);
        else
          ... // sig contains RSA-SHA1 signature of length siglen

To verify the signature, we use the RSA public key and re-run the octet stream (by re-serialization in this example) through the smdevp engine using the SOAP_SMD_VRFY_RSA_SHA1 algorithm. Note that a PEM file may contain both the (encrypted) private and public keys.

        char *sig = ...;
        int siglen = ...;
        ns__Object *object = ...;
        int alg = SOAP_SMD_VRFY_RSA_SHA1;
        FILE *fd = fopen("key.pem", "r");
        EVP_PKEY *key = PEM_read_PUBKEY(fd, NULL, NULL, NULL);
        fclose(fd);
        if (soap_smd_begin(soap, alg, key, 0)
         || soap_out_ns__Object(soap, "ns:Object", 0, object, NULL)
         || soap_smd_end(soap, sig, &siglen))
          soap_print_fault(soap, stderr);
        else
          ... // sig verified, i.e. signed object was not changed

The HMAC algorithm uses a secret key (which both the sender and receiver must keep secret) to sign and verify a message:

        ns__Object *object = ...;
        int alg = SOAP_SMD_HMAC_SHA1;
        static char key[16] =
        { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
          0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00 };
        char *sig = (char*)soap_malloc(soap, soap_smd_size(alg, NULL));
        int siglen;
        if (soap_smd_begin(soap, alg, key, sizeof(key))
         || soap_out_ns__Object(soap, "ns:Object", 0, object, NULL)
         || soap_smd_end(soap, sig, &siglen))
          soap_print_fault(soap, stderr);
        else
          ... // sig holds the signature

Note: HMAC signature verification proceeds by recomputing the signature value for comparison.

A digest is a hash value of an octet stream computed using the MD5 or SHA1 algorithms:

        ns__Object *object = ...;
        int alg = SOAP_SMD_DGST_SHA1;
        char *digest = (char*)soap_malloc(soap, soap_smd_size(alg, NULL));
        int digestlen;
        if (soap_smd_begin(soap, alg, NULL, 0)
         || soap_out_ns__Object(soap, "ns:Object", 0, object, NULL)
         || soap_smd_end(soap, digest, &digestlen))
          soap_print_fault(soap, stderr);
        else
          ... // digest holds hash value of serialized object

Note that indentation (SOAP_XML_INDENT) and exc-c14n canonicalization (SOAP_XML_CANONICAL) affects the XML serialization format and, therefore, the digest or signature produced.