-
Notifications
You must be signed in to change notification settings - Fork 113
Tutorial Sign And Encrypt
The XML Security Library performs signing or encryption by processing a template that specifies the signing or encryption parameters (transforms, algorithms, keys, etc.) and, optionally, the input XML or binary data if it is not already included in the template. The template has the same structure as the desired result, but some of its nodes might be empty. The XML Security Library finds the key for signing or encryption in the keys manager or in the signing/encryption context, performs the required cryptographic operations, and finally writes the results to the output XML document. The signing/encryption context controls the process and stores the required temporary data.

A typical signature process includes the following steps:
- Create or load a signature template, and select the dsig:Signature node.
- Create a signature context using the xmlSecDSigCtxCreate function.
- Load the signing key(s), X509 certificates, etc. into the
keys manager
or set the key in the signature context (the
signKeymember of the xmlSecDSigCtx structure). - Sign the data by calling the xmlSecDSigCtxSign function.
- Check the returned value to make sure there are no errors.
- Destroy the signature context using the xmlSecDSigCtxDestroy function.
/**
* @brief Signs an XML template file using a private key.
* @details Signs the #tmpl_file using private key from #key_file.
* @param tmpl_file the signature template file name.
* @param key_file the PEM private key file name.
* @return 0 on success or a negative value if an error occurs.
*/
int
sign_file(const char* tmpl_file, const char* key_file) {
xmlDocPtr doc = NULL;
xmlNodePtr node = NULL;
xmlSecDSigCtxPtr dsigCtx = NULL;
int res = -1;
assert(tmpl_file);
assert(key_file);
/* load template */
doc = xmlReadFile(tmpl_file, NULL, XML_PARSE_PEDANTIC | XML_PARSE_NONET | XML_PARSE_NOENT);
if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
fprintf(stderr, "Error: unable to parse file \"%s\"\n", tmpl_file);
goto done;
}
/* find start node */
node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
if(node == NULL) {
fprintf(stderr, "Error: start node not found in \"%s\"\n", tmpl_file);
goto done;
}
/* create signature context, we don't need keys manager in this example */
dsigCtx = xmlSecDSigCtxCreate(NULL);
if(dsigCtx == NULL) {
fprintf(stderr,"Error: failed to create signature context\n");
goto done;
}
/* load private key, assuming that there is no password */
dsigCtx->signKey = xmlSecCryptoAppKeyLoadEx(key_file,
xmlSecKeyDataTypePrivate,
xmlSecKeyDataFormatPem,
NULL,
NULL,
NULL);
if(dsigCtx->signKey == NULL) {
fprintf(stderr,"Error: failed to load private pem key from \"%s\"\n", key_file);
goto done;
}
/* set the key name to the file name; this is only an example */
if(xmlSecKeySetName(dsigCtx->signKey, BAD_CAST key_file) < 0) {
fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
goto done;
}
/* sign the template */
if(xmlSecDSigCtxSign(dsigCtx, node) < 0) {
fprintf(stderr,"Error: signature failed\n");
goto done;
}
/* print signed document to stdout */
xmlDocDump(stdout, doc);
/* success */
res = 0;
done:
/* cleanup */
if(dsigCtx != NULL) {
xmlSecDSigCtxDestroy(dsigCtx);
}
if(doc != NULL) {
xmlFreeDoc(doc);
}
return(res);
}A typical encryption process includes the following steps:
- Create or load an encryption template and select the starting enc:EncryptedData node.
- Create an encryption context using the xmlSecEncCtxCreate function.
- Load the encryption key(s), X509 certificates, etc. into the
keys manager
or set the key in the encryption context (the
encKeymember of xmlSecEncCtx structure). - Encrypt the data by calling one of the following functions:
- Check the returned value to make sure there are no errors.
- Destroy the encryption context using the xmlSecEncCtxDestroy function.
/**
* @brief Encrypts binary data using a DES key and a template file.
* @details Encrypts binary #data using template from #tmpl_file and DES key from
* #key_file.
* @param tmpl_file the encryption template file name.
* @param key_file the Triple DES key file.
* @param data the binary data to encrypt.
* @param dataSize the binary data size.
* @return 0 on success or a negative value if an error occurs.
*/
int
encrypt_file(const char* tmpl_file, const char* key_file,
const unsigned char* data, size_t dataSize) {
xmlDocPtr doc = NULL;
xmlNodePtr node = NULL;
xmlSecEncCtxPtr encCtx = NULL;
int res = -1;
assert(tmpl_file);
assert(key_file);
assert(data);
/* load template */
doc = xmlReadFile(tmpl_file, NULL, XML_PARSE_PEDANTIC | XML_PARSE_NONET | XML_PARSE_NOENT);
if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
fprintf(stderr, "Error: unable to parse file \"%s\"\n", tmpl_file);
goto done;
}
/* find start node */
node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs);
if(node == NULL) {
fprintf(stderr, "Error: start node not found in \"%s\"\n", tmpl_file);
goto done;
}
/* create encryption context, we don't need keys manager in this example */
encCtx = xmlSecEncCtxCreate(NULL);
if(encCtx == NULL) {
fprintf(stderr,"Error: failed to create encryption context\n");
goto done;
}
/* load DES key, assuming that there is no password */
encCtx->encKey = xmlSecKeyReadBinaryFile(xmlSecKeyDataDesId, key_file);
if(encCtx->encKey == NULL) {
fprintf(stderr,"Error: failed to load des key from binary file \"%s\"\n", key_file);
goto done;
}
/* set the key name to the file name; this is only an example */
if(xmlSecKeySetName(encCtx->encKey, BAD_CAST key_file) < 0) {
fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
goto done;
}
/* encrypt the data */
if(xmlSecEncCtxBinaryEncrypt(encCtx, node, data, dataSize) < 0) {
fprintf(stderr,"Error: encryption failed\n");
goto done;
}
/* print encrypted data with document to stdout */
xmlDocDump(stdout, doc);
/* success */
res = 0;
done:
/* cleanup */
if(encCtx != NULL) {
xmlSecEncCtxDestroy(encCtx);
}
if(doc != NULL) {
xmlFreeDoc(doc);
}
return(res);
}