nokogiri-xmlsec-me-harder 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }