nokogiri-xmlsec1 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +11 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +13 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +133 -0
  9. data/Rakefile +30 -0
  10. data/dependencies.yml +3 -0
  11. data/ext/nokogiri_ext_xmlsec/extconf.rb +489 -0
  12. data/ext/nokogiri_ext_xmlsec/init.c +46 -0
  13. data/ext/nokogiri_ext_xmlsec/nokogiri_decrypt_with_key.c +124 -0
  14. data/ext/nokogiri_ext_xmlsec/nokogiri_encrypt_with_key.c +182 -0
  15. data/ext/nokogiri_ext_xmlsec/nokogiri_helpers_set_attribute_id.c +43 -0
  16. data/ext/nokogiri_ext_xmlsec/nokogiri_init.c +32 -0
  17. data/ext/nokogiri_ext_xmlsec/nokogiri_sign_certificate.c +104 -0
  18. data/ext/nokogiri_ext_xmlsec/nokogiri_sign_rsa.c +95 -0
  19. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_certificates.c +96 -0
  20. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_named_keys.c +106 -0
  21. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_rsa.c +56 -0
  22. data/ext/nokogiri_ext_xmlsec/shutdown.c +12 -0
  23. data/ext/nokogiri_ext_xmlsec/xmlsecrb.h +39 -0
  24. data/lib/nokogiri-xmlsec.rb +1 -0
  25. data/lib/xmlsec.rb +110 -0
  26. data/lib/xmlsec/version.rb +3 -0
  27. data/nokogiri-xmlsec1.gemspec +46 -0
  28. data/ports/patches/libxml2/0001-Fix-parser-local-buffers-size-problems.patch +265 -0
  29. data/ports/patches/libxml2/0002-Fix-entities-local-buffers-size-problems.patch +102 -0
  30. data/ports/patches/libxml2/0003-Fix-an-error-in-previous-commit.patch +26 -0
  31. data/ports/patches/libxml2/0004-Fix-potential-out-of-bound-access.patch +26 -0
  32. data/ports/patches/libxml2/0005-Detect-excessive-entities-expansion-upon-replacement.patch +158 -0
  33. data/ports/patches/libxml2/0006-Do-not-fetch-external-parsed-entities.patch +78 -0
  34. data/ports/patches/libxml2/0007-Enforce-XML_PARSER_EOF-state-handling-through-the-pa.patch +480 -0
  35. data/ports/patches/libxml2/0008-Improve-handling-of-xmlStopParser.patch +315 -0
  36. data/ports/patches/libxml2/0009-Fix-a-couple-of-return-without-value.patch +37 -0
  37. data/ports/patches/libxml2/0010-Keep-non-significant-blanks-node-in-HTML-parser.patch +2006 -0
  38. data/ports/patches/libxml2/0011-Do-not-fetch-external-parameter-entities.patch +39 -0
  39. data/ports/patches/libxslt/0001-Adding-doc-update-related-to-1.1.28.patch +222 -0
  40. data/ports/patches/libxslt/0002-Fix-a-couple-of-places-where-f-printf-parameters-wer.patch +53 -0
  41. data/ports/patches/libxslt/0003-Initialize-pseudo-random-number-generator-with-curre.patch +60 -0
  42. data/ports/patches/libxslt/0004-EXSLT-function-str-replace-is-broken-as-is.patch +42 -0
  43. data/ports/patches/libxslt/0006-Fix-str-padding-to-work-with-UTF-8-strings.patch +164 -0
  44. data/ports/patches/libxslt/0007-Separate-function-for-predicate-matching-in-patterns.patch +587 -0
  45. data/ports/patches/libxslt/0008-Fix-direct-pattern-matching.patch +80 -0
  46. data/ports/patches/libxslt/0009-Fix-certain-patterns-with-predicates.patch +185 -0
  47. data/ports/patches/libxslt/0010-Fix-handling-of-UTF-8-strings-in-EXSLT-crypto-module.patch +126 -0
  48. data/ports/patches/libxslt/0013-Memory-leak-in-xsltCompileIdKeyPattern-error-path.patch +25 -0
  49. data/ports/patches/libxslt/0014-Fix-for-bug-436589.patch +43 -0
  50. data/ports/patches/libxslt/0015-Fix-mkdir-for-mingw.patch +41 -0
  51. data/ports/patches/xmlsec1/.keep +0 -0
  52. data/spec/fixtures/cert/server.crt +14 -0
  53. data/spec/fixtures/cert/server.csr +11 -0
  54. data/spec/fixtures/cert/server.key.decrypted +15 -0
  55. data/spec/fixtures/cert/server.key.encrypted +18 -0
  56. data/spec/fixtures/rsa.pem +15 -0
  57. data/spec/fixtures/rsa.pub +6 -0
  58. data/spec/fixtures/sign2-doc.xml +6 -0
  59. data/spec/fixtures/sign2-result.xml +24 -0
  60. data/spec/fixtures/sign3-result.xml +37 -0
  61. data/spec/lib/nokogiri/xml/document/encryption_and_decryption_spec.rb +22 -0
  62. data/spec/lib/nokogiri/xml/document/signing_and_verifying_spec.rb +77 -0
  63. data/spec/spec_helper.rb +10 -0
  64. metadata +251 -0
@@ -0,0 +1,46 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ void Init_nokogiri_ext_xmlsec() {
4
+ /* xmlsec proper */
5
+ // libxml
6
+ xmlInitParser();
7
+ LIBXML_TEST_VERSION
8
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
9
+ xmlSubstituteEntitiesDefault(1);
10
+ // xslt
11
+ #ifndef XMLSEC_NO_XSLT
12
+ xmlIndentTreeOutput = 1;
13
+ #endif /* XMLSEC_NO_XSLT */
14
+ // xmlsec
15
+ if (xmlSecInit() < 0) {
16
+ rb_raise(rb_eRuntimeError, "xmlsec initialization failed");
17
+ return;
18
+ }
19
+ if (xmlSecCheckVersion() != 1) {
20
+ rb_raise(rb_eRuntimeError, "xmlsec version is not compatible");
21
+ return;
22
+ }
23
+ // load crypto
24
+ #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
25
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
26
+ rb_raise(rb_eRuntimeError,
27
+ "Error: unable to load default xmlsec-crypto library. Make sure"
28
+ "that you have it installed and check shared libraries path\n"
29
+ "(LD_LIBRARY_PATH) envornment variable.\n");
30
+ return;
31
+ }
32
+ #endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
33
+ // init crypto
34
+ if (xmlSecCryptoAppInit(NULL) < 0) {
35
+ rb_raise(rb_eRuntimeError, "unable to initialize crypto engine");
36
+ return;
37
+ }
38
+ // init xmlsec-crypto library
39
+ if (xmlSecCryptoInit() < 0) {
40
+ rb_raise(rb_eRuntimeError, "xmlsec-crypto initialization failed");
41
+ }
42
+
43
+ /* ruby classes & objects */
44
+ Init_Nokogiri_ext();
45
+ }
46
+
@@ -0,0 +1,124 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ static xmlSecKeysMngrPtr getKeyManager(char* keyStr, unsigned int keyLength, char *keyName) {
4
+ xmlSecKeysMngrPtr mngr;
5
+ xmlSecKeyPtr key;
6
+
7
+ /* create and initialize keys manager, we use a simple list based
8
+ * keys manager, implement your own xmlSecKeysStore klass if you need
9
+ * something more sophisticated
10
+ */
11
+ mngr = xmlSecKeysMngrCreate();
12
+ if(mngr == NULL) {
13
+ rb_raise(rb_eDecryptionError, "failed to create keys manager.");
14
+ return(NULL);
15
+ }
16
+ if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
17
+ rb_raise(rb_eDecryptionError, "failed to initialize keys manager.");
18
+ xmlSecKeysMngrDestroy(mngr);
19
+ return(NULL);
20
+ }
21
+
22
+ /* load private RSA key */
23
+ // key = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
24
+ key = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)keyStr,
25
+ keyLength,
26
+ xmlSecKeyDataFormatPem,
27
+ NULL, // password
28
+ NULL, NULL);
29
+ if(key == NULL) {
30
+ rb_raise(rb_eDecryptionError, "failed to load rsa key");
31
+ xmlSecKeysMngrDestroy(mngr);
32
+ return(NULL);
33
+ }
34
+
35
+ /* set key name to the file name, this is just an example! */
36
+ if(xmlSecKeySetName(key, BAD_CAST keyName) < 0) {
37
+ rb_raise(rb_eDecryptionError, "failed to set key name");
38
+ xmlSecKeyDestroy(key);
39
+ xmlSecKeysMngrDestroy(mngr);
40
+ return(NULL);
41
+ }
42
+
43
+ /* add key to keys manager, from now on keys manager is responsible
44
+ * for destroying key
45
+ */
46
+ if(xmlSecCryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0) {
47
+ rb_raise(rb_eDecryptionError, "failed to add key to keys manager");
48
+ xmlSecKeyDestroy(key);
49
+ xmlSecKeysMngrDestroy(mngr);
50
+ return(NULL);
51
+ }
52
+
53
+ return(mngr);
54
+ }
55
+
56
+ VALUE decrypt_with_key(VALUE self, VALUE rb_key_name, VALUE rb_key) {
57
+ xmlDocPtr doc;
58
+ xmlNodePtr node = NULL;
59
+ xmlSecEncCtxPtr encCtx = NULL;
60
+ xmlSecKeysMngrPtr keyManager = NULL;
61
+ char *key;
62
+ char *keyName;
63
+ unsigned int keyLength;
64
+
65
+ Check_Type(rb_key, T_STRING);
66
+ Check_Type(rb_key_name, T_STRING);
67
+ Data_Get_Struct(self, xmlDoc, doc);
68
+ key = RSTRING_PTR(rb_key);
69
+ keyLength = RSTRING_LEN(rb_key);
70
+ keyName = RSTRING_PTR(rb_key_name);
71
+
72
+
73
+ // find start node
74
+ node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs);
75
+ if(node == NULL) {
76
+ rb_raise(rb_eDecryptionError, "start node not found");
77
+ goto done;
78
+ }
79
+
80
+ keyManager = getKeyManager(key, keyLength, keyName);
81
+ if (keyManager == NULL) {
82
+ rb_raise(rb_eEncryptionError, "failed to create key manager");
83
+ goto done;
84
+ }
85
+
86
+ // create encryption context
87
+ encCtx = xmlSecEncCtxCreate(keyManager);
88
+ if(encCtx == NULL) {
89
+ rb_raise(rb_eDecryptionError, "failed to create encryption context");
90
+ goto done;
91
+ }
92
+
93
+ // decrypt the data
94
+ if((xmlSecEncCtxDecrypt(encCtx, node) < 0) || (encCtx->result == NULL)) {
95
+ rb_raise(rb_eDecryptionError, "decryption failed");
96
+ goto done;
97
+ }
98
+
99
+ if(encCtx->resultReplaced == 0) {
100
+ fprintf(stdout, "Decrypted binary data (%d bytes):", xmlSecBufferGetSize(encCtx->result));
101
+ if(xmlSecBufferGetData(encCtx->result) != NULL) {
102
+ fwrite(xmlSecBufferGetData(encCtx->result),
103
+ 1,
104
+ xmlSecBufferGetSize(encCtx->result),
105
+ stdout);
106
+ fprintf(stdout, "\n");
107
+ }
108
+
109
+ rb_raise(rb_eDecryptionError, "Not implemented: don't know how to handle decrypted, non-XML data yet");
110
+ goto done;
111
+ }
112
+
113
+ done:
114
+ // cleanup
115
+ if(encCtx != NULL) {
116
+ xmlSecEncCtxDestroy(encCtx);
117
+ }
118
+
119
+ if (keyManager != NULL) {
120
+ xmlSecKeysMngrDestroy(keyManager);
121
+ }
122
+
123
+ return T_NIL;
124
+ }
@@ -0,0 +1,182 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ static xmlSecKeysMngrPtr getKeyManager(char* keyStr, unsigned int keyLength, char *keyName) {
4
+ xmlSecKeysMngrPtr mngr;
5
+ xmlSecKeyPtr key;
6
+
7
+ /* create and initialize keys manager, we use a simple list based
8
+ * keys manager, implement your own xmlSecKeysStore klass if you need
9
+ * something more sophisticated
10
+ */
11
+ mngr = xmlSecKeysMngrCreate();
12
+ if(mngr == NULL) {
13
+ rb_raise(rb_eDecryptionError, "failed to create keys manager.");
14
+ return(NULL);
15
+ }
16
+ if(xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
17
+ rb_raise(rb_eDecryptionError, "failed to initialize keys manager.");
18
+ xmlSecKeysMngrDestroy(mngr);
19
+ return(NULL);
20
+ }
21
+
22
+ /* load private RSA key */
23
+ // key = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
24
+ key = xmlSecCryptoAppKeyLoadMemory((xmlSecByte *)keyStr,
25
+ keyLength,
26
+ xmlSecKeyDataFormatPem,
27
+ NULL, // password
28
+ NULL, NULL);
29
+ if(key == NULL) {
30
+ rb_raise(rb_eDecryptionError, "failed to load rsa key");
31
+ xmlSecKeysMngrDestroy(mngr);
32
+ return(NULL);
33
+ }
34
+
35
+ /* set key name to the file name, this is just an example! */
36
+ if(xmlSecKeySetName(key, BAD_CAST keyName) < 0) {
37
+ rb_raise(rb_eDecryptionError, "failed to set key name");
38
+ xmlSecKeyDestroy(key);
39
+ xmlSecKeysMngrDestroy(mngr);
40
+ return(NULL);
41
+ }
42
+
43
+ /* add key to keys manager, from now on keys manager is responsible
44
+ * for destroying key
45
+ */
46
+ if(xmlSecCryptoAppDefaultKeysMngrAdoptKey(mngr, key) < 0) {
47
+ rb_raise(rb_eDecryptionError, "failed to add key to keys manager");
48
+ xmlSecKeyDestroy(key);
49
+ xmlSecKeysMngrDestroy(mngr);
50
+ return(NULL);
51
+ }
52
+
53
+ return(mngr);
54
+ }
55
+
56
+ VALUE encrypt_with_key(VALUE self, VALUE rb_key_name, VALUE rb_key) {
57
+ xmlDocPtr doc;
58
+ xmlNodePtr encDataNode = NULL;
59
+ xmlNodePtr encKeyNode = NULL;
60
+ xmlNodePtr keyInfoNode = NULL;
61
+ xmlSecEncCtxPtr encCtx = NULL;
62
+ xmlSecKeysMngrPtr keyManager = NULL;
63
+ char *keyName;
64
+ char *key;
65
+ unsigned int keyLength;
66
+
67
+ Check_Type(rb_key_name, T_STRING);
68
+ Check_Type(rb_key, T_STRING);
69
+ Data_Get_Struct(self, xmlDoc, doc);
70
+ key = RSTRING_PTR(rb_key);
71
+ keyLength = RSTRING_LEN(rb_key);
72
+ keyName = RSTRING_PTR(rb_key_name);
73
+
74
+ // create encryption template to encrypt XML file and replace
75
+ // its content with encryption result
76
+ encDataNode = xmlSecTmplEncDataCreate(doc, xmlSecTransformDes3CbcId,
77
+ NULL, xmlSecTypeEncElement, NULL, NULL);
78
+ if(encDataNode == NULL) {
79
+ rb_raise(rb_eEncryptionError, "failed to create encryption template");
80
+ goto done;
81
+ }
82
+
83
+ // we want to put encrypted data in the <enc:CipherValue/> node
84
+ if(xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL) {
85
+ rb_raise(rb_eEncryptionError, "failed to add CipherValue node");
86
+ goto done;
87
+ }
88
+
89
+ // add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name in the
90
+ // signed document
91
+ keyInfoNode = xmlSecTmplEncDataEnsureKeyInfo(encDataNode, NULL);
92
+ if(keyInfoNode == NULL) {
93
+ rb_raise(rb_eEncryptionError, "failed to add key info");
94
+ goto done;
95
+ }
96
+
97
+ if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) {
98
+ rb_raise(rb_eEncryptionError, "failed to add key name");
99
+ goto done;
100
+ }
101
+
102
+ keyManager = getKeyManager(key, keyLength, keyName);
103
+ if (keyManager == NULL) {
104
+ rb_raise(rb_eEncryptionError, "failed to create key manager");
105
+ goto done;
106
+ }
107
+
108
+ // create encryption context, we don't need keys manager in this example
109
+ encCtx = xmlSecEncCtxCreate(keyManager);
110
+ if(encCtx == NULL) {
111
+ rb_raise(rb_eEncryptionError, "failed to create encryption context");
112
+ goto done;
113
+ }
114
+
115
+ // generate a 3DES key
116
+ // TODO make a note of this one, it lets us pass in key type and bits from ruby
117
+ encCtx->encKey = xmlSecKeyGenerateByName((xmlChar *)"des", 192,
118
+ xmlSecKeyDataTypeSession);
119
+
120
+ // encCtx->encKey = xmlSecKeyGenerate(xmlSecKeyDataDesId, 192,
121
+ // xmlSecKeyDataTypeSession);
122
+ // encCtx->encKey = xmlSecAppCryptoKeyGenerate(xmlSecAppCmdLineParamGetString(&sessionKeyParam),
123
+ // NULL, xmlSecKeyDataTypeSession);
124
+ if(encCtx->encKey == NULL) {
125
+ rb_raise(rb_eDecryptionError, "failed to generate session des key");
126
+ goto done;
127
+ }
128
+
129
+ // set key name
130
+ if(xmlSecKeySetName(encCtx->encKey, (xmlSecByte *)keyName) < 0) {
131
+ rb_raise(rb_eEncryptionError, "failed to set key name to '%s'", keyName);
132
+ goto done;
133
+ }
134
+
135
+ // add <enc:EncryptedKey/> node to the <dsig:KeyInfo/> tag to include
136
+ // the session key
137
+ encKeyNode = xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode,
138
+ xmlSecTransformRsaPkcs1Id, // encMethodId encryptionMethod
139
+ NULL, // xmlChar *idAttribute
140
+ NULL, // xmlChar *typeAttribute
141
+ NULL // xmlChar *recipient
142
+ );
143
+ if (encKeyNode == NULL) {
144
+ rb_raise(rb_eEncryptionError, "failed to add encrypted key node");
145
+ goto done;
146
+ }
147
+ if (xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == NULL) {
148
+ rb_raise(rb_eEncryptionError, "failed to add encrypted cipher value");
149
+ goto done;
150
+ }
151
+
152
+ // encrypt the data
153
+ if(xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, xmlDocGetRootElement(doc)) < 0) {
154
+ rb_raise(rb_eEncryptionError, "encryption failed");
155
+ goto done;
156
+ }
157
+
158
+ // the template is inserted in the doc, so don't free it
159
+ encDataNode = NULL;
160
+ encKeyNode = NULL;
161
+
162
+ done:
163
+
164
+ /* cleanup */
165
+ if(encCtx != NULL) {
166
+ xmlSecEncCtxDestroy(encCtx);
167
+ }
168
+
169
+ if (encKeyNode != NULL) {
170
+ xmlFreeNode(encKeyNode);
171
+ }
172
+
173
+ if(encDataNode != NULL) {
174
+ xmlFreeNode(encDataNode);
175
+ }
176
+
177
+ if (keyManager != NULL) {
178
+ xmlSecKeysMngrDestroy(keyManager);
179
+ }
180
+
181
+ return T_NIL;
182
+ }
@@ -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, 3);
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,104 @@
1
+ #include "xmlsecrb.h"
2
+
3
+ VALUE sign_with_certificate(VALUE self, VALUE rb_key_name, VALUE rb_rsa_key, VALUE rb_cert) {
4
+ xmlDocPtr doc;
5
+ xmlNodePtr signNode = NULL;
6
+ xmlNodePtr refNode = NULL;
7
+ xmlNodePtr keyInfoNode = NULL;
8
+ xmlSecDSigCtxPtr dsigCtx = NULL;
9
+ char *keyName;
10
+ char *certificate;
11
+ char *rsaKey;
12
+ unsigned int rsaKeyLength, certificateLength;
13
+
14
+ Data_Get_Struct(self, xmlDoc, doc);
15
+ rsaKey = RSTRING_PTR(rb_rsa_key);
16
+ rsaKeyLength = RSTRING_LEN(rb_rsa_key);
17
+ keyName = RSTRING_PTR(rb_key_name);
18
+ certificate = RSTRING_PTR(rb_cert);
19
+ certificateLength = RSTRING_LEN(rb_cert);
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:X509Data/>
47
+ keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL);
48
+ if(keyInfoNode == NULL) {
49
+ rb_raise(rb_eSigningError, "failed to add key info");
50
+ goto done;
51
+ }
52
+
53
+ if(xmlSecTmplKeyInfoAddX509Data(keyInfoNode) == NULL) {
54
+ rb_raise(rb_eSigningError, "failed to add X509Data node");
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 not 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 key");
74
+ goto done;
75
+ }
76
+
77
+ // load certificate and add to the key
78
+ if(xmlSecCryptoAppKeyCertLoadMemory(dsigCtx->signKey,
79
+ (xmlSecByte *)certificate,
80
+ certificateLength,
81
+ xmlSecKeyDataFormatPem) < 0) {
82
+ rb_raise(rb_eSigningError, "failed to load certificate");
83
+ goto done;
84
+ }
85
+
86
+ // set key name
87
+ if(xmlSecKeySetName(dsigCtx->signKey, (xmlSecByte *)keyName) < 0) {
88
+ rb_raise(rb_eSigningError, "failed to set key name");
89
+ goto done;
90
+ }
91
+
92
+ // sign the template
93
+ if(xmlSecDSigCtxSign(dsigCtx, signNode) < 0) {
94
+ rb_raise(rb_eSigningError, "signature failed");
95
+ goto done;
96
+ }
97
+
98
+ done:
99
+ if(dsigCtx != NULL) {
100
+ xmlSecDSigCtxDestroy(dsigCtx);
101
+ }
102
+
103
+ return T_NIL;
104
+ }