nokogiri-xmlsec-instructure 0.9.4

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 (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +13 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +124 -0
  9. data/Rakefile +30 -0
  10. data/ext/nokogiri_ext_xmlsec/common.h +13 -0
  11. data/ext/nokogiri_ext_xmlsec/extconf.rb +27 -0
  12. data/ext/nokogiri_ext_xmlsec/init.c +76 -0
  13. data/ext/nokogiri_ext_xmlsec/nokogiri_decrypt_with_key.c +82 -0
  14. data/ext/nokogiri_ext_xmlsec/nokogiri_encrypt_with_key.c +169 -0
  15. data/ext/nokogiri_ext_xmlsec/nokogiri_helpers_set_attribute_id.c +94 -0
  16. data/ext/nokogiri_ext_xmlsec/nokogiri_init.c +30 -0
  17. data/ext/nokogiri_ext_xmlsec/nokogiri_sign.c +252 -0
  18. data/ext/nokogiri_ext_xmlsec/nokogiri_verify_with.c +259 -0
  19. data/ext/nokogiri_ext_xmlsec/options.c +166 -0
  20. data/ext/nokogiri_ext_xmlsec/options.h +36 -0
  21. data/ext/nokogiri_ext_xmlsec/shutdown.c +12 -0
  22. data/ext/nokogiri_ext_xmlsec/util.c +139 -0
  23. data/ext/nokogiri_ext_xmlsec/util.h +42 -0
  24. data/ext/nokogiri_ext_xmlsec/xmlsecrb.h +42 -0
  25. data/lib/nokogiri-xmlsec.rb +1 -0
  26. data/lib/xmlsec.rb +102 -0
  27. data/lib/xmlsec/version.rb +3 -0
  28. data/nokogiri-xmlsec-instructure.gemspec +39 -0
  29. data/spec/fixtures/cert/server.crt +14 -0
  30. data/spec/fixtures/cert/server.csr +11 -0
  31. data/spec/fixtures/cert/server.key.decrypted +15 -0
  32. data/spec/fixtures/cert/server.key.encrypted +18 -0
  33. data/spec/fixtures/hate.xml +7 -0
  34. data/spec/fixtures/pwned.xml +1 -0
  35. data/spec/fixtures/rsa.pem +15 -0
  36. data/spec/fixtures/rsa.pub +6 -0
  37. data/spec/fixtures/sign2-doc.xml +6 -0
  38. data/spec/fixtures/sign2-result.xml +25 -0
  39. data/spec/fixtures/sign3-result.xml +38 -0
  40. data/spec/lib/nokogiri/xml/document/encryption_and_decryption_spec.rb +34 -0
  41. data/spec/lib/nokogiri/xml/document/signing_and_verifying_spec.rb +122 -0
  42. data/spec/lib/nokogiri/xml/document/unsafe_xml_spec.rb +61 -0
  43. data/spec/spec_helper.rb +10 -0
  44. metadata +211 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ed59b79032290908cffa12a20deb7b0d5c2195e45a817e430d49bfc404243bee
4
+ data.tar.gz: b315b63fe30ab7760719bce3e435b36c3565b658eb0ac42d1fb6d6f48c65b974
5
+ SHA512:
6
+ metadata.gz: 660d2ff3242177e1e6fd09112afed32ae5507d331c3c2fedd7c920a75cf09b58115ca14d3915fa76297ee7879594b314caacef967b5b90903d3fd1b9b36a4aff
7
+ data.tar.gz: d96e85677b8f9c34b3df00ae1d878d1de8c8f69d7ed5d78f76a680a504e8afcee4d55c398ccdc6e766a773a1bb45466bbe507985930839c4591dd2c452d8153d
@@ -0,0 +1,20 @@
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
20
+ *.sw[opn]
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+
@@ -0,0 +1,3 @@
1
+ before_install:
2
+ - sudo apt-get update -qq
3
+ - sudo apt-get install -y libxmlsec1-dev
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in xmlsec.gemspec
4
+ gemspec
@@ -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
@@ -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.
@@ -0,0 +1,124 @@
1
+ # nokogiri-xmlsec
2
+
3
+ [![Build Status](https://travis-ci.org/omb-awong/xmlsec.svg)](https://travis-ci.org/omb-awong/xmlsec)
4
+
5
+ Adds support to Ruby for encrypting, decrypting, signing and validating
6
+ the signatures of XML documents, according to the [XML Encryption Syntax and
7
+ Processing](http://www.w3.org/TR/xmlenc-core/) standard, by wrapping around the
8
+ [xmlsec](http://www.aleksey.com/xmlsec) C library and adding relevant methods
9
+ to `Nokogiri::XML::Document`.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'nokogiri-xmlsec'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install nokogiri-xmlsec
24
+
25
+ ## Usage
26
+
27
+ Several methods are added to `Nokogiri::XML::Document` which expose this gem's
28
+ functionality.
29
+
30
+ ### Signing
31
+
32
+ The `sign!` method adds a digital signature to the XML document so that it can
33
+ later be determined whether the document itself has been tampered with. If the
34
+ document changes, the signature will be invalid.
35
+
36
+ Signing a document will add XML nodes directly to the document itself, and
37
+ then returns itself.
38
+
39
+ # First, get an XML document
40
+ doc = Nokogiri::XML("<doc><greeting>Hello, World!</greeting></doc>")
41
+
42
+ # Sign the document with a certificate, a key, and a key name
43
+ doc.sign! cert: 'certificate data',
44
+ key: 'private key data',
45
+ name: 'private key name',
46
+ digest_alg: 'sha256',
47
+ signature_alg: 'rsa-sha256'
48
+
49
+ If you pass `cert`, the certificate will be included as part of the signature,
50
+ so that it can be later verified by certificate instead of by key.
51
+
52
+ `name` can be used to verify the signature with any of a set of keys, as in the
53
+ following example:
54
+
55
+ ### Signature verification
56
+
57
+ Verification of signatures always returns `true` if successful, `false`
58
+ otherwise.
59
+
60
+ # Verify the document's signature to ensure it has not been tampered with
61
+ doc.verify_with({
62
+ 'key-name-1' => 'public key contents',
63
+ 'key-name-2' => 'another public key content'
64
+ })
65
+
66
+ In the above example, the `name` field from the signing process will be used
67
+ to determine which key to validate with. If you plan to always verify with the
68
+ same key, you can do it like so, effectively ignoring the `name` value:
69
+
70
+ # Verify the document's signature with a specific key
71
+ doc.verify_with key: 'public key contents'
72
+
73
+ Finally, you can also verify with a certificate:
74
+
75
+ # Verify the document's signature with a single certificate
76
+ doc.verify_with cert: 'certificate data'
77
+
78
+ # Verify the document's signature with multiple certificates. Any one match
79
+ # will pass verification.
80
+ doc.verify_with certs: [ 'cert1', 'cert2', 'cert3' ]
81
+
82
+ If the certificate has been installed to your system certificates, then you can
83
+ verify signatures like so:
84
+
85
+ # Verify with installed CA certificates
86
+ doc.verify_signature
87
+
88
+ ### Encryption & Decryption
89
+
90
+ Encrypted documents can only be decrypted with the private key that corresponds
91
+ to the public key that was used to encrypt it. Thus, the party that encrypted
92
+ the document can be sure that the document will only be readable by its intended
93
+ recipient.
94
+
95
+ Both encryption and decryption of a document manipulates the XML nodes of the
96
+ document in-place. Both methods return the original document, after the changes
97
+ have been made to it.
98
+
99
+ To encrypt a document, use a public key:
100
+
101
+ doc.encrypt! key: 'public key content'
102
+
103
+ To decrypt a document, use a private key:
104
+
105
+ doc.decrypt! key: 'private key content'
106
+
107
+
108
+ ## Limitations and Known Issues
109
+
110
+ Following is a list of limitations and/or issues I know about, but have no
111
+ immediate plan to resolve. This is probably because I haven't needed the
112
+ functionality, and no one has sent a pull request. (Hint, hint!)
113
+
114
+ - Currently, it is not possible to encrypt/decrypt individual XML nodes. The
115
+ `nokogiri-xmlsec` operations must be performed on the entire document.
116
+ You _can_ sign an individual node.
117
+
118
+ ## Contributing
119
+
120
+ 1. Fork it
121
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
122
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
123
+ 4. Push to the branch (`git push origin my-new-feature`)
124
+ 5. Create new Pull Request
@@ -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,13 @@
1
+ #ifndef NOKOGIRI_EXT_XMLSEC_COMMON_H
2
+ #define NOKOGIRI_EXT_XMLSEC_COMMON_H
3
+
4
+ #ifndef TRUE
5
+ #define TRUE 1
6
+ #endif
7
+ #ifndef FALSE
8
+ #define FALSE 0
9
+ #endif
10
+
11
+ typedef int BOOL;
12
+
13
+ #endif // NOKOGIRI_EXT_XMLSEC_COMMON_H
@@ -0,0 +1,27 @@
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
+ pkg_config('xmlsec1')
10
+ $CFLAGS << " " + `xmlsec1-config --cflags`.strip
11
+ $CFLAGS << " -fvisibility=hidden"
12
+
13
+ if $CFLAGS =~ /\-DXMLSEC_CRYPTO=\\\\\\"openssl\\\\\\"/
14
+ puts "Changing escaping: #{$CFLAGS}"
15
+ $CFLAGS['-DXMLSEC_CRYPTO=\\\\\\"openssl\\\\\\"'] =
16
+ '-DXMLSEC_CRYPTO=\\"openssl\\"'
17
+ end
18
+
19
+ if $CFLAGS =~ /\-DXMLSEC_CRYPTO="openssl"/
20
+ puts "Ensure we escaping: #{$CFLAGS}"
21
+ $CFLAGS['-DXMLSEC_CRYPTO="openssl"'] =
22
+ '-DXMLSEC_CRYPTO=\\"openssl\\"'
23
+ end
24
+
25
+ puts "Clfags: #{$CFLAGS}"
26
+ $libs = `xmlsec1-config --libs`.strip
27
+ create_makefile('nokogiri_ext_xmlsec')
@@ -0,0 +1,76 @@
1
+ #include "xmlsecrb.h"
2
+ #include "util.h"
3
+
4
+ #include <xmlsec/dl.h>
5
+ #include <xmlsec/errors.h>
6
+
7
+ #ifndef XMLSEC_NO_XSLT
8
+ #include <libxslt/xslt.h>
9
+ #include <libxslt/security.h>
10
+ #endif /* XMLSEC_NO_XSLT */
11
+
12
+ EXTENSION_EXPORT
13
+ void Init_nokogiri_ext_xmlsec() {
14
+ #ifndef XMLSEC_NO_XSLT
15
+ xsltSecurityPrefsPtr xsltSecPrefs = NULL;
16
+ #endif /* XMLSEC_NO_XSLT */
17
+
18
+ /* xmlsec proper */
19
+ // libxml
20
+ xmlInitParser();
21
+ LIBXML_TEST_VERSION
22
+ xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
23
+ xmlSubstituteEntitiesDefault(1);
24
+ // xslt
25
+
26
+ #ifndef XMLSEC_NO_XSLT
27
+ xmlIndentTreeOutput = 1;
28
+
29
+ /* Disable all XSLT options that give filesystem and network access. */
30
+ xsltSecPrefs = xsltNewSecurityPrefs();
31
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
32
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
33
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
34
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
35
+ xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
36
+ xsltSetDefaultSecurityPrefs(xsltSecPrefs);
37
+ #endif /* XMLSEC_NO_XSLT */
38
+
39
+ // xmlsec
40
+
41
+ if (xmlSecInit() < 0) {
42
+ rb_raise(rb_eRuntimeError, "xmlsec initialization failed");
43
+ return;
44
+ }
45
+ if (xmlSecCheckVersion() != 1) {
46
+ rb_raise(rb_eRuntimeError, "xmlsec version is not compatible");
47
+ return;
48
+ }
49
+ // load crypto
50
+ #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
51
+ if(xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
52
+ rb_raise(rb_eRuntimeError,
53
+ "Error: unable to load default xmlsec-crypto library. Make sure"
54
+ "that you have it installed and check shared libraries path\n"
55
+ "(LD_LIBRARY_PATH) envornment variable.\n");
56
+ return;
57
+ }
58
+ #endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
59
+ // init crypto
60
+ if (xmlSecCryptoAppInit(NULL) < 0) {
61
+ rb_raise(rb_eRuntimeError, "unable to initialize crypto engine");
62
+ return;
63
+ }
64
+ // init xmlsec-crypto library
65
+ if (xmlSecCryptoInit() < 0) {
66
+ rb_raise(rb_eRuntimeError, "xmlsec-crypto initialization failed");
67
+ }
68
+
69
+ // Set Error callback catcher last because various modules also call this.
70
+ // This way we always win.
71
+ xmlSecErrorsSetCallback(storeErrorCallback);
72
+
73
+ /* ruby classes & objects */
74
+ Init_Nokogiri_ext();
75
+ }
76
+
@@ -0,0 +1,82 @@
1
+ #include "xmlsecrb.h"
2
+ #include "util.h"
3
+
4
+ VALUE decrypt_with_key(VALUE self, VALUE rb_key_name, VALUE rb_key) {
5
+ VALUE rb_exception_result = Qnil;
6
+ const char* exception_message = NULL;
7
+
8
+ xmlNodePtr node = NULL;
9
+ xmlSecEncCtxPtr encCtx = NULL;
10
+ xmlSecKeysMngrPtr keyManager = NULL;
11
+ char *key = NULL;
12
+ char *keyName = NULL;
13
+ unsigned int keyLength = 0;
14
+
15
+ resetXmlSecError();
16
+
17
+ Check_Type(rb_key, T_STRING);
18
+ Check_Type(rb_key_name, T_STRING);
19
+ Data_Get_Struct(self, xmlNode, node);
20
+ key = RSTRING_PTR(rb_key);
21
+ keyLength = RSTRING_LEN(rb_key);
22
+ keyName = StringValueCStr(rb_key_name);
23
+
24
+ keyManager = createKeyManagerWithSingleKey(key, keyLength, keyName,
25
+ &rb_exception_result,
26
+ &exception_message);
27
+ if (keyManager == NULL) {
28
+ // Propagate the exception.
29
+ goto done;
30
+ }
31
+
32
+ // create encryption context
33
+ encCtx = xmlSecEncCtxCreate(keyManager);
34
+ if(encCtx == NULL) {
35
+ rb_exception_result = rb_eDecryptionError;
36
+ exception_message = "failed to create encryption context";
37
+ goto done;
38
+ }
39
+ // don't let xmlsec free the node we're looking at out from under us
40
+ encCtx->flags |= XMLSEC_ENC_RETURN_REPLACED_NODE;
41
+
42
+ // decrypt the data
43
+ if((xmlSecEncCtxDecrypt(encCtx, node) < 0) || (encCtx->result == NULL)) {
44
+ rb_exception_result = rb_eDecryptionError;
45
+ exception_message = "decryption failed";
46
+ goto done;
47
+ }
48
+
49
+ if(encCtx->resultReplaced == 0) {
50
+ rb_exception_result = rb_eDecryptionError;
51
+ exception_message = "Not implemented: don't know how to handle decrypted, non-XML data yet";
52
+ goto done;
53
+ }
54
+
55
+ done:
56
+ // cleanup
57
+ if(encCtx != NULL) {
58
+ // the replaced node is orphaned, but not freed; let Nokogiri
59
+ // own it now
60
+ if(encCtx->replacedNodeList != NULL) {
61
+ nokogiri_root_node(encCtx->replacedNodeList);
62
+ // no really, please don't free it
63
+ encCtx->replacedNodeList = NULL;
64
+ }
65
+ xmlSecEncCtxDestroy(encCtx);
66
+ }
67
+
68
+ if (keyManager != NULL) {
69
+ xmlSecKeysMngrDestroy(keyManager);
70
+ }
71
+
72
+ if(rb_exception_result != Qnil) {
73
+ if (hasXmlSecLastError()) {
74
+ rb_raise(rb_exception_result, "%s, XmlSec error: %s", exception_message,
75
+ getXmlSecLastError());
76
+ } else {
77
+ rb_raise(rb_exception_result, "%s", exception_message);
78
+ }
79
+ }
80
+
81
+ return Qnil;
82
+ }
@@ -0,0 +1,169 @@
1
+ #include "xmlsecrb.h"
2
+ #include "options.h"
3
+ #include "util.h"
4
+
5
+ // Encrypes the XML Document document using XMLEnc.
6
+ //
7
+ // Expects 3 positional arguments:
8
+ // rb_rsa_key_name - String with name of the rsa key. May be the empty.
9
+ // rb_rsa_key - A PEM encoded rsa key for signing.
10
+ // rb_opts - An ruby hash that configures the encryption options.
11
+ // See XmlEncOptions struct for possible values.
12
+ VALUE encrypt_with_key(VALUE self, VALUE rb_rsa_key_name, VALUE rb_rsa_key,
13
+ VALUE rb_opts) {
14
+ VALUE rb_exception_result = Qnil;
15
+ const char* exception_message = NULL;
16
+
17
+ xmlDocPtr doc = NULL;
18
+ xmlNodePtr encDataNode = NULL;
19
+ xmlNodePtr encKeyNode = NULL;
20
+ xmlNodePtr keyInfoNode = NULL;
21
+ xmlSecEncCtxPtr encCtx = NULL;
22
+ xmlSecKeysMngrPtr keyManager = NULL;
23
+ char *keyName = NULL;
24
+ char *key = NULL;
25
+ unsigned int keyLength = 0;
26
+
27
+ resetXmlSecError();
28
+
29
+ Check_Type(rb_rsa_key, T_STRING);
30
+ Check_Type(rb_rsa_key_name, T_STRING);
31
+ Check_Type(rb_opts, T_HASH);
32
+
33
+ key = RSTRING_PTR(rb_rsa_key);
34
+ keyLength = RSTRING_LEN(rb_rsa_key);
35
+ keyName = StringValueCStr(rb_rsa_key_name);
36
+
37
+ XmlEncOptions options;
38
+ if (!GetXmlEncOptions(rb_opts, &options, &rb_exception_result,
39
+ &exception_message)) {
40
+ goto done;
41
+ }
42
+
43
+ Data_Get_Struct(self, xmlDoc, doc);
44
+
45
+ // create encryption template to encrypt XML file and replace
46
+ // its content with encryption result
47
+ encDataNode = xmlSecTmplEncDataCreate(doc, options.block_encryption, NULL,
48
+ xmlSecTypeEncElement, NULL, NULL);
49
+ if(encDataNode == NULL) {
50
+ rb_exception_result = rb_eEncryptionError;
51
+ exception_message = "failed to create encryption template";
52
+ goto done;
53
+ }
54
+
55
+ // we want to put encrypted data in the <enc:CipherValue/> node
56
+ if(xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL) {
57
+ rb_exception_result = rb_eEncryptionError;
58
+ exception_message = "failed to add CipherValue node";
59
+ goto done;
60
+ }
61
+
62
+ // add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name in the
63
+ // signed document
64
+ keyInfoNode = xmlSecTmplEncDataEnsureKeyInfo(encDataNode, NULL);
65
+ if(keyInfoNode == NULL) {
66
+ rb_exception_result = rb_eEncryptionError;
67
+ exception_message = "failed to add key info";
68
+ goto done;
69
+ }
70
+
71
+ if(xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL) {
72
+ rb_exception_result = rb_eEncryptionError;
73
+ exception_message = "failed to add key name";
74
+ goto done;
75
+ }
76
+
77
+ if ((keyManager = createKeyManagerWithSingleKey(
78
+ key, keyLength, keyName,
79
+ &rb_exception_result,
80
+ &exception_message)) == NULL) {
81
+ // Propagate the exception.
82
+ goto done;
83
+ }
84
+
85
+ // create encryption context, we don't need keys manager in this example
86
+ encCtx = xmlSecEncCtxCreate(keyManager);
87
+ if(encCtx == NULL) {
88
+ rb_exception_result = rb_eEncryptionError;
89
+ exception_message = "failed to create encryption context";
90
+ goto done;
91
+ }
92
+
93
+ // Generate the symmetric key.
94
+ encCtx->encKey = xmlSecKeyGenerateByName(BAD_CAST options.key_type, options.key_bits,
95
+ xmlSecKeyDataTypeSession);
96
+
97
+ if(encCtx->encKey == NULL) {
98
+ rb_exception_result = rb_eDecryptionError;
99
+ exception_message = "failed to generate session key";
100
+ goto done;
101
+ }
102
+
103
+ // Set key name.
104
+ if(xmlSecKeySetName(encCtx->encKey, (xmlSecByte *)keyName) < 0) {
105
+ rb_exception_result = rb_eEncryptionError;
106
+ exception_message = "failed to set key name";
107
+ goto done;
108
+ }
109
+
110
+ // Add <enc:EncryptedKey/> node to the <dsig:KeyInfo/> tag to include
111
+ // the session key.
112
+ encKeyNode = xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode,
113
+ options.key_transport, // encMethodId encryptionMethod
114
+ NULL, // xmlChar *idAttribute
115
+ NULL, // xmlChar *typeAttribute
116
+ NULL // xmlChar *recipient
117
+ );
118
+ if (encKeyNode == NULL) {
119
+ rb_exception_result = rb_eEncryptionError;
120
+ exception_message = "failed to add encrypted key node";
121
+ goto done;
122
+ }
123
+ if (xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == NULL) {
124
+ rb_exception_result = rb_eEncryptionError;
125
+ exception_message = "failed to add encrypted cipher value";
126
+ goto done;
127
+ }
128
+
129
+ // encrypt the data
130
+ if(xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, xmlDocGetRootElement(doc)) < 0) {
131
+ rb_exception_result = rb_eEncryptionError;
132
+ exception_message = "encryption failed";
133
+ goto done;
134
+ }
135
+
136
+ // the template is inserted in the doc, so don't free it
137
+ encDataNode = NULL;
138
+ encKeyNode = NULL;
139
+
140
+ done:
141
+
142
+ /* cleanup */
143
+ if(encCtx != NULL) {
144
+ xmlSecEncCtxDestroy(encCtx);
145
+ }
146
+
147
+ if (encKeyNode != NULL) {
148
+ xmlFreeNode(encKeyNode);
149
+ }
150
+
151
+ if(encDataNode != NULL) {
152
+ xmlFreeNode(encDataNode);
153
+ }
154
+
155
+ if (keyManager != NULL) {
156
+ xmlSecKeysMngrDestroy(keyManager);
157
+ }
158
+
159
+ if(rb_exception_result != Qnil) {
160
+ if (hasXmlSecLastError()) {
161
+ rb_raise(rb_exception_result, "%s, XmlSec error: %s", exception_message,
162
+ getXmlSecLastError());
163
+ } else {
164
+ rb_raise(rb_exception_result, "%s", exception_message);
165
+ }
166
+ }
167
+
168
+ return Qnil;
169
+ }