nokogiri-xmlsec 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
+ }