A digest or signature algorithm is selected with one the following constants:
The smdevp engine wraps the EVP API with three new functions:
A higher-level interface for computing (signed) message digests over messages produced by the gSOAP enginre is defined by two new functions:
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.