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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.travis.yml +11 -0
- data/Gemfile +4 -0
- data/Guardfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +133 -0
- data/Rakefile +30 -0
- data/dependencies.yml +3 -0
- data/ext/nokogiri_ext_xmlsec/extconf.rb +489 -0
- data/ext/nokogiri_ext_xmlsec/init.c +46 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_decrypt_with_key.c +124 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_encrypt_with_key.c +182 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_helpers_set_attribute_id.c +43 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_init.c +32 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_sign_certificate.c +104 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_sign_rsa.c +95 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_certificates.c +96 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_named_keys.c +106 -0
- data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_rsa.c +56 -0
- data/ext/nokogiri_ext_xmlsec/shutdown.c +12 -0
- data/ext/nokogiri_ext_xmlsec/xmlsecrb.h +39 -0
- data/lib/nokogiri-xmlsec.rb +1 -0
- data/lib/xmlsec.rb +110 -0
- data/lib/xmlsec/version.rb +3 -0
- data/nokogiri-xmlsec1.gemspec +46 -0
- data/ports/patches/libxml2/0001-Fix-parser-local-buffers-size-problems.patch +265 -0
- data/ports/patches/libxml2/0002-Fix-entities-local-buffers-size-problems.patch +102 -0
- data/ports/patches/libxml2/0003-Fix-an-error-in-previous-commit.patch +26 -0
- data/ports/patches/libxml2/0004-Fix-potential-out-of-bound-access.patch +26 -0
- data/ports/patches/libxml2/0005-Detect-excessive-entities-expansion-upon-replacement.patch +158 -0
- data/ports/patches/libxml2/0006-Do-not-fetch-external-parsed-entities.patch +78 -0
- data/ports/patches/libxml2/0007-Enforce-XML_PARSER_EOF-state-handling-through-the-pa.patch +480 -0
- data/ports/patches/libxml2/0008-Improve-handling-of-xmlStopParser.patch +315 -0
- data/ports/patches/libxml2/0009-Fix-a-couple-of-return-without-value.patch +37 -0
- data/ports/patches/libxml2/0010-Keep-non-significant-blanks-node-in-HTML-parser.patch +2006 -0
- data/ports/patches/libxml2/0011-Do-not-fetch-external-parameter-entities.patch +39 -0
- data/ports/patches/libxslt/0001-Adding-doc-update-related-to-1.1.28.patch +222 -0
- data/ports/patches/libxslt/0002-Fix-a-couple-of-places-where-f-printf-parameters-wer.patch +53 -0
- data/ports/patches/libxslt/0003-Initialize-pseudo-random-number-generator-with-curre.patch +60 -0
- data/ports/patches/libxslt/0004-EXSLT-function-str-replace-is-broken-as-is.patch +42 -0
- data/ports/patches/libxslt/0006-Fix-str-padding-to-work-with-UTF-8-strings.patch +164 -0
- data/ports/patches/libxslt/0007-Separate-function-for-predicate-matching-in-patterns.patch +587 -0
- data/ports/patches/libxslt/0008-Fix-direct-pattern-matching.patch +80 -0
- data/ports/patches/libxslt/0009-Fix-certain-patterns-with-predicates.patch +185 -0
- data/ports/patches/libxslt/0010-Fix-handling-of-UTF-8-strings-in-EXSLT-crypto-module.patch +126 -0
- data/ports/patches/libxslt/0013-Memory-leak-in-xsltCompileIdKeyPattern-error-path.patch +25 -0
- data/ports/patches/libxslt/0014-Fix-for-bug-436589.patch +43 -0
- data/ports/patches/libxslt/0015-Fix-mkdir-for-mingw.patch +41 -0
- data/ports/patches/xmlsec1/.keep +0 -0
- data/spec/fixtures/cert/server.crt +14 -0
- data/spec/fixtures/cert/server.csr +11 -0
- data/spec/fixtures/cert/server.key.decrypted +15 -0
- data/spec/fixtures/cert/server.key.encrypted +18 -0
- data/spec/fixtures/rsa.pem +15 -0
- data/spec/fixtures/rsa.pub +6 -0
- data/spec/fixtures/sign2-doc.xml +6 -0
- data/spec/fixtures/sign2-result.xml +24 -0
- data/spec/fixtures/sign3-result.xml +37 -0
- data/spec/lib/nokogiri/xml/document/encryption_and_decryption_spec.rb +22 -0
- data/spec/lib/nokogiri/xml/document/signing_and_verifying_spec.rb +77 -0
- data/spec/spec_helper.rb +10 -0
- 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
|
+
}
|