nokogiri-xmlsec 0.0.3

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 (37) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -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 +182 -0
  13. data/ext/nokogiri_ext_xmlsec/nokogiri_init.c +29 -0
  14. data/ext/nokogiri_ext_xmlsec/nokogiri_sign_certificate.c +104 -0
  15. data/ext/nokogiri_ext_xmlsec/nokogiri_sign_rsa.c +95 -0
  16. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_certificates.c +96 -0
  17. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_named_keys.c +106 -0
  18. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_signature_rsa.c +56 -0
  19. data/ext/nokogiri_ext_xmlsec/shutdown.c +12 -0
  20. data/ext/nokogiri_ext_xmlsec/xmlsecrb.h +38 -0
  21. data/lib/nokogiri-xmlsec.rb +1 -0
  22. data/lib/xmlsec.rb +110 -0
  23. data/lib/xmlsec/version.rb +3 -0
  24. data/nokogiri-xmlsec.gemspec +36 -0
  25. data/spec/fixtures/cert/server.crt +14 -0
  26. data/spec/fixtures/cert/server.csr +11 -0
  27. data/spec/fixtures/cert/server.key.decrypted +15 -0
  28. data/spec/fixtures/cert/server.key.encrypted +18 -0
  29. data/spec/fixtures/rsa.pem +15 -0
  30. data/spec/fixtures/rsa.pub +6 -0
  31. data/spec/fixtures/sign2-doc.xml +6 -0
  32. data/spec/fixtures/sign2-result.xml +24 -0
  33. data/spec/fixtures/sign3-result.xml +37 -0
  34. data/spec/lib/nokogiri/xml/document/encryption_and_decryption_spec.rb +28 -0
  35. data/spec/lib/nokogiri/xml/document/signing_and_verifying_spec.rb +70 -0
  36. data/spec/spec_helper.rb +10 -0
  37. metadata +196 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5ce9aa5774cf601b1d61c7a91d1a40b54ccc1707
4
+ data.tar.gz: 09ddf766c88fd311c714f1d64f20ba8c2be1de55
5
+ SHA512:
6
+ metadata.gz: 8dc8f5fb6f6523d39572a633e91b1948dc4fb3b956082e50919dbfb06565872b2d26ac3ffce27aa3a3cf79fe5e264235ecb25900e9ef3b4169a31687848bed30
7
+ data.tar.gz: de1fb73e0f83c43c9f4f1de2afcc13f7b65a7b41dedacc727b37341ea325f54e03f7764ced670e1c946bcbcb51994edce0dadf2e398bd03661a09362f6731f76
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ spec/old
19
+ *.so
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in xmlsec.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,13 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rake', :task => 'default' do
5
+ watch(/^ext\//)
6
+ end
7
+
8
+ guard 'rspec' do
9
+ watch(%r{^spec/.+_spec\.rb$})
10
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
11
+ watch('spec/spec_helper.rb') { "spec" }
12
+ # watch(/^ext\//) { "spec" }
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # nokogiri-xmlsec
2
+
3
+ Adds support to Ruby for encrypting, decrypting, signing and validating
4
+ the signatures of XML documents, according to the [XML Encryption Syntax and
5
+ Processing](http://www.w3.org/TR/xmlenc-core/) standard, by wrapping around the
6
+ [xmlsec](http://www.aleksey.com/xmlsec) C library and adding relevant methods
7
+ to `Nokogiri::XML::Document`.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'nokogiri-xmlsec'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install nokogiri-xmlsec
22
+
23
+ ## Usage
24
+
25
+ Several methods are added to `Nokogiri::XML::Document` which expose this gem's
26
+ functionality.
27
+
28
+ ### Signing
29
+
30
+ The `sign!` method adds a digital signature to the XML document so that it can
31
+ later be determined whether the document itself has been tampered with. If the
32
+ document changes, the signature will be invalid.
33
+
34
+ Signing a document will add XML nodes directly to the document itself, and
35
+ then returns itself.
36
+
37
+ # First, get an XML document
38
+ doc = Nokogiri::XML("<doc><greeting>Hello, World!</greeting></doc>")
39
+
40
+ # Sign the document with a certificate, a key, and a key name
41
+ doc.sign! certificate: 'certificate data',
42
+ key: 'private key data',
43
+ name: 'private key name'
44
+
45
+ You only need one of `certificate` or `key`, but you can pass both. If you do,
46
+ the certificate will be included as part of the signature, so that it can be
47
+ later verified by certificate instead of by key.
48
+
49
+ The `name` is implicitly converted into a string. Thus it is effectively
50
+ optional, since `nil` converts to `""`, and its value only matters if you plan
51
+ to verify the signature with any of a set of keys, as in the following example:
52
+
53
+ ### Signature verification
54
+
55
+ Verification of signatures always returns `true` if successful, `false`
56
+ otherwise.
57
+
58
+ # Verify the document's signature to ensure it has not been tampered with
59
+ doc.verify_with({
60
+ 'key-name-1' => 'public key contents',
61
+ 'key-name-2' => 'another public key content'
62
+ })
63
+
64
+ In the above example, the `name` field from the signing process will be used
65
+ to determine which key to validate with. If you plan to always verify with the
66
+ same key, you can do it like so, effectively ignoring the `name` value:
67
+
68
+ # Verify the document's signature with a specific key
69
+ doc.verify_with key: 'public key contents'
70
+
71
+ Finally, you can also verify with a certificate:
72
+
73
+ # Verify the document's signature with a single certificate
74
+ doc.verify_with certificate: 'certificate data'
75
+
76
+ # Verify the document's signature with multiple certificates. Any one match
77
+ # will pass verification.
78
+ doc.verify_with certificates: [ 'cert1', 'cert2', 'cert3' ]
79
+
80
+ If the certificate has been installed to your system certificates, then you can
81
+ verify signatures like so:
82
+
83
+ # Verify with installed CA certificates
84
+ doc.verify_signature
85
+
86
+ ### Encryption & Decryption
87
+
88
+ Encrypted documents can only be decrypted with the private key that corresponds
89
+ to the public key that was used to encrypt it. Thus, the party that encrypted
90
+ the document can be sure that the document will only be readable by its intended
91
+ recipient.
92
+
93
+ Both encryption and decryption of a document manipulates the XML nodes of the
94
+ document in-place. Both methods return the original document, after the changes
95
+ have been made to it.
96
+
97
+ To encrypt a document, use a public key:
98
+
99
+ doc.encrypt! key: 'public key content'
100
+
101
+ To decrypt a document, use a private key:
102
+
103
+ doc.decrypt! key: 'private key content'
104
+
105
+
106
+ ## Limitations and Known Issues
107
+
108
+ Following is a list of limitations and/or issues I know about, but have no
109
+ immediate plan to resolve. This is probably because I haven't needed the
110
+ functionality, and no one has sent a pull request. (Hint, hint!)
111
+
112
+ - Currently, it is not possible to operate on individual XML nodes. The
113
+ `nokogiri-xmlsec` operations must be performed on the entire document.
114
+
115
+ ## Contributing
116
+
117
+ 1. Fork it
118
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
119
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
120
+ 4. Push to the branch (`git push origin my-new-feature`)
121
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/extensiontask'
3
+ require 'rspec/core/rake_task'
4
+
5
+ Rake::ExtensionTask.new('nokogiri_ext_xmlsec')
6
+
7
+ RSpec::Core::RakeTask.new :rspec
8
+
9
+ desc 'clean out build files'
10
+ task :clean do
11
+ rm_rf File.expand_path('../tmp', __FILE__)
12
+ end
13
+
14
+ task :default => [:clean, :compile, :rspec]
15
+
16
+ desc 'code statistics, cause im a stats junky'
17
+ task :stats do
18
+ def count(glob)
19
+ Dir[glob].inject(0) do |count, fi|
20
+ next unless File.file?(fi)
21
+ count + File.read(fi).lines.length
22
+ end
23
+ end
24
+
25
+ rb_lines = count 'lib/**/*.rb'
26
+ c_lines = count 'ext/**/*.{c,h}'
27
+
28
+ puts "Lines of Ruby: #{rb_lines}"
29
+ puts "Lines of C: #{c_lines}"
30
+ end
@@ -0,0 +1,20 @@
1
+ require 'mkmf'
2
+
3
+ def barf message = 'dependencies not met'
4
+ raise message
5
+ end
6
+
7
+ barf unless have_header('ruby.h')
8
+
9
+ if pkg_config('xmlsec1-openssl')
10
+ # HACK 'openssl' is escaped too many times, I don't know why
11
+ if $CFLAGS =~ /\-DXMLSEC_CRYPTO=\\\\\\"openssl\\\\\\"/
12
+ $CFLAGS['-DXMLSEC_CRYPTO=\\\\\\"openssl\\\\\\"'] =
13
+ '-DXMLSEC_CRYPTO=\\"openssl\\"'
14
+ end
15
+
16
+ have_library 'xmlsec1-openssl'
17
+ create_makefile('nokogiri_ext_xmlsec')
18
+ else
19
+ barf "xmlsec1 is not installed."
20
+ end
@@ -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
+ }