xmlenc 0.0.1

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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZTg0OGJjOWQ5MzI1MDU2ZTZlYjk0ODU5NzE1ZjYyMDJhMzZmZmYwNQ==
5
+ data.tar.gz: !binary |-
6
+ OTk5OGFmZWM2NTNmMmUzNGQxNDE4NjgyZTlkMWUwNWQ4MWMzZGYxNw==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NmY0ZGQyMTZjNzk2N2E5NzQ1M2I5MTUyNzBhZDhiYWQwYjE3ZGM4ZDhlZTBj
10
+ ODY5MjJhNzVmZGFjZTE1Yzk2YjZjZGM1ZTlkZmZlNzY1ZWJhMjY2NWM4NjI0
11
+ OWYzNTBkMTE4ZDNlOTU2MThlNzAwNzk2MmEyNWY4ZWEzNDFjMDM=
12
+ data.tar.gz: !binary |-
13
+ ZjNlZTYxMTQ1ZGM4YjdjODcyNTdkNTkxMDhiZTJkYjA5YmMxOWJkZGVmNzFh
14
+ MjkwODNkNTBhMjY2NTg5MGI1OGVhMzBlZmJjZWEwYTQxODI0ZjYwOWVmYWI2
15
+ YWVjZjk2MDFiMjZhNmNlMTc1MDY3MTViMWU5MGYxOTkwOWYyOWQ=
@@ -0,0 +1,18 @@
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
+ .idea
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in xmlenc.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Benoist
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,29 @@
1
+ # Xmlenc
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'xmlenc'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install xmlenc
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,25 @@
1
+ require 'xmlenc/version'
2
+ require 'openssl'
3
+ require 'base64'
4
+ require 'nokogiri'
5
+
6
+ module Xmlenc
7
+ NAMESPACES = {
8
+ xenc: 'http://www.w3.org/2001/04/xmlenc#',
9
+ ds: 'http://www.w3.org/2000/09/xmldsig#'
10
+ }
11
+
12
+ class UnsupportedError < StandardError
13
+ end
14
+
15
+ module Algorithms
16
+ autoload :Rsa15, 'xmlenc/algorithms/rsa_15'
17
+ autoload :RsaOaepMgf1p, 'xmlenc/algorithms/rsa_oaep_mgf1p'
18
+ autoload :DES3CBC, 'xmlenc/algorithms/des3_cbc'
19
+ autoload :AESCBC, 'xmlenc/algorithms/aes_cbc'
20
+ end
21
+
22
+ autoload :EncryptedDocument, 'xmlenc/encrypted_document'
23
+ autoload :EncryptedData, 'xmlenc/encrypted_data'
24
+ autoload :EncryptedKey, 'xmlenc/encrypted_key'
25
+ end
@@ -0,0 +1,38 @@
1
+ module Xmlenc
2
+ module Algorithms
3
+ class AESCBC
4
+ class << self
5
+ def [](size)
6
+ new(size)
7
+ end
8
+ end
9
+
10
+ def initialize(size)
11
+ @size = size
12
+ end
13
+
14
+ def setup(key)
15
+ @key = key
16
+ self
17
+ end
18
+
19
+ def decrypt(cipher_value, options = {})
20
+ cipher.decrypt
21
+ cipher.key = @key
22
+ cipher.iv = cipher_value[0...iv_len]
23
+ result = cipher.update(cipher_value[iv_len..-1])
24
+ result << cipher.final
25
+ end
26
+
27
+ private
28
+
29
+ def iv_len
30
+ cipher.iv_len
31
+ end
32
+
33
+ def cipher
34
+ @cipher ||= OpenSSL::Cipher::Cipher.new("aes-#{@size}-cbc")
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ module Xmlenc
2
+ module Algorithms
3
+ class DES3CBC
4
+ def self.setup(key)
5
+ new(key)
6
+ end
7
+
8
+ def initialize(key)
9
+ @key = key
10
+ end
11
+
12
+ def decrypt(cipher_value, options = {})
13
+ cipher.decrypt
14
+ cipher.key = @key
15
+ cipher.iv = cipher_value[0...iv_len]
16
+ result = cipher.update(cipher_value[iv_len..-1])
17
+ result << cipher.final
18
+ end
19
+
20
+ private
21
+
22
+ def iv_len
23
+ cipher.iv_len
24
+ end
25
+
26
+ def cipher
27
+ @cipher ||= OpenSSL::Cipher::Cipher.new('des-ede3-cbc')
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ module Xmlenc
2
+ module Algorithms
3
+ class Rsa15
4
+ def initialize(key)
5
+ @key = key
6
+ end
7
+
8
+ def decrypt(cipher_value, options = {})
9
+ @key.private_decrypt(cipher_value)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ module Xmlenc
2
+ module Algorithms
3
+ class RsaOaepMgf1p
4
+ DIGEST_METHODS = %w(http://www.w3.org/2000/09/xmldsig#sha1)
5
+
6
+ def initialize(key)
7
+ @key = key
8
+ end
9
+
10
+ def decrypt(cipher_value, options = {})
11
+ verify_algorithm(options[:node])
12
+ @key.private_decrypt(cipher_value, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
13
+ end
14
+
15
+ private
16
+
17
+ def verify_algorithm(node)
18
+ digest_method = node.at_xpath('./ds:DigestMethod', NAMESPACES)['Algorithm']
19
+ unless DIGEST_METHODS.include? digest_method
20
+ raise UnsupportedError.new("RSA OEAP MGF1P unsupported digest method #{digest_method}")
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,44 @@
1
+ module Xmlenc
2
+ class EncryptedData
3
+ ALGORITHMS = {
4
+ 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc' => Algorithms::DES3CBC,
5
+ 'http://www.w3.org/2001/04/xmlenc#aes128-cbc' => Algorithms::AESCBC[128],
6
+ 'http://www.w3.org/2001/04/xmlenc#aes256-cbc' => Algorithms::AESCBC[256]
7
+ }
8
+
9
+ attr_accessor :node
10
+
11
+ def initialize(node)
12
+ @node = node
13
+ end
14
+
15
+ def document
16
+ @node.document
17
+ end
18
+
19
+ def encryption_method
20
+ at_xpath('./xenc:EncryptionMethod')
21
+ end
22
+
23
+ def cipher_value
24
+ at_xpath('./xenc:CipherData/xenc:CipherValue').content.gsub(/[\n\s]/, '')
25
+ end
26
+
27
+ def decrypt(key)
28
+ decryptor = algorithm.setup(key)
29
+ decryptor.decrypt(Base64.decode64(cipher_value), node: encryption_method)
30
+ end
31
+
32
+ private
33
+
34
+ def at_xpath(xpath)
35
+ @node.at_xpath(xpath, NAMESPACES)
36
+ end
37
+
38
+ def algorithm
39
+ algorithm = encryption_method['Algorithm']
40
+ ALGORITHMS[algorithm] ||
41
+ raise(UnsupportedError.new("Unsupported encryption method #{algorithm}"))
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,28 @@
1
+ module Xmlenc
2
+ class EncryptedDocument
3
+ attr_accessor :xml
4
+
5
+ def initialize(xml)
6
+ @xml = xml
7
+ end
8
+
9
+ def document
10
+ @document = Nokogiri::XML::Document.parse(xml)
11
+ end
12
+
13
+ def encrypted_keys
14
+ document.xpath('//xenc:EncryptedKey', NAMESPACES).collect { |n| EncryptedKey.new(n) }
15
+ end
16
+
17
+ def decrypt(key)
18
+ encrypted_keys.each do |encrypted_key|
19
+ encrypted_data = encrypted_key.encrypted_data
20
+
21
+ data_key = encrypted_key.decrypt(key)
22
+ decrypted_data = encrypted_data.decrypt(data_key)
23
+ encrypted_data.node.replace(decrypted_data)
24
+ end
25
+ @document.to_xml
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,53 @@
1
+ module Xmlenc
2
+ class EncryptedKey
3
+ ALGORITHMS = {
4
+ 'http://www.w3.org/2001/04/xmlenc#rsa-1_5' => Algorithms::Rsa15,
5
+ 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' => Algorithms::RsaOaepMgf1p
6
+ }
7
+
8
+ def initialize(node)
9
+ @node = node
10
+ end
11
+
12
+ def document
13
+ @node.document
14
+ end
15
+
16
+ def encryption_method
17
+ at_xpath('./xenc:EncryptionMethod')
18
+ end
19
+
20
+ def encrypted_data
21
+ EncryptedData.new(referenced_node)
22
+ end
23
+
24
+ def cipher_value
25
+ at_xpath('./xenc:CipherData/xenc:CipherValue').content.gsub(/[\n\s]/, '')
26
+ end
27
+
28
+ def decrypt(key)
29
+ decryptor = algorithm.new(key)
30
+ decryptor.decrypt(Base64.decode64(cipher_value), node: encryption_method)
31
+ end
32
+
33
+ private
34
+
35
+ def referenced_node
36
+ document.at_xpath("//xenc:EncryptedData[@Id='#{reference_uri}']", NAMESPACES)
37
+ end
38
+
39
+ def reference_uri
40
+ at_xpath('./xenc:ReferenceList/xenc:DataReference')['URI'][1..-1]
41
+ end
42
+
43
+ def at_xpath(xpath)
44
+ @node.at_xpath(xpath, NAMESPACES)
45
+ end
46
+
47
+ def algorithm
48
+ algorithm = encryption_method['Algorithm']
49
+ ALGORITHMS[algorithm] ||
50
+ raise(UnsupportedError.new("Unsupported encryption method #{algorithm}"))
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,3 @@
1
+ module Xmlenc
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,61 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <PaymentInfo xmlns="http://example.org/paymentv2">
3
+ <Name>John Smith</Name>
4
+ <EncryptedData Id="ED" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#">
5
+ <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
6
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
7
+ <EncryptedKey Id="EK" xmlns="http://www.w3.org/2001/04/xmlenc#">
8
+ <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
9
+ <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
10
+ <ds:KeyName>my-rsa-key</ds:KeyName>
11
+ <ds:X509Data>
12
+ <ds:X509Certificate>
13
+ MIIDzTCCArWgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBljELMAkGA1UEBhMCVVMx
14
+ CzAJBgNVBAgTAk5ZMRIwEAYDVQQHEwlNYW5oYXR0YW4xFTATBgNVBAoTDExhdmEg
15
+ U3VwcmVtZTEUMBIGA1UECxMLSGVhZCBPZmZpY2UxFDASBgNVBAMTC1JTQSBUZXN0
16
+ IENBMSMwIQYJKoZIhvcNAQkBFhR0ZWNoQGxhdmFzdXByZW1lLm9yZzAeFw0wMjAx
17
+ MzExNjI5NDNaFw00MzAyMjUxNjI5NDNaMIGWMQswCQYDVQQGEwJVUzELMAkGA1UE
18
+ CBMCTlkxEjAQBgNVBAcTCU1hbmhhdHRhbjEVMBMGA1UEChMMTGF2YSBTdXByZW1l
19
+ MRQwEgYDVQQLEwtIZWFkIE9mZmljZTEUMBIGA1UEAxMLUlNBIFRlc3QgQ0ExIzAh
20
+ BgkqhkiG9w0BCQEWFHRlY2hAbGF2YXN1cHJlbWUub3JnMIIBIjANBgkqhkiG9w0B
21
+ AQEFAAOCAQ8AMIIBCgKCAQEAgj3TOyUtgg99oEfsm8h9JTZBxUkzYkXVUOHxIwnk
22
+ Fwp4y9ZnrGja/j+kpRyKvYP5CkNdq0e58/r7GLXj45iqd03XjsFNTdjy4OIOgf7J
23
+ xMG7z+hEB1LT2swTs10GILFWPByRl3/BEsnekLZdoqNoJrvnttVkxgu3x80Ji3/A
24
+ ZD8Ub/kBGOSPyu6pn3OdnMTc5q4r1qUe985lQzCZvCMw6AoGeCyJodNu2MbveNeH
25
+ +YPjRgLCQfzvOFRq+9qMtE8XfUJZdNhPZhgdsOGf8uJauTcIHbAyw7BhxPy6RikW
26
+ W5yiWUmBya+7t4y1TQJzham/0y0zU3TAA7b/rDrU7xmNPwIDAQABoyQwIjAPBgNV
27
+ HRMBAf8EBTADAQH/MA8GA1UdDwEB/wQFAwMHBgAwDQYJKoZIhvcNAQEEBQADggEB
28
+ ADELWZjFLPjSjGeOaeUwH/mEOP+l/nTtxe07IWAQL4kvb4wsiUsM1EkPptcBQsym
29
+ OYgFhf3Elqma84bbOyp85y/iQnjpqWWJ73TFXSWZamSIhYb4Gk+dQuwFI+zD3B2y
30
+ WwqghaAHDzxtzROLUBjo+97Y6ng6V5zjmtdGOFwNXwWhf3Y+MjnErtBIKYao8NJO
31
+ p6di80w82+s6Ot+CLVvVobLhxS/y8yWplATRiQnI5ij/WTLML+tiU5aes0c9abaf
32
+ O7i9j1iTuZsDT3f96ia0RSLsXSGij737QKc3ZM8lSxBWfepWYO+G+IRgr1q9IUDa
33
+ kKO/vB9Ay64Rt88XbLnnGns=
34
+ </ds:X509Certificate>
35
+ </ds:X509Data>
36
+ </ds:KeyInfo>
37
+ <CipherData>
38
+ <CipherValue>
39
+ cCxxYh3xGBTqlXbhmKxWzNMlHeE28E7vPrMyM5V4T+t1Iy2csj1BoQ7cqBjEhqEy
40
+ Eot4WNRYsY7P44mWBKurj2mdWQWgoxHvtITP9AR3JTMxUo3TF5ltW76DLDsEvWlE
41
+ uZKam0PYj6lYPKd4npUULeZyR/rDRrth/wFIBD8vbQlUsBHapNT9MbQfSKZemOuT
42
+ UJL9PNgsosySpKrX564oQw398XsxfTFxi4hqbdqzA/CLL418X01hUjIHdyv6XnA2
43
+ 98Bmfv9WMPpX05udR4raDv5X8NWxjH00hAhasM3qumxoyCT6mAGfqvE23I+OXtrN
44
+ lUvE9mMjANw4zweCHsOcfw==
45
+ </CipherValue>
46
+ </CipherData>
47
+ <ReferenceList>
48
+ <DataReference URI="#ED"/>
49
+ </ReferenceList>
50
+ </EncryptedKey>
51
+ </ds:KeyInfo>
52
+ <CipherData>
53
+ <CipherValue>
54
+ u2vogkwlvFqeknJ0lYTBZkWS/eX8LR1fDPFMfyK1/UY0EyZfHvbONfDHcC/HLv/f
55
+ aAOOO2Y0GqsknP0LYT1OznkiJrzx134cmJCgbyrYXd3Mp21Pq3rs66JJ34Qt3/+I
56
+ EyJBUSMT8TdT3fBD44BtOqH2op/hy2g3hQPFZul4GiHBEnNJL/4nU1yad3bMvtAB
57
+ mzhx80lJvPGLcruj5V77WMvkvZfoeEqMq4qPWK02ZURsJsq0iZcJDi39NB7OCiON
58
+ </CipherValue>
59
+ </CipherData>
60
+ </EncryptedData>
61
+ </PaymentInfo>
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEogIBAAKCAQEAgj3TOyUtgg99oEfsm8h9JTZBxUkzYkXVUOHxIwnkFwp4y9Zn
3
+ rGja/j+kpRyKvYP5CkNdq0e58/r7GLXj45iqd03XjsFNTdjy4OIOgf7JxMG7z+hE
4
+ B1LT2swTs10GILFWPByRl3/BEsnekLZdoqNoJrvnttVkxgu3x80Ji3/AZD8Ub/kB
5
+ GOSPyu6pn3OdnMTc5q4r1qUe985lQzCZvCMw6AoGeCyJodNu2MbveNeH+YPjRgLC
6
+ QfzvOFRq+9qMtE8XfUJZdNhPZhgdsOGf8uJauTcIHbAyw7BhxPy6RikWW5yiWUmB
7
+ ya+7t4y1TQJzham/0y0zU3TAA7b/rDrU7xmNPwIDAQABAoIBAFK+PIiC4hqTBNjj
8
+ WOrPwNH3WmmgS8jPXOp54NzF1+bbfErj+BGMvDRy8oMDUxF72qgujD/Y3canWQcl
9
+ 55Yc04/gIGZNYHNotUUx2M21tTIPcuZvRWjxsi57ILj/DHmQsJyX+dcqDtuE7KU7
10
+ dtlwvyZ8koWRpOg9YZDKLpo1m2ET0RjyNEm9fvt6m3ZwSawA9Yu0xSVvVIukNIl7
11
+ eimQzBYeGQwGwhMgMoybQWjwIOpnbvcRfT/iAh9n/AyXcjtOMGwWhifjel+U1XMM
12
+ hrcL3mA5xb+gGQpZ7TToTfmOEJeVCh9BRKpgniH4JVClhiTOeN4VTLZYg/BGmGTj
13
+ rEZKX4ECgYEAigDXtsEns9+QVsQKYolI/GE0Edkd1OkyGw11N3YIMNNzOotcDKoU
14
+ 0/Jt1hI7NaWRgi9/LyphmEM/dBaNnrNW6GPIETSjUQ9FuK2LywkNUiM2D+UFsLlq
15
+ EJ4S50/7kdXOC3t9rm9tiIPyqwJKNxRmyAAKfiRbYiEtqqR5zdGXcBECgYEA8ZoG
16
+ xTcXI7pqmkWcI87siHhth1jFCGv3EMwAeIy4tk4HBkxjZoBy/hU2mxviYPhuFEPj
17
+ JTKEbiQRebVLwaTJxs543deGQ1shdVHT1005wyGyhuIVXYC56Xhu+8B2y32650/X
18
+ wRTSUXxP/eQ+Qb2MeDPZ0XgpHhU74Za4F812eE8CgYABNwqvKDoyQjiiGu3Aelbz
19
+ KePseE3j7v2q8U5j450k2Oe9zzZLQkAWsZ638McmrMOAMuzavHPJhGYNnpk2mXud
20
+ Zit/w0fg0dKaUqTVb8n3PCogr7KCIM/HP60I7lJXsVs0DK1JmN+NASRkzwtaOsrA
21
+ 3gc5nxZS4dnmE7ai0kKUEQKBgEfA/xHDctPhoZd/5QedhRJi8eSosJv3tMEAVYN4
22
+ B8PdGKj+NudSbtSXaEhY17sFDWxnXSbHAh3UCHylI4K3dlXdLHh2ciG/BwjY7Jmd
23
+ DfKuJ1939fB3Mr/sTMnoN1/oT4IzbFij3nLlALze9L6BlR5+B8r2bP/KPqaZJMOs
24
+ +epxAoGAdV6yhdRcUrSBg6e8Q2f1or7LeYzi6xWjf1RRjqPOgf6VB/xiMmF6RnZK
25
+ uRUzK9ieRnAhtDFJTS1nPbfVLPSsASzxAaGQGdZ3AsHD4jp03jCyKtBaPKdDzeVr
26
+ rrIYPcyZ4OBeoFWUvzlDEtEcqJc3ONwpNWal7nhKEbb/AjqFmpg=
27
+ -----END RSA PRIVATE KEY-----