money-nokogiri-xmlsec 0.0.5

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 (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/Guardfile +13 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +121 -0
  8. data/Rakefile +30 -0
  9. data/ext/nokogiri_ext_xmlsec/extconf.rb +20 -0
  10. data/ext/nokogiri_ext_xmlsec/init.c +46 -0
  11. data/ext/nokogiri_ext_xmlsec/nokogiri_decrypt_with_key.c +124 -0
  12. data/ext/nokogiri_ext_xmlsec/nokogiri_encrypt_with_key.c +177 -0
  13. data/ext/nokogiri_ext_xmlsec/nokogiri_helpers_set_attribute_id.c +43 -0
  14. data/ext/nokogiri_ext_xmlsec/nokogiri_init.c +32 -0
  15. data/ext/nokogiri_ext_xmlsec/nokogiri_sign_certificate.c +143 -0
  16. data/ext/nokogiri_ext_xmlsec/nokogiri_sign_rsa.c +95 -0
  17. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_certificates.c +96 -0
  18. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_named_keys.c +106 -0
  19. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_rsa.c +56 -0
  20. data/ext/nokogiri_ext_xmlsec/shutdown.c +12 -0
  21. data/ext/nokogiri_ext_xmlsec/xmlsecrb.h +39 -0
  22. data/lib/money-nokogiri-xmlsec.rb +1 -0
  23. data/lib/xmlsec.rb +110 -0
  24. data/lib/xmlsec/version.rb +3 -0
  25. data/money-nokogiri-xmlsec.gemspec +36 -0
  26. data/spec/fixtures/cert/server.crt +14 -0
  27. data/spec/fixtures/cert/server.csr +11 -0
  28. data/spec/fixtures/cert/server.key.decrypted +15 -0
  29. data/spec/fixtures/cert/server.key.encrypted +18 -0
  30. data/spec/fixtures/rsa.pem +15 -0
  31. data/spec/fixtures/rsa.pub +6 -0
  32. data/spec/fixtures/sign2-doc.xml +6 -0
  33. data/spec/fixtures/sign2-result.xml +24 -0
  34. data/spec/fixtures/sign3-result.xml +37 -0
  35. data/spec/lib/nokogiri/xml/document/encryption_and_decryption_spec.rb +28 -0
  36. data/spec/lib/nokogiri/xml/document/signing_and_verifying_spec.rb +70 -0
  37. data/spec/spec_helper.rb +10 -0
  38. metadata +197 -0
@@ -0,0 +1,43 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ VALUE set_id_attribute(VALUE self, VALUE rb_attr_name) {
4
+ xmlNodePtr node;
5
+ xmlAttrPtr attr;
6
+ xmlAttrPtr tmp;
7
+ xmlChar *name;
8
+ const xmlChar *idName;
9
+
10
+ Data_Get_Struct(self, xmlNode, node);
11
+ Check_Type(rb_attr_name, T_STRING);
12
+ idName = (const xmlChar *)RSTRING_PTR(rb_attr_name);
13
+
14
+ // find pointer to id attribute
15
+ attr = xmlHasProp(node, idName);
16
+ if((attr == NULL) || (attr->children == NULL)) {
17
+ rb_raise(rb_eRuntimeError, "Can't find attribute to add register as id");
18
+ return Qfalse;
19
+ }
20
+
21
+ // get the attribute (id) value
22
+ name = xmlNodeListGetString(node->doc, attr->children, 1);
23
+ if(name == NULL) {
24
+ rb_raise(rb_eRuntimeError, "Attribute %s has no value", idName);
25
+ return Qfalse;
26
+ }
27
+
28
+ // check that we don't have that id already registered
29
+ tmp = xmlGetID(node->doc, name);
30
+ if(tmp != NULL) {
31
+ // rb_raise(rb_eRuntimeError, "Attribute %s is already an ID", idName);
32
+ xmlFree(name);
33
+ return Qfalse;
34
+ }
35
+
36
+ // finally register id
37
+ xmlAddID(NULL, node->doc, name, attr);
38
+
39
+ // and do not forget to cleanup
40
+ xmlFree(name);
41
+
42
+ return Qtrue;
43
+ }
@@ -0,0 +1,32 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ VALUE rb_cNokogiri_XML_Document = T_NIL;
4
+ VALUE rb_cNokogiri_XML_Node = T_NIL;
5
+ VALUE rb_eSigningError = T_NIL;
6
+ VALUE rb_eVerificationError = T_NIL;
7
+ VALUE rb_eKeystoreError = T_NIL;
8
+ VALUE rb_eEncryptionError = T_NIL;
9
+ VALUE rb_eDecryptionError = T_NIL;
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, 2);
19
+ rb_define_method(rb_cNokogiri_XML_Document, "sign_with_certificate", sign_with_certificate, 5);
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, 2);
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,143 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ VALUE sign_with_certificate(VALUE self, VALUE rb_key_name, VALUE rb_rsa_key, VALUE rb_cert, VALUE rb_cert_issuer_name, VALUE rb_cert_serial_number) {
4
+ xmlDocPtr doc;
5
+ xmlNodePtr signNode = NULL;
6
+ xmlNodePtr refNode = NULL;
7
+ xmlNodePtr keyInfoNode = NULL;
8
+ xmlNodePtr x509DataNode = NULL;
9
+ xmlNodePtr issuerSerialNode = NULL;
10
+ xmlSecDSigCtxPtr dsigCtx = NULL;
11
+ char *keyName;
12
+ char *certificate;
13
+ char *issuerName;
14
+ char *serialNumber;
15
+ char *rsaKey;
16
+ unsigned int rsaKeyLength, certificateLength;
17
+
18
+ Data_Get_Struct(self, xmlDoc, doc);
19
+ rsaKey = RSTRING_PTR(rb_rsa_key);
20
+ rsaKeyLength = RSTRING_LEN(rb_rsa_key);
21
+ keyName = RSTRING_PTR(rb_key_name);
22
+ certificate = RSTRING_PTR(rb_cert);
23
+ issuerName = RSTRING_PTR(rb_cert_issuer_name);
24
+ serialNumber = RSTRING_PTR(rb_cert_serial_number);
25
+ certificateLength = RSTRING_LEN(rb_cert);
26
+
27
+ // create signature template for RSA-SHA1 enveloped signature
28
+ signNode = xmlSecTmplSignatureCreateNsPref(doc, xmlSecTransformInclC14NId,
29
+ xmlSecTransformRsaSha1Id, NULL, "ds");
30
+ if (signNode == NULL) {
31
+ rb_raise(rb_eSigningError, "failed to create signature template");
32
+ goto done;
33
+ }
34
+
35
+ // add <dsig:Signature/> node to the doc
36
+ xmlAddChild(xmlDocGetRootElement(doc), signNode);
37
+
38
+ // add reference
39
+ refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id,
40
+ NULL, "", NULL);
41
+ if(refNode == NULL) {
42
+ rb_raise(rb_eSigningError, "failed to add reference to signature template");
43
+ goto done;
44
+ }
45
+
46
+ // add enveloped transform
47
+ if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) {
48
+ rb_raise(rb_eSigningError, "failed to add enveloped transform to reference");
49
+ goto done;
50
+ }
51
+
52
+ // add c14n transform
53
+ if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformInclC14NId) == NULL) {
54
+ rb_raise(rb_eSigningError, "failed to add c14n transform to reference");
55
+ goto done;
56
+ }
57
+
58
+ // add <dsig:KeyInfo/> and <dsig:X509Data/>
59
+ keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
60
+ if(keyInfoNode == NULL) {
61
+ rb_raise(rb_eSigningError, "failed to add key info");
62
+ goto done;
63
+ }
64
+
65
+ // add <X509Data/>
66
+ x509DataNode = xmlSecTmplKeyInfoAddX509Data(keyInfoNode);
67
+ if(x509DataNode == NULL) {
68
+ rb_raise(rb_eSigningError, "failed to add X509Data node");
69
+ goto done;
70
+ }
71
+
72
+ // add <X509Certificate/>
73
+ if(xmlSecTmplX509DataAddCertificate(x509DataNode) == NULL) {
74
+ rb_raise(rb_eSigningError, "failed to add X509Certificate node");
75
+ goto done;
76
+ }
77
+
78
+ // add <X509IssuerSerial/>
79
+ issuerSerialNode = xmlSecTmplX509DataAddIssuerSerial(x509DataNode);
80
+ if(issuerSerialNode == NULL) {
81
+ rb_raise(rb_eSigningError, "failed to add X509IssuerSerial node");
82
+ goto done;
83
+ }
84
+
85
+ // add <X509IssuerName/>
86
+ if(xmlSecTmplX509IssuerSerialAddIssuerName(issuerSerialNode, (xmlSecByte *)issuerName) == NULL) {
87
+ rb_raise(rb_eSigningError, "failed to add X509IssuerName node");
88
+ goto done;
89
+ }
90
+
91
+ // add <X509SerialNumber/>
92
+ if(xmlSecTmplX509IssuerSerialAddSerialNumber(issuerSerialNode, (xmlSecByte *)serialNumber) == NULL) {
93
+ rb_raise(rb_eSigningError, "failed to add X509SerialNumber node");
94
+ goto done;
95
+ }
96
+
97
+ // create signature context, we don't need keys manager in this example
98
+ dsigCtx = xmlSecDSigCtxCreate(NULL);
99
+ if(dsigCtx == NULL) {
100
+ rb_raise(rb_eSigningError, "failed to create signature context");
101
+ goto done;
102
+ }
103
+
104
+ // load private key, assuming that there is not password
105
+ dsigCtx->signKey = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)rsaKey,
106
+ rsaKeyLength,
107
+ xmlSecKeyDataFormatPem,
108
+ NULL, // password
109
+ NULL,
110
+ NULL);
111
+ if(dsigCtx->signKey == NULL) {
112
+ rb_raise(rb_eSigningError, "failed to load private key");
113
+ goto done;
114
+ }
115
+
116
+ // load certificate and add to the key
117
+ if(xmlSecCryptoAppKeyCertLoadMemory(dsigCtx->signKey,
118
+ (xmlSecByte *)certificate,
119
+ certificateLength,
120
+ xmlSecKeyDataFormatPem) < 0) {
121
+ rb_raise(rb_eSigningError, "failed to load certificate");
122
+ goto done;
123
+ }
124
+
125
+ // set key name
126
+ if(xmlSecKeySetName(dsigCtx->signKey, (xmlSecByte *)keyName) < 0) {
127
+ rb_raise(rb_eSigningError, "failed to set key name");
128
+ goto done;
129
+ }
130
+
131
+ // sign the template
132
+ if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) {
133
+ rb_raise(rb_eSigningError, "signature failed");
134
+ goto done;
135
+ }
136
+
137
+ done:
138
+ if(dsigCtx != NULL) {
139
+ xmlSecDSigCtxDestroy(dsigCtx);
140
+ }
141
+
142
+ return T_NIL;
143
+ }
@@ -0,0 +1,95 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ // TODO the signature context probably should be a ruby instance variable
4
+ // and separate object, instead of being allocated/freed in each method.
5
+
6
+ VALUE sign_with_key(VALUE self, VALUE rb_key_name, VALUE rb_rsa_key) {
7
+ xmlDocPtr doc;
8
+ xmlNodePtr signNode = NULL;
9
+ xmlNodePtr refNode = NULL;
10
+ xmlNodePtr keyInfoNode = NULL;
11
+ xmlSecDSigCtxPtr dsigCtx = NULL;
12
+ char *keyName;
13
+ char *rsaKey;
14
+ unsigned int rsaKeyLength;
15
+
16
+ Data_Get_Struct(self, xmlDoc, doc);
17
+ rsaKey = RSTRING_PTR(rb_rsa_key);
18
+ rsaKeyLength = RSTRING_LEN(rb_rsa_key);
19
+ keyName = RSTRING_PTR(rb_key_name);
20
+
21
+ // create signature template for RSA-SHA1 enveloped signature
22
+ signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformExclC14NId,
23
+ xmlSecTransformRsaSha1Id, NULL);
24
+ if (signNode == NULL) {
25
+ rb_raise(rb_eSigningError, "failed to create signature template");
26
+ goto done;
27
+ }
28
+
29
+ // add <dsig:Signature/> node to the doc
30
+ xmlAddChild(xmlDocGetRootElement(doc), signNode);
31
+
32
+ // add reference
33
+ refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id,
34
+ NULL, NULL, NULL);
35
+ if(refNode == NULL) {
36
+ rb_raise(rb_eSigningError, "failed to add reference to signature template");
37
+ goto done;
38
+ }
39
+
40
+ // add enveloped transform
41
+ if(xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL) {
42
+ rb_raise(rb_eSigningError, "failed to add enveloped transform to reference");
43
+ goto done;
44
+ }
45
+
46
+ // add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name in the signed
47
+ // document
48
+ keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
49
+ if(keyInfoNode == NULL) {
50
+ rb_raise(rb_eSigningError, "failed to add key info");
51
+ goto done;
52
+ }
53
+ if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) {
54
+ rb_raise(rb_eSigningError, "failed to add key name");
55
+ goto done;
56
+ }
57
+
58
+ // create signature context, we don't need keys manager in this example
59
+ dsigCtx = xmlSecDSigCtxCreate(NULL);
60
+ if(dsigCtx == NULL) {
61
+ rb_raise(rb_eSigningError, "failed to create signature context");
62
+ goto done;
63
+ }
64
+
65
+ // load private key, assuming that there is no password
66
+ dsigCtx->signKey = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)rsaKey,
67
+ rsaKeyLength,
68
+ xmlSecKeyDataFormatPem,
69
+ NULL, // password
70
+ NULL,
71
+ NULL);
72
+ if(dsigCtx->signKey == NULL) {
73
+ rb_raise(rb_eSigningError, "failed to load private pem key");
74
+ goto done;
75
+ }
76
+
77
+ // set key name
78
+ if(xmlSecKeySetName(dsigCtx->signKey, (xmlSecByte *)keyName) < 0) {
79
+ rb_raise(rb_eSigningError, "failed to set key name");
80
+ goto done;
81
+ }
82
+
83
+ // sign the template
84
+ if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) {
85
+ rb_raise(rb_eSigningError, "signature failed");
86
+ goto done;
87
+ }
88
+
89
+ done:
90
+ if(dsigCtx != NULL) {
91
+ xmlSecDSigCtxDestroy(dsigCtx);
92
+ }
93
+
94
+ return T_NIL;
95
+ }
@@ -0,0 +1,96 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ static xmlSecKeysMngrPtr getKeyManager(VALUE rb_certs) {
4
+ int i, numCerts = RARRAY_LEN(rb_certs);
5
+ xmlSecKeysMngrPtr keyManager = xmlSecKeysMngrCreate();
6
+ VALUE rb_cert;
7
+ char *cert;
8
+ unsigned int certLength;
9
+ int numSuccessful = 0;
10
+
11
+ if (keyManager == NULL) return NULL;
12
+
13
+ if (xmlSecCryptoAppDefaultKeysMngrInit(keyManager) < 0) {
14
+ rb_raise(rb_eKeystoreError, "could not initialize key manager");
15
+ xmlSecKeysMngrDestroy(keyManager);
16
+ return NULL;
17
+ }
18
+
19
+ for (i = 0; i < numCerts; i++) {
20
+ rb_cert = RARRAY_PTR(rb_certs)[i];
21
+ Check_Type(rb_cert, T_STRING);
22
+ cert = RSTRING_PTR(rb_cert);
23
+ certLength = RSTRING_LEN(rb_cert);
24
+
25
+ if(xmlSecCryptoAppKeysMngrCertLoadMemory(keyManager,
26
+ (xmlSecByte *)cert,
27
+ certLength,
28
+ xmlSecKeyDataFormatPem,
29
+ xmlSecKeyDataTypeTrusted) < 0) {
30
+ rb_warn("failed to load certificate at index %d", i);
31
+ } else {
32
+ numSuccessful++;
33
+ }
34
+ }
35
+
36
+ // note, numCerts could be zero, meaning that we should use system SSL certs
37
+ if (numSuccessful == 0 && numCerts != 0) {
38
+ rb_raise(rb_eKeystoreError, "Could not load any of the specified certificates for signature verification");
39
+ xmlSecKeysMngrDestroy(keyManager);
40
+ return NULL;
41
+ }
42
+
43
+ return keyManager;
44
+ }
45
+
46
+ VALUE verify_signature_with_certificates(VALUE self, VALUE rb_certs) {
47
+ xmlDocPtr doc;
48
+ xmlNodePtr node = NULL;
49
+ xmlSecDSigCtxPtr dsigCtx = NULL;
50
+ xmlSecKeysMngrPtr keyManager = NULL;
51
+ VALUE result = Qfalse;
52
+
53
+ Check_Type(rb_certs, T_ARRAY);
54
+ Data_Get_Struct(self, xmlDoc, doc);
55
+
56
+ // find start node
57
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
58
+ if(node == NULL) {
59
+ rb_raise(rb_eVerificationError, "start node not found");
60
+ goto done;
61
+ }
62
+
63
+ keyManager = getKeyManager(rb_certs);
64
+ if (keyManager == NULL) {
65
+ rb_raise(rb_eKeystoreError, "failed to create key manager");
66
+ goto done;
67
+ }
68
+
69
+ // create signature context, we don't need keys manager in this example
70
+ dsigCtx = xmlSecDSigCtxCreate(keyManager);
71
+ if(dsigCtx == NULL) {
72
+ rb_raise(rb_eVerificationError, "failed to create signature context");
73
+ goto done;
74
+ }
75
+
76
+ // verify signature
77
+ if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
78
+ rb_raise(rb_eVerificationError, "error occurred during signature verification");
79
+ goto done;
80
+ }
81
+
82
+ if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
83
+ result = Qtrue;
84
+ }
85
+
86
+ done:
87
+ if(dsigCtx != NULL) {
88
+ xmlSecDSigCtxDestroy(dsigCtx);
89
+ }
90
+
91
+ if (keyManager != NULL) {
92
+ xmlSecKeysMngrDestroy(keyManager);
93
+ }
94
+
95
+ return result;
96
+ }
@@ -0,0 +1,106 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ static int addRubyKeyToManager(VALUE rb_key, VALUE rb_value, VALUE rb_manager) {
4
+ xmlSecKeysMngrPtr keyManager = (xmlSecKeysMngrPtr)rb_manager;
5
+ char *keyName, *keyData;
6
+ unsigned int keyDataLength;
7
+ xmlSecKeyPtr key;
8
+
9
+ Check_Type(rb_key, T_STRING);
10
+ Check_Type(rb_value, T_STRING);
11
+ keyName = RSTRING_PTR(rb_key);
12
+ keyData = RSTRING_PTR(rb_value);
13
+ keyDataLength = RSTRING_LEN(rb_value);
14
+
15
+ // load key
16
+ key = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)keyData,
17
+ keyDataLength,
18
+ xmlSecKeyDataFormatPem,
19
+ NULL, // password
20
+ NULL, NULL);
21
+ if (key == NULL) {
22
+ rb_warn("failed to load '%s' public or private pem key", keyName);
23
+ return ST_CONTINUE;
24
+ }
25
+
26
+ // set key name
27
+ if (xmlSecKeySetName(key, BAD_CAST keyName) < 0) {
28
+ rb_warn("failed to set key name for key '%s'", keyName);
29
+ return ST_CONTINUE;
30
+ }
31
+
32
+ // add key to key manager; from now on the manager is responsible for
33
+ // destroying the key
34
+ if (xmlSecCryptoAppDefaultKeysMngrAdoptKey(keyManager, key) < 0) {
35
+ rb_warn("failed to add key '%s' to key manager", keyName);
36
+ return ST_CONTINUE;
37
+ }
38
+
39
+ return ST_CONTINUE;
40
+ }
41
+
42
+ static xmlSecKeysMngrPtr getKeyManager(VALUE rb_hash) {
43
+ xmlSecKeysMngrPtr keyManager = xmlSecKeysMngrCreate();
44
+ if (keyManager == NULL) return NULL;
45
+ if (xmlSecCryptoAppDefaultKeysMngrInit(keyManager) < 0) {
46
+ rb_raise(rb_eKeystoreError, "could not initialize key manager");
47
+ xmlSecKeysMngrDestroy(keyManager);
48
+ return NULL;
49
+ }
50
+
51
+ rb_hash_foreach(rb_hash, addRubyKeyToManager, (VALUE)keyManager);
52
+
53
+ return keyManager;
54
+ }
55
+
56
+ VALUE verify_signature_with_named_keys(VALUE self, VALUE rb_hash) {
57
+ xmlDocPtr doc;
58
+ xmlNodePtr node = NULL;
59
+ xmlSecDSigCtxPtr dsigCtx = NULL;
60
+ xmlSecKeysMngrPtr keyManager = NULL;
61
+ VALUE result = Qfalse;
62
+
63
+ Check_Type(rb_hash, T_HASH);
64
+ Data_Get_Struct(self, xmlDoc, doc);
65
+
66
+ // find start node
67
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
68
+ if(node == NULL) {
69
+ rb_raise(rb_eVerificationError, "start node not found");
70
+ goto done;
71
+ }
72
+
73
+ keyManager = getKeyManager(rb_hash);
74
+ if (keyManager == NULL) {
75
+ rb_raise(rb_eKeystoreError, "failed to create key manager");
76
+ goto done;
77
+ }
78
+
79
+ // create signature context, we don't need keys manager in this example
80
+ dsigCtx = xmlSecDSigCtxCreate(keyManager);
81
+ if(dsigCtx == NULL) {
82
+ rb_raise(rb_eVerificationError, "failed to create signature context");
83
+ goto done;
84
+ }
85
+
86
+ // verify signature
87
+ if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
88
+ rb_raise(rb_eVerificationError, "signature could not be verified");
89
+ goto done;
90
+ }
91
+
92
+ if(dsigCtx->status == xmlSecDSigStatusSucceeded) {
93
+ result = Qtrue;
94
+ }
95
+
96
+ done:
97
+ if(dsigCtx != NULL) {
98
+ xmlSecDSigCtxDestroy(dsigCtx);
99
+ }
100
+
101
+ if (keyManager != NULL) {
102
+ xmlSecKeysMngrDestroy(keyManager);
103
+ }
104
+
105
+ return result;
106
+ }