nokogiri-xmlsec-me-harder 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +13 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +123 -0
  9. data/Rakefile +30 -0
  10. data/ext/nokogiri_ext_xmlsec/common.h +13 -0
  11. data/ext/nokogiri_ext_xmlsec/extconf.rb +27 -0
  12. data/ext/nokogiri_ext_xmlsec/init.c +76 -0
  13. data/ext/nokogiri_ext_xmlsec/nokogiri_decrypt_with_key.c +82 -0
  14. data/ext/nokogiri_ext_xmlsec/nokogiri_encrypt_with_key.c +169 -0
  15. data/ext/nokogiri_ext_xmlsec/nokogiri_helpers_set_attribute_id.c +76 -0
  16. data/ext/nokogiri_ext_xmlsec/nokogiri_init.c +32 -0
  17. data/ext/nokogiri_ext_xmlsec/nokogiri_sign_certificate.c +186 -0
  18. data/ext/nokogiri_ext_xmlsec/nokogiri_sign_rsa.c +167 -0
  19. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_certificates.c +138 -0
  20. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_named_keys.c +133 -0
  21. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_rsa.c +76 -0
  22. data/ext/nokogiri_ext_xmlsec/options.c +166 -0
  23. data/ext/nokogiri_ext_xmlsec/options.h +36 -0
  24. data/ext/nokogiri_ext_xmlsec/shutdown.c +12 -0
  25. data/ext/nokogiri_ext_xmlsec/util.c +139 -0
  26. data/ext/nokogiri_ext_xmlsec/util.h +42 -0
  27. data/ext/nokogiri_ext_xmlsec/xmlsecrb.h +44 -0
  28. data/lib/nokogiri-xmlsec.rb +1 -0
  29. data/lib/xmlsec.rb +104 -0
  30. data/lib/xmlsec/version.rb +3 -0
  31. data/nokogiri-xmlsec-me-harder.gemspec +39 -0
  32. data/spec/fixtures/cert/server.crt +14 -0
  33. data/spec/fixtures/cert/server.csr +11 -0
  34. data/spec/fixtures/cert/server.key.decrypted +15 -0
  35. data/spec/fixtures/cert/server.key.encrypted +18 -0
  36. data/spec/fixtures/hate.xml +7 -0
  37. data/spec/fixtures/pwned.xml +1 -0
  38. data/spec/fixtures/rsa.pem +15 -0
  39. data/spec/fixtures/rsa.pub +6 -0
  40. data/spec/fixtures/sign2-doc.xml +6 -0
  41. data/spec/fixtures/sign2-result.xml +25 -0
  42. data/spec/fixtures/sign3-result.xml +38 -0
  43. data/spec/lib/nokogiri/xml/document/encryption_and_decryption_spec.rb +34 -0
  44. data/spec/lib/nokogiri/xml/document/signing_and_verifying_spec.rb +123 -0
  45. data/spec/lib/nokogiri/xml/document/unsafe_xml_spec.rb +61 -0
  46. data/spec/spec_helper.rb +10 -0
  47. metadata +213 -0
@@ -0,0 +1,76 @@
1
+ #include "xmlsecrb.h"
2
+ #include "util.h"
3
+
4
+ VALUE set_id_attribute(VALUE self, VALUE rb_attr_name) {
5
+ VALUE rb_exception_result = Qnil;
6
+ const char* exception_message = NULL;
7
+
8
+ xmlNodePtr node = NULL;
9
+ xmlAttrPtr attr = NULL;
10
+ xmlAttrPtr tmp = NULL;
11
+ xmlChar *name = NULL;
12
+ char *idName = NULL;
13
+ char *exception_attribute_arg = NULL;
14
+
15
+ resetXmlSecError();
16
+
17
+ Data_Get_Struct(self, xmlNode, node);
18
+ Check_Type(rb_attr_name, T_STRING);
19
+ idName = StringValueCStr(rb_attr_name);
20
+
21
+ // find pointer to id attribute
22
+ attr = xmlHasProp(node, (const xmlChar* )idName);
23
+ if((attr == NULL) || (attr->children == NULL)) {
24
+ rb_exception_result = rb_eRuntimeError;
25
+ exception_message = "Can't find attribute to add register as id";
26
+ goto done;
27
+ }
28
+
29
+ // get the attribute (id) value
30
+ name = xmlNodeListGetString(node->doc, attr->children, 1);
31
+ if(name == NULL) {
32
+ rb_exception_result = rb_eRuntimeError;
33
+ exception_message = "has no value";
34
+ exception_attribute_arg = idName;
35
+ goto done;
36
+ }
37
+
38
+ // check that we don't have that id already registered
39
+ tmp = xmlGetID(node->doc, name);
40
+ if(tmp != NULL) {
41
+ rb_exception_result = rb_eRuntimeError;
42
+ exception_message = "is already an ID";
43
+ exception_attribute_arg = idName;
44
+ goto done;
45
+ }
46
+
47
+ // finally register id
48
+ xmlAddID(NULL, node->doc, name, attr);
49
+
50
+ done:
51
+ // and do not forget to cleanup
52
+ if (name) {
53
+ xmlFree(name);
54
+ }
55
+
56
+ if(rb_exception_result != Qnil) {
57
+ if (exception_attribute_arg) {
58
+ if (hasXmlSecLastError()) {
59
+ rb_raise(rb_exception_result, "Attribute %s %s, XmlSec error: %s",
60
+ exception_attribute_arg, exception_message, getXmlSecLastError());
61
+ } else {
62
+ rb_raise(rb_exception_result, "Attribute %s %s",
63
+ exception_attribute_arg, exception_message);
64
+ }
65
+ } else {
66
+ if (hasXmlSecLastError()) {
67
+ rb_raise(rb_exception_result, "%s, XmlSec error: %s", exception_message,
68
+ getXmlSecLastError());
69
+ } else {
70
+ rb_raise(rb_exception_result, "%s", exception_message);
71
+ }
72
+ }
73
+ }
74
+
75
+ return Qtrue;
76
+ }
@@ -0,0 +1,32 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ VALUE rb_cNokogiri_XML_Document = Qnil;
4
+ VALUE rb_cNokogiri_XML_Node = Qnil;
5
+ VALUE rb_eSigningError = Qnil;
6
+ VALUE rb_eVerificationError = Qnil;
7
+ VALUE rb_eKeystoreError = Qnil;
8
+ VALUE rb_eEncryptionError = Qnil;
9
+ VALUE rb_eDecryptionError = Qnil;
10
+
11
+ void Init_Nokogiri_ext() {
12
+ VALUE XMLSec = rb_define_module("XMLSec");
13
+ VALUE Nokogiri = rb_define_module("Nokogiri");
14
+ VALUE Nokogiri_XML = rb_define_module_under(Nokogiri, "XML");
15
+ rb_cNokogiri_XML_Document = rb_const_get(Nokogiri_XML, rb_intern("Document"));
16
+ rb_cNokogiri_XML_Node = rb_const_get(Nokogiri_XML, rb_intern("Node"));
17
+
18
+ rb_define_method(rb_cNokogiri_XML_Document, "sign_with_key", sign_with_key, 1);
19
+ rb_define_method(rb_cNokogiri_XML_Document, "sign_with_certificate", sign_with_certificate, 1);
20
+ rb_define_method(rb_cNokogiri_XML_Document, "verify_with_rsa_key", verify_signature_with_rsa_key, 1);
21
+ rb_define_method(rb_cNokogiri_XML_Document, "verify_with_named_keys", verify_signature_with_named_keys, 1);
22
+ rb_define_method(rb_cNokogiri_XML_Document, "verify_with_certificates", verify_signature_with_certificates, 1);
23
+ rb_define_method(rb_cNokogiri_XML_Document, "encrypt_with_key", encrypt_with_key, 3);
24
+ rb_define_method(rb_cNokogiri_XML_Document, "decrypt_with_key", decrypt_with_key, 2);
25
+ rb_define_method(rb_cNokogiri_XML_Node, "set_id_attribute", set_id_attribute, 1);
26
+
27
+ rb_eSigningError = rb_define_class_under(XMLSec, "SigningError", rb_eRuntimeError);
28
+ rb_eVerificationError = rb_define_class_under(XMLSec, "VerificationError", rb_eRuntimeError);
29
+ rb_eKeystoreError = rb_define_class_under(XMLSec, "KeystoreError", rb_eRuntimeError);
30
+ rb_eEncryptionError = rb_define_class_under(XMLSec, "EncryptionError", rb_eRuntimeError);
31
+ rb_eDecryptionError = rb_define_class_under(XMLSec, "DecryptionError", rb_eRuntimeError);
32
+ }
@@ -0,0 +1,186 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ #include "options.h"
4
+ #include "util.h"
5
+
6
+ // Appends an xmlsig <dsig:Signature> node to document stored in |self|
7
+ // with a signature based on the given key and cert.
8
+ //
9
+ // Expects a ruby hash for the signing arguments.
10
+ // Hash parameters:
11
+ // :key - A PEM encoded rsa key for signing.
12
+ // :cert - The public cert to include with the signature.
13
+ // :signature_alg - Algorithm identified by the URL fragment. Supported algorithms
14
+ // taken from http://www.w3.org/TR/xmldsig-core
15
+ // :digest_alg - Algorithm identified by the URL fragment. Supported algorithms
16
+ // taken from http://www.w3.org/TR/xmldsig-core
17
+ // :name - [optional] String with name of the rsa key.
18
+ // :uri - [optional] The URI attribute for the <Reference> node in the
19
+ // signature.
20
+ VALUE sign_with_certificate(VALUE self, VALUE rb_opts) {
21
+ VALUE rb_exception_result = Qnil;
22
+ const char* exception_message = NULL;
23
+
24
+ xmlDocPtr doc = NULL;
25
+ xmlNodePtr signNode = NULL;
26
+ xmlNodePtr refNode = NULL;
27
+ xmlNodePtr keyInfoNode = NULL;
28
+ xmlSecDSigCtxPtr dsigCtx = NULL;
29
+ char *keyName = "";
30
+ char *certificate = NULL;
31
+ char *rsaKey = NULL;
32
+ char *refUri = NULL;
33
+ unsigned int rsaKeyLength = 0;
34
+ unsigned int certificateLength = 0;
35
+
36
+ resetXmlSecError();
37
+
38
+ VALUE rb_rsa_key = rb_hash_aref(rb_opts, ID2SYM(rb_intern("key")));
39
+ VALUE rb_cert = rb_hash_aref(rb_opts, ID2SYM(rb_intern("cert")));
40
+ VALUE rb_signature_alg = rb_hash_aref(rb_opts, ID2SYM(rb_intern("signature_alg")));
41
+ VALUE rb_digest_alg = rb_hash_aref(rb_opts, ID2SYM(rb_intern("digest_alg")));
42
+ VALUE rb_uri = rb_hash_aref(rb_opts, ID2SYM(rb_intern("uri")));
43
+ VALUE rb_key_name = rb_hash_aref(rb_opts, ID2SYM(rb_intern("name")));
44
+
45
+ Check_Type(rb_rsa_key, T_STRING);
46
+ Check_Type(rb_cert, T_STRING);
47
+ Check_Type(rb_signature_alg, T_STRING);
48
+ Check_Type(rb_digest_alg, T_STRING);
49
+
50
+ rsaKey = RSTRING_PTR(rb_rsa_key);
51
+ rsaKeyLength = RSTRING_LEN(rb_rsa_key);
52
+ certificate = RSTRING_PTR(rb_cert);
53
+ certificateLength = RSTRING_LEN(rb_cert);
54
+
55
+ if (!NIL_P(rb_key_name)) {
56
+ Check_Type(rb_key_name, T_STRING);
57
+ keyName = StringValueCStr(rb_key_name);
58
+ }
59
+ if (!NIL_P(rb_uri)) {
60
+ Check_Type(rb_uri, T_STRING);
61
+ refUri = StringValueCStr(rb_uri);
62
+ }
63
+
64
+ Data_Get_Struct(self, xmlDoc, doc);
65
+ xmlSecTransformId signature_algorithm = GetSignatureMethod(rb_signature_alg,
66
+ &rb_exception_result, &exception_message);
67
+ if (signature_algorithm == xmlSecTransformIdUnknown) {
68
+ // Propagate exception.
69
+ goto done;
70
+ }
71
+
72
+ // create signature template for enveloped signature.
73
+ signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId,
74
+ signature_algorithm, NULL);
75
+ if (signNode == NULL) {
76
+ rb_exception_result = rb_eSigningError;
77
+ exception_message = "failed to create signature template";
78
+ goto done;
79
+ }
80
+
81
+ // add <dsig:Signature/> node to the doc
82
+ xmlAddChild(xmlDocGetRootElement(doc), signNode);
83
+
84
+ // add reference
85
+ xmlSecTransformId digest_algorithm = GetDigestMethod(rb_digest_alg,
86
+ &rb_exception_result, &exception_message);
87
+ if (digest_algorithm == xmlSecTransformIdUnknown) {
88
+ // Propagate exception.
89
+ goto done;
90
+ }
91
+ refNode = xmlSecTmplSignatureAddReference(signNode, digest_algorithm,
92
+ NULL, (const xmlChar *)refUri, NULL);
93
+ if(refNode == NULL) {
94
+ rb_exception_result = rb_eSigningError;
95
+ exception_message = "failed to add reference to signature template";
96
+ goto done;
97
+ }
98
+
99
+ // add enveloped transform
100
+ if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) {
101
+ rb_exception_result = rb_eSigningError;
102
+ exception_message = "failed to add enveloped transform to reference";
103
+ goto done;
104
+ }
105
+
106
+ if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformExclC14NId) == NULL) {
107
+ rb_exception_result = rb_eSigningError;
108
+ exception_message = "failed to add canonicalization transform to reference";
109
+ goto done;
110
+ }
111
+
112
+ // add <dsig:KeyInfo/> and <dsig:X509Data/>
113
+ keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
114
+ if(keyInfoNode == NULL) {
115
+ rb_exception_result = rb_eSigningError;
116
+ exception_message = "failed to add key info";
117
+ goto done;
118
+ }
119
+
120
+ if(xmlSecTmplKeyInfoAddX509Data(keyInfoNode) == NULL) {
121
+ rb_exception_result = rb_eSigningError;
122
+ exception_message = "failed to add X509Data node";
123
+ goto done;
124
+ }
125
+
126
+ // create signature context, we don't need keys manager in this example
127
+ dsigCtx = createDSigContext(NULL);
128
+ if(dsigCtx == NULL) {
129
+ rb_exception_result = rb_eSigningError;
130
+ exception_message = "failed to create signature context";
131
+ goto done;
132
+ }
133
+
134
+ // load private key, assuming that there is not password
135
+ dsigCtx->signKey = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)rsaKey,
136
+ rsaKeyLength,
137
+ xmlSecKeyDataFormatPem,
138
+ NULL, // password
139
+ NULL,
140
+ NULL);
141
+ if(dsigCtx->signKey == NULL) {
142
+ rb_exception_result = rb_eSigningError;
143
+ exception_message = "failed to load private key";
144
+ goto done;
145
+ }
146
+
147
+ // load certificate and add to the key
148
+ if(xmlSecCryptoAppKeyCertLoadMemory(dsigCtx->signKey,
149
+ (xmlSecByte *)certificate,
150
+ certificateLength,
151
+ xmlSecKeyDataFormatPem) < 0) {
152
+ rb_exception_result = rb_eSigningError;
153
+ exception_message = "failed to load certificate";
154
+ goto done;
155
+ }
156
+
157
+ // set key name
158
+ if(xmlSecKeySetName(dsigCtx->signKey, (xmlSecByte *)keyName) < 0) {
159
+ rb_exception_result = rb_eSigningError;
160
+ exception_message = "failed to set key name";
161
+ goto done;
162
+ }
163
+
164
+ // sign the template
165
+ if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) {
166
+ rb_exception_result = rb_eSigningError;
167
+ exception_message = "signature failed";
168
+ goto done;
169
+ }
170
+
171
+ done:
172
+ if(dsigCtx != NULL) {
173
+ xmlSecDSigCtxDestroy(dsigCtx);
174
+ }
175
+
176
+ if(rb_exception_result != Qnil) {
177
+ if (hasXmlSecLastError()) {
178
+ rb_raise(rb_exception_result, "%s, XmlSec error: %s", exception_message,
179
+ getXmlSecLastError());
180
+ } else {
181
+ rb_raise(rb_exception_result, "%s", exception_message);
182
+ }
183
+ }
184
+
185
+ return Qnil;
186
+ }
@@ -0,0 +1,167 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ #include "options.h"
4
+ #include "util.h"
5
+
6
+ // Appends an xmlsig <dsig:Signature> node to document stored in |self|
7
+ // with a signature based on the given bare rsa key and keyname.
8
+ //
9
+ // Expects a ruby hash for the signing arguments.
10
+ // Hash parameters:
11
+ // :key_name - String with name of the rsa key. May be the empty string.
12
+ // :rsa_key - A PEM encoded rsa key for signing.
13
+ // :signature_alg - Algorithm identified by the URL fragment. Supported algorithms
14
+ // taken from http://www.w3.org/TR/xmldsig-core
15
+ // :digest_alg - Algorithm identified by the URL fragment. Supported algorithms
16
+ // taken from http://www.w3.org/TR/xmldsig-core
17
+ // :ref_uri - [optional] The URI attribute for the <Reference> node in the
18
+ // signature.
19
+ VALUE sign_with_key(VALUE self, VALUE rb_opts) {
20
+ VALUE rb_exception_result = Qnil;
21
+ const char* exception_message = NULL;
22
+
23
+ xmlDocPtr doc = NULL;
24
+ xmlNodePtr signNode = NULL;
25
+ xmlNodePtr refNode = NULL;
26
+ xmlNodePtr keyInfoNode = NULL;
27
+ xmlSecDSigCtxPtr dsigCtx = NULL;
28
+ char *keyName = NULL;
29
+ char *rsaKey = NULL;
30
+ char *refUri = NULL;
31
+ unsigned int rsaKeyLength = 0;
32
+
33
+ resetXmlSecError();
34
+
35
+ VALUE rb_key_name = rb_hash_aref(rb_opts, ID2SYM(rb_intern("name")));
36
+ VALUE rb_rsa_key = rb_hash_aref(rb_opts, ID2SYM(rb_intern("key")));
37
+ VALUE rb_signature_alg = rb_hash_aref(rb_opts, ID2SYM(rb_intern("signature_alg")));
38
+ VALUE rb_digest_alg = rb_hash_aref(rb_opts, ID2SYM(rb_intern("digest_alg")));
39
+ VALUE rb_uri = rb_hash_aref(rb_opts, ID2SYM(rb_intern("uri")));
40
+
41
+ Check_Type(rb_rsa_key, T_STRING);
42
+ Check_Type(rb_key_name, T_STRING);
43
+ Check_Type(rb_signature_alg, T_STRING);
44
+ Check_Type(rb_digest_alg, T_STRING);
45
+
46
+ rsaKey = RSTRING_PTR(rb_rsa_key);
47
+ rsaKeyLength = RSTRING_LEN(rb_rsa_key);
48
+ keyName = StringValueCStr(rb_key_name);
49
+
50
+ if (!NIL_P(rb_uri)) {
51
+ Check_Type(rb_uri, T_STRING);
52
+ refUri = StringValueCStr(rb_uri);
53
+ }
54
+
55
+ Data_Get_Struct(self, xmlDoc, doc);
56
+ xmlSecTransformId signature_algorithm = GetSignatureMethod(rb_signature_alg,
57
+ &rb_exception_result, &exception_message);
58
+ if (signature_algorithm == xmlSecTransformIdUnknown) {
59
+ // Propagate exception.
60
+ goto done;
61
+ }
62
+
63
+ // create signature template for enveloped signature
64
+ signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId,
65
+ signature_algorithm, NULL);
66
+ if (signNode == NULL) {
67
+ rb_exception_result = rb_eSigningError;
68
+ exception_message = "failed to create signature template";
69
+ goto done;
70
+ }
71
+
72
+ // add <dsig:Signature/> node to the doc
73
+ xmlAddChild(xmlDocGetRootElement(doc), signNode);
74
+
75
+ // add reference
76
+ xmlSecTransformId digest_algorithm = GetDigestMethod(rb_digest_alg,
77
+ &rb_exception_result, &exception_message);
78
+ if (digest_algorithm == xmlSecTransformIdUnknown) {
79
+ // Propagate exception.
80
+ goto done;
81
+ }
82
+ refNode = xmlSecTmplSignatureAddReference(signNode, digest_algorithm,
83
+ NULL, (const xmlChar *)refUri, NULL);
84
+ if(refNode == NULL) {
85
+ rb_exception_result = rb_eSigningError;
86
+ exception_message = "failed to add reference to signature template";
87
+ goto done;
88
+ }
89
+
90
+ // add enveloped transform
91
+ if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) {
92
+ rb_exception_result = rb_eSigningError;
93
+ exception_message = "failed to add enveloped transform to reference";
94
+ goto done;
95
+ }
96
+
97
+ if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformExclC14NId) == NULL) {
98
+ rb_exception_result = rb_eSigningError;
99
+ exception_message = "failed to add canonicalization transform to reference";
100
+ goto done;
101
+ }
102
+
103
+ // add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name in the signed
104
+ // document
105
+ keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
106
+ if(keyInfoNode == NULL) {
107
+ rb_exception_result = rb_eSigningError;
108
+ exception_message = "failed to add key info";
109
+ goto done;
110
+ }
111
+ if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) {
112
+ rb_exception_result = rb_eSigningError;
113
+ exception_message = "failed to add key name";
114
+ goto done;
115
+ }
116
+
117
+ // create signature context, we don't need keys manager in this example
118
+ dsigCtx = createDSigContext(NULL);
119
+ if(dsigCtx == NULL) {
120
+ rb_exception_result = rb_eSigningError;
121
+ exception_message = "failed to create signature context";
122
+ goto done;
123
+ }
124
+
125
+ // load private key, assuming that there is no password
126
+ dsigCtx->signKey = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)rsaKey,
127
+ rsaKeyLength,
128
+ xmlSecKeyDataFormatPem,
129
+ NULL, // password
130
+ NULL,
131
+ NULL);
132
+ if(dsigCtx->signKey == NULL) {
133
+ rb_exception_result = rb_eSigningError;
134
+ exception_message = "failed to load private pem key";
135
+ goto done;
136
+ }
137
+
138
+ // set key name
139
+ if(xmlSecKeySetName(dsigCtx->signKey, (xmlSecByte *)keyName) < 0) {
140
+ rb_exception_result = rb_eSigningError;
141
+ exception_message = "failed to set key name";
142
+ goto done;
143
+ }
144
+
145
+ // sign the template
146
+ if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) {
147
+ rb_exception_result = rb_eSigningError;
148
+ exception_message = "signature failed";
149
+ goto done;
150
+ }
151
+
152
+ done:
153
+ if(dsigCtx != NULL) {
154
+ xmlSecDSigCtxDestroy(dsigCtx);
155
+ }
156
+
157
+ if(rb_exception_result != Qnil) {
158
+ if (hasXmlSecLastError()) {
159
+ rb_raise(rb_exception_result, "%s, XmlSec error: %s", exception_message,
160
+ getXmlSecLastError());
161
+ } else {
162
+ rb_raise(rb_exception_result, "%s", exception_message);
163
+ }
164
+ }
165
+
166
+ return Qnil;
167
+ }