#include "xmlsecrb.h"
VALUE sign_with_certificate(VALUE self, VALUE rb_key_name, VALUE rb_rsa_key, VALUE rb_cert) {
xmlDocPtr doc;
xmlNodePtr signNode = NULL;
xmlNodePtr refNode = NULL;
xmlNodePtr keyInfoNode = NULL;
xmlSecDSigCtxPtr dsigCtx = NULL;
char *keyName;
char *certificate;
char *rsaKey;
unsigned int rsaKeyLength, certificateLength;
Data_Get_Struct(self, xmlDoc, doc);
rsaKey = RSTRING_PTR(rb_rsa_key);
rsaKeyLength = RSTRING_LEN(rb_rsa_key);
keyName = RSTRING_PTR(rb_key_name);
certificate = RSTRING_PTR(rb_cert);
certificateLength = RSTRING_LEN(rb_cert);
// create signature template for RSA-SHA1 enveloped signature
signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId,
xmlSecTransformRsaSha1Id, NULL);
if (signNode == NULL) {
rb_raise(rb_eSigningError, "failed to create signature template");
goto done;
}
// add node to the doc
xmlAddChild(xmlDocGetRootElement(doc), signNode);
// add reference
refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id,
NULL, NULL, NULL);
if(refNode == NULL) {
rb_raise(rb_eSigningError, "failed to add reference to signature template");
goto done;
}
// add enveloped transform
if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) {
rb_raise(rb_eSigningError, "failed to add enveloped transform to reference");
goto done;
}
// add and
keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
if(keyInfoNode == NULL) {
rb_raise(rb_eSigningError, "failed to add key info");
goto done;
}
if(xmlSecTmplKeyInfoAddX509Data(keyInfoNode) == NULL) {
rb_raise(rb_eSigningError, "failed to add X509Data node");
goto done;
}
// create signature context, we don't need keys manager in this example
dsigCtx = xmlSecDSigCtxCreate(NULL);
if(dsigCtx == NULL) {
rb_raise(rb_eSigningError, "failed to create signature context");
goto done;
}
// load private key, assuming that there is not password
dsigCtx->signKey = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)rsaKey,
rsaKeyLength,
xmlSecKeyDataFormatPem,
NULL, // password
NULL,
NULL);
if(dsigCtx->signKey == NULL) {
rb_raise(rb_eSigningError, "failed to load private key");
goto done;
}
// load certificate and add to the key
if(xmlSecCryptoAppKeyCertLoadMemory(dsigCtx->signKey,
(xmlSecByte *)certificate,
certificateLength,
xmlSecKeyDataFormatPem) < 0) {
rb_raise(rb_eSigningError, "failed to load certificate");
goto done;
}
// set key name
if(xmlSecKeySetName(dsigCtx->signKey, (xmlSecByte *)keyName) < 0) {
rb_raise(rb_eSigningError, "failed to set key name");
goto done;
}
// sign the template
if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) {
rb_raise(rb_eSigningError, "signature failed");
goto done;
}
done:
if(dsigCtx != NULL) {
xmlSecDSigCtxDestroy(dsigCtx);
}
return T_NIL;
}