nokogiri-xmlsec1 0.0.6

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 (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
+ }