xml-kit 0.1.0 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3a289752cbc49e2c74959f38b5b104ecbd02b4b8
4
- data.tar.gz: 1475f47273a9d9483645c629517b3bf087f686c9
3
+ metadata.gz: 49fff640520abeb3b244774d156af6e18ee85928
4
+ data.tar.gz: 92f26fb96366f6a9b8991fa4806f40edeff2d11a
5
5
  SHA512:
6
- metadata.gz: 0576d38d7792ee436cfe335809516219730d817d5fc0a0d605affc897861e248ea07cc8ffe7e5312b77f2f1a85dd87b034a6d06e05a2b4c4f82afd8a655d8e0c
7
- data.tar.gz: f7c764c6ff671e16b4992d0bea126819238ae766368d5c8b6215ca2cecbaa30890a5fad7ee2ba802be74de4f29bcfe63476cc6c0520a390c4c36bcf205a6e269
6
+ metadata.gz: 000cccaa63a068e24acaa203dfeb80bcd3704f214be8812bb84feacb3d584e920eef7bd1a17d317e6049055a991f9d3c589cf505b4cf9574969a2ed179e19ad7
7
+ data.tar.gz: 516d4b2f71e2e9e6bd70d09be1f217234d0d10f5649a73ee97ae5100b32b34af24f42e52705465de3047a0d565c9a61f83c117fb1dfe0dc4149e1ff47413c10c
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Xml::Kit
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/xml/kit`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ Xml::Kit is a toolkit for working with XML. It supports adding [XML
4
+ Digital Signatures](https://www.w3.org/TR/xmldsig-core/)
5
+ and [XML Encryption](https://www.w3.org/TR/2002/REC-xmlenc-core-20021210/Overview.html).
6
6
 
7
7
  ## Installation
8
8
 
@@ -22,7 +22,97 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
25
+ ```builder
26
+ # ./templates/item.builder
27
+ xml.instruct!
28
+ xml.Item ID: id do
29
+ signature_for reference_id: id, xml: xml
30
+ xml.Encrypted do
31
+ encryption_for xml: xml do |encrypted_xml|
32
+ encrypted_xml.EncryptMe do
33
+ encrypted_xml.Secret "secret"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ ```
39
+
40
+ ```ruby
41
+ require 'xml/kit'
42
+
43
+ class Item
44
+ include ::Xml::Kit::Templatable
45
+
46
+ def initialize
47
+ @id = ::Xml::Kit::Id.generate
48
+ @signing_key_pair = ::Xml::Kit::KeyPair.generate(use: :signing)
49
+ @embed_signature = true
50
+ @encrypt = true
51
+ @encryption_certificate = ::Xml::Kit::KeyPair.generate(use: :encryption).certificate
52
+ end
53
+
54
+ def template_path
55
+ current_path = File.expand_path(File.dirname(__FILE__))
56
+ File.join(current_path, "./templates/item.builder")
57
+ end
58
+ end
59
+
60
+ puts Item.new.to_xml
61
+ ```
62
+
63
+ This will produce something like the following:
64
+
65
+ ```xml
66
+ <?xml version="1.0" encoding="UTF-8"?>
67
+ <Item ID="_de3f6209-f842-400f-b1f7-85159aa90299">
68
+ <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
69
+ <SignedInfo>
70
+ <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
71
+ <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
72
+ <Reference URI="#_de3f6209-f842-400f-b1f7-85159aa90299">
73
+ <Transforms>
74
+ <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
75
+ <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
76
+ </Transforms>
77
+ <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
78
+ <DigestValue>3cH13yM8oR0sgWbhAx0mo536KMJDkVBynbPo7ehwJPE=</DigestValue>
79
+ </Reference>
80
+ </SignedInfo>
81
+ <SignatureValue>ZCSx4dad704jz0Z6rCMsnOs/oyVH3YBeEF9wtk2UFmWBW+VfhoBKw7N50GnzmAGCHyI6zajRPdff5i6UMDz3fOzh7rlROnqW0TXoG77xPiIfqJswCKE/4LzzBLrEHVbdUz90U8n0M1Ahbesrt+pbf/NkJghpvDhJW+w6oho7dyU6k57C5D//kTaSb7DvKte3a7/o8xWvPRztQhYekK+RyWjK9k/lU4WEXk5rGbx+QrD9rgIXBQOdcSjOtUosZJADz7uFod6AWRak246U62Xahz8JxE/1N22LhZY9whvB7s+c76f1Uv44NtF87D0P8UXs0TVx2jsnhEwLsT7DPQ6jDg==</SignatureValue>
82
+ <KeyInfo>
83
+ <X509Data>
84
+ <X509Certificate>MIIDQTCCAimgAwIBAgIBADANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQGEwJDQTEQMA4GA1UECAwHQWxiZXJ0YTEQMA4GA1UEBwwHQ2FsZ2FyeTEPMA0GA1UECgwGWG1sS2l0MQ8wDQYDVQQLDAZYbWxLaXQxDzANBgNVBAMMBlhtbEtpdDAeFw0xNzEyMzAxOTM1MjZaFw0xODAxMjkwNzAwMDBaMGQxCzAJBgNVBAYTAkNBMRAwDgYDVQQIDAdBbGJlcnRhMRAwDgYDVQQHDAdDYWxnYXJ5MQ8wDQYDVQQKDAZYbWxLaXQxDzANBgNVBAsMBlhtbEtpdDEPMA0GA1UEAwwGWG1sS2l0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz8yvaY1zvqiSTpDc0vFgS00N0R05ytanViNy0YrcAvLH2njvLOYi8e5lWAjCUzoWTe6FMJQySIHuzr9NvZztlQBp5tydmxDsOFQ3DrBhiqtyafdCd5s8OQz1CekavgToTOm5VdZEWLD7HSCFvHXeuiS/zwEh4yYpJBAERtsSaYxT7L1wNggxc6F6UEfF1vwrGxMNH/OUi4okeS773esXeRlP5fHyMUvVC70KHauSYt/kjNR8/WuZBOY8/kFv3XiErf0PNSAYhyGHozabv8hJ2Bho0+HR12P6Xv+qKXFlDnMeAOHy23eShuUpCEBaEPAG4o8w4g/lrn0nJ+e9XrYaNQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCWybi6buMD75KBCcyd5aRtSKavYoDaZlzuohKh4z1HEzHS/fbpbxVQOrfXtuawZjNxcn62LFIe/w68EImzYkAss8LKojRcaKnIeF1/3Pzo6qfnmFpaecfYvX3ZTtw9JPOd4chy2X2WFAUMRscjSvjNvTBzFOXg60F0UMDnWOWMbc5Di/aZD8r2s/RDE3QxcUou8QhBMc2nYw77mQsXBnWmBeUA2aGP
85
+ 8OG/fOgtBKkZnNF8gx7wuodbYSmKAfFGx8+CGtnkwNr4/hXgd1qg5KmsAx+9VYozCjGKSkVUIqC5khy6N+1Pb5jMKrMQ+QU9zGhylWoJ2jiK65hzUUVUESIB</X509Certificate>
86
+ </X509Data>
87
+ </KeyInfo>
88
+ </Signature>
89
+ <Encrypted>
90
+ <EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#">
91
+ <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
92
+ <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
93
+ <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
94
+ <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
95
+ <CipherData>
96
+ <CipherValue>rBJwm+gmL6eUHBZDXs2swIL3DiZ+MfmBPpM52eF0RWFtZv/gutY02KlsFLlm
97
+ jc+DO7X5p9l1Br67FjGJrTdfSSqHf35cS1cioyaKLtgniSrD7Hf9d8qIuWt5
98
+ 6dLWjmCi21cePMJHhNiFe5yRjFHNp5LZ9dX5hvNXjbn0+p90fj8zlO2TWZv9
99
+ atooON3BaYGCezZlmG0bWyEmloqKHiGjqaKtkdeSKJDzoo/AvubDEgz56rin
100
+ Cpw26rEOg8BBd/KNfSXyDUifOOzXmn6myq+8+W/FFQ+6y+5SgtsbONRCqe2c
101
+ KkNi3fYhilwLxWCaXFjONimEOkeG03yR5QnWhzEOpw==
102
+ </CipherValue>
103
+ </CipherData>
104
+ </EncryptedKey>
105
+ </KeyInfo>
106
+ <CipherData>
107
+ <CipherValue>45rM0phzM/S/vpiq8Ev+uQZ6WL5qZ8av0UDVzWAlHn6Qr7zWYjHea+NF94lK
108
+ pvmTPWQDEnfv2UW8l0VdCLc+51zHjluRE/xJh31Gk3rVuRJtLioSge/N9UM4
109
+ 5g901rE9
110
+ </CipherValue>
111
+ </CipherData>
112
+ </EncryptedData>
113
+ </Encrypted>
114
+ </Item>
115
+ ```
26
116
 
27
117
  ## Development
28
118
 
data/lib/xml/kit.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "active_model"
2
2
  require "active_support/core_ext/numeric/time"
3
+ require "active_support/deprecation"
3
4
  require "base64"
4
5
  require "builder"
5
6
  require "logger"
@@ -10,16 +11,16 @@ require "xmldsig"
10
11
 
11
12
  require "xml/kit/namespaces"
12
13
 
13
- require "xml/kit/builders/encryption"
14
- require "xml/kit/builders/signature"
15
14
  require "xml/kit/certificate"
16
15
  require "xml/kit/crypto"
17
16
  require "xml/kit/decryption"
18
17
  require "xml/kit/document"
18
+ require "xml/kit/encryption"
19
19
  require "xml/kit/fingerprint"
20
20
  require "xml/kit/id"
21
21
  require "xml/kit/key_pair"
22
22
  require "xml/kit/self_signed_certificate"
23
+ require "xml/kit/signature"
23
24
  require "xml/kit/signatures"
24
25
  require "xml/kit/templatable"
25
26
  require "xml/kit/template"
@@ -35,6 +36,11 @@ module Xml
35
36
  def logger=(logger)
36
37
  @logger = logger
37
38
  end
39
+
40
+ def deprecate(message)
41
+ @deprecation ||= ActiveSupport::Deprecation.new('1.0.0', 'xml-kit')
42
+ @deprecation.deprecation_warning(message)
43
+ end
38
44
  end
39
45
  end
40
46
  end
@@ -1,16 +1,16 @@
1
1
  require 'xml/kit/crypto/oaep_cipher'
2
2
  require 'xml/kit/crypto/rsa_cipher'
3
- require 'xml/kit/crypto/simple_cipher'
3
+ require 'xml/kit/crypto/symmetric_cipher'
4
4
  require 'xml/kit/crypto/unknown_cipher'
5
5
 
6
6
  module Xml
7
7
  module Kit
8
8
  module Crypto
9
- DECRYPTORS = [ SimpleCipher, RsaCipher, OaepCipher, UnknownCipher ]
9
+ CIPHERS = [ SymmetricCipher, RsaCipher, OaepCipher, UnknownCipher ]
10
10
 
11
11
  # @!visibility private
12
- def self.decryptor_for(algorithm, key)
13
- DECRYPTORS.find { |x| x.matches?(algorithm) }.new(algorithm, key)
12
+ def self.cipher_for(algorithm, key)
13
+ CIPHERS.find { |x| x.matches?(algorithm) }.new(algorithm, key)
14
14
  end
15
15
  end
16
16
  end
@@ -13,8 +13,18 @@ module Xml
13
13
  ALGORITHMS[algorithm]
14
14
  end
15
15
 
16
+ def encrypt(plain_text)
17
+ @key.public_encrypt(plain_text, padding)
18
+ end
19
+
16
20
  def decrypt(cipher_text)
17
- @key.private_decrypt(cipher_text, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
21
+ @key.private_decrypt(cipher_text, padding)
22
+ end
23
+
24
+ private
25
+
26
+ def padding
27
+ OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING
18
28
  end
19
29
  end
20
30
  end
@@ -2,16 +2,18 @@ module Xml
2
2
  module Kit
3
3
  module Crypto
4
4
  class RsaCipher
5
- ALGORITHMS = {
6
- 'http://www.w3.org/2001/04/xmlenc#rsa-1_5' => true,
7
- }
5
+ ALGORITHM = "#{::Xml::Kit::Namespaces::XMLENC}rsa-1_5"
8
6
 
9
7
  def initialize(algorithm, key)
10
8
  @key = key
11
9
  end
12
10
 
13
11
  def self.matches?(algorithm)
14
- ALGORITHMS[algorithm]
12
+ ALGORITHM == algorithm
13
+ end
14
+
15
+ def encrypt(plain_text)
16
+ @key.public_encrypt(plain_text)
15
17
  end
16
18
 
17
19
  def decrypt(cipher_text)
@@ -0,0 +1,48 @@
1
+ module Xml
2
+ module Kit
3
+ module Crypto
4
+ class SymmetricCipher
5
+ DEFAULT_ALGORITHM="#{::Xml::Kit::Namespaces::XMLENC}aes256-cbc"
6
+ ALGORITHMS = {
7
+ "#{::Xml::Kit::Namespaces::XMLENC}tripledes-cbc" => "DES-EDE3-CBC",
8
+ "#{::Xml::Kit::Namespaces::XMLENC}aes128-cbc" => "AES-128-CBC",
9
+ "#{::Xml::Kit::Namespaces::XMLENC}aes192-cbc" => "AES-192-CBC",
10
+ "#{::Xml::Kit::Namespaces::XMLENC}aes256-cbc" => "AES-256-CBC",
11
+ }
12
+
13
+ attr_reader :key
14
+
15
+ def initialize(algorithm, key = nil)
16
+ @algorithm = algorithm
17
+ @key = key || cipher.random_key
18
+ end
19
+
20
+ def self.matches?(algorithm)
21
+ ALGORITHMS[algorithm]
22
+ end
23
+
24
+ def encrypt(plain_text)
25
+ cipher.encrypt
26
+ cipher.key = @key
27
+ cipher.random_iv + cipher.update(plain_text) + cipher.final
28
+ end
29
+
30
+ def decrypt(cipher_text)
31
+ cipher.decrypt
32
+ iv = cipher_text[0..cipher.iv_len-1]
33
+ data = cipher_text[cipher.iv_len..-1]
34
+ #cipher.padding = 0
35
+ cipher.key = @key
36
+ cipher.iv = iv
37
+ cipher.update(data) + cipher.final
38
+ end
39
+
40
+ private
41
+
42
+ def cipher
43
+ @cipher ||= OpenSSL::Cipher.new(ALGORITHMS[@algorithm])
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -13,7 +13,22 @@ module Xml
13
13
  #
14
14
  # @param data [Hash] the XML document converted to a [Hash] using Hash.from_xml.
15
15
  def decrypt(data)
16
- encrypted_data = data['EncryptedData']
16
+ ::Xml::Kit.deprecate("decrypt is deprecated. Use decrypt_xml or decrypt_hash instead.")
17
+ decrypt_hash(data)
18
+ end
19
+
20
+ # Decrypts an EncryptedData section of an XML document.
21
+ #
22
+ # @param raw_xml [String] the XML document as a string.
23
+ def decrypt_xml(raw_xml)
24
+ decrypt_hash(Hash.from_xml(raw_xml))
25
+ end
26
+
27
+ # Decrypts an EncryptedData section of an XML document.
28
+ #
29
+ # @param data [Hash] the XML document converted to a [Hash] using Hash.from_xml.
30
+ def decrypt_hash(hash)
31
+ encrypted_data = hash['EncryptedData']
17
32
  symmetric_key = symmetric_key_from(encrypted_data)
18
33
  cipher_text = Base64.decode64(encrypted_data["CipherData"]["CipherValue"])
19
34
  to_plaintext(cipher_text, symmetric_key, encrypted_data["EncryptionMethod"]['Algorithm'])
@@ -37,7 +52,7 @@ module Xml
37
52
  end
38
53
 
39
54
  def to_plaintext(cipher_text, symmetric_key, algorithm)
40
- Crypto.decryptor_for(algorithm, symmetric_key).decrypt(cipher_text)
55
+ Crypto.cipher_for(algorithm, symmetric_key).decrypt(cipher_text)
41
56
  end
42
57
  end
43
58
  end
@@ -0,0 +1,35 @@
1
+ module Xml
2
+ module Kit
3
+ class Encryption
4
+ attr_reader :asymmetric_algorithm
5
+ attr_reader :asymmetric_cipher_value
6
+ attr_reader :symmetric_algorithm
7
+ attr_reader :symmetric_cipher_value
8
+
9
+ def initialize(
10
+ raw_xml,
11
+ public_key,
12
+ symmetric_algorithm: ::Xml::Kit::Crypto::SymmetricCipher::DEFAULT_ALGORITHM,
13
+ asymmetric_algorithm: ::Xml::Kit::Crypto::RsaCipher::ALGORITHM
14
+ )
15
+ @symmetric_algorithm = symmetric_algorithm
16
+ @symmetric_cipher_value = Base64.encode64(symmetric_cipher.encrypt(raw_xml))
17
+
18
+ @asymmetric_algorithm = asymmetric_algorithm
19
+ @asymmetric_cipher_value = Base64.encode64(public_key.public_encrypt(symmetric_cipher.key))
20
+ end
21
+
22
+ def to_xml(xml: ::Builder::XmlMarkup.new)
23
+ ::Xml::Kit::Template.new(self).to_xml(xml: xml)
24
+ end
25
+
26
+ private
27
+
28
+ def symmetric_cipher
29
+ @symmetric_cipher ||= ::Xml::Kit::Crypto::SymmetricCipher.new(
30
+ symmetric_algorithm
31
+ )
32
+ end
33
+ end
34
+ end
35
+ end
data/lib/xml/kit/id.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Xml
2
2
  module Kit
3
3
  # This class is used primary for generating ID.
4
- #https://www.w3.org/2001/XMLSchema.xsd
4
+ # https://www.w3.org/2001/XMLSchema.xsd
5
5
  class Id
6
6
  # Generate an ID that conforms to the XML Schema.
7
7
  # https://www.w3.org/2001/XMLSchema.xsd
@@ -16,12 +16,18 @@ module Xml
16
16
  @use == use
17
17
  end
18
18
 
19
+ def public_key
20
+ certificate.public_key
21
+ end
22
+
19
23
  # Returns a generated self signed certificate with private key.
20
24
  #
21
25
  # @param use [Symbol] Can be either `:signing` or `:encryption`.
22
26
  # @param passphrase [String] the passphrase to use to encrypt the private key.
23
- def self.generate(use:, passphrase: SecureRandom.uuid)
24
- certificate, private_key = ::Xml::Kit::SelfSignedCertificate.new(passphrase).create
27
+ # @param algorithm [String] the symmetric algorithm to use for encrypting the private key.
28
+ def self.generate(use:, passphrase: SecureRandom.uuid, algorithm: ::Xml::Kit::Crypto::SymmetricCipher::DEFAULT_ALGORITHM)
29
+ algorithm = ::Xml::Kit::Crypto::SymmetricCipher::ALGORITHMS[algorithm]
30
+ certificate, private_key = ::Xml::Kit::SelfSignedCertificate.new(passphrase).create(algorithm)
25
31
  new(certificate, private_key, passphrase, use)
26
32
  end
27
33
  end
@@ -1,6 +1,7 @@
1
1
  module Xml
2
2
  module Kit
3
3
  module Namespaces
4
+ CANONICALIZATION = "http://www.w3.org/2001/10/xml-exc-c14n#"
4
5
  ENVELOPED_SIG = "http://www.w3.org/2000/09/xmldsig#enveloped-signature"
5
6
  RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
6
7
  RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
@@ -7,20 +7,19 @@ module Xml
7
7
  @passphrase = passphrase
8
8
  end
9
9
 
10
- def create
10
+ def create(algorithm = 'AES-256-CBC')
11
11
  rsa_key = OpenSSL::PKey::RSA.new(2048)
12
- public_key = rsa_key.public_key
13
12
  certificate = OpenSSL::X509::Certificate.new
14
13
  certificate.subject = certificate.issuer = OpenSSL::X509::Name.parse(SUBJECT)
15
14
  certificate.not_before = Time.now.to_i
16
15
  certificate.not_after = (Date.today + 30).to_time.to_i
17
- certificate.public_key = public_key
16
+ certificate.public_key = rsa_key.public_key
18
17
  certificate.serial = 0x0
19
18
  certificate.version = 2
20
19
  certificate.sign(rsa_key, OpenSSL::Digest::SHA256.new)
21
20
  [
22
21
  certificate.to_pem,
23
- rsa_key.to_pem(OpenSSL::Cipher.new('AES-256-CBC'), @passphrase)
22
+ rsa_key.to_pem(OpenSSL::Cipher.new(algorithm), @passphrase)
24
23
  ]
25
24
  end
26
25
  end
@@ -0,0 +1,36 @@
1
+ module Xml
2
+ module Kit
3
+ class Signature
4
+ SIGNATURE_METHODS = {
5
+ SHA1: "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
6
+ SHA224: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha224",
7
+ SHA256: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
8
+ SHA384: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
9
+ SHA512: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
10
+ }.freeze
11
+ DIGEST_METHODS = {
12
+ SHA1: "http://www.w3.org/2000/09/xmldsig#SHA1",
13
+ SHA224: "http://www.w3.org/2001/04/xmldsig-more#sha224",
14
+ SHA256: "http://www.w3.org/2001/04/xmlenc#sha256",
15
+ SHA384: "http://www.w3.org/2001/04/xmldsig-more#sha384",
16
+ SHA512: "http://www.w3.org/2001/04/xmlenc#sha512",
17
+ }.freeze
18
+
19
+ attr_reader :certificate
20
+ attr_reader :digest_method
21
+ attr_reader :reference_id
22
+ attr_reader :signature_method
23
+
24
+ def initialize(reference_id, signature_method: :SH256, digest_method: :SHA256, certificate:)
25
+ @certificate = certificate
26
+ @digest_method = DIGEST_METHODS[digest_method]
27
+ @reference_id = reference_id
28
+ @signature_method = SIGNATURE_METHODS[signature_method]
29
+ end
30
+
31
+ def to_xml(xml: ::Builder::XmlMarkup.new)
32
+ ::Xml::Kit::Template.new(self).to_xml(xml: xml)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -20,7 +20,7 @@ module Xml
20
20
  def build(reference_id)
21
21
  return nil if key_pair.nil?
22
22
 
23
- ::Xml::Kit::Builders::Signature.new(
23
+ ::Xml::Kit::Signature.new(
24
24
  reference_id,
25
25
  certificate: key_pair.certificate,
26
26
  signature_method: signature_method,
@@ -24,12 +24,10 @@ module Xml
24
24
  if encrypt?
25
25
  temp = ::Builder::XmlMarkup.new
26
26
  yield temp
27
- signed_xml = signatures.complete(temp.target!)
28
- xml_encryption = ::Xml::Kit::Builders::Encryption.new(
29
- signed_xml,
27
+ ::Xml::Kit::Encryption.new(
28
+ signatures.complete(temp.target!),
30
29
  encryption_certificate.public_key
31
- )
32
- render(xml_encryption, xml: xml)
30
+ ).to_xml(xml: xml)
33
31
  else
34
32
  yield xml
35
33
  end
@@ -41,7 +39,7 @@ module Xml
41
39
 
42
40
  def signature_for(reference_id:, xml:)
43
41
  return unless sign?
44
- render(signatures.build(reference_id), xml: xml)
42
+ signatures.build(reference_id).to_xml(xml: xml)
45
43
  end
46
44
 
47
45
  # Allows you to specify which key pair to use for generating an XML digital signature.
@@ -21,7 +21,7 @@ module Xml
21
21
 
22
22
  root_path = File.expand_path(File.dirname(__FILE__))
23
23
  template_name = "#{target.class.name.split("::").last.underscore}.builder"
24
- File.join(root_path, "builders/templates/", template_name)
24
+ File.join(root_path, "templates/", template_name)
25
25
  end
26
26
 
27
27
  def template
@@ -0,0 +1,14 @@
1
+ xml.EncryptedData xmlns: ::Xml::Kit::Namespaces::XMLENC do
2
+ xml.EncryptionMethod Algorithm: symmetric_algorithm
3
+ xml.KeyInfo xmlns: ::Xml::Kit::Namespaces::XMLDSIG do
4
+ xml.EncryptedKey xmlns: ::Xml::Kit::Namespaces::XMLENC do
5
+ xml.EncryptionMethod Algorithm: asymmetric_algorithm
6
+ xml.CipherData do
7
+ xml.CipherValue asymmetric_cipher_value
8
+ end
9
+ end
10
+ end
11
+ xml.CipherData do
12
+ xml.CipherValue symmetric_cipher_value
13
+ end
14
+ end
@@ -1,11 +1,11 @@
1
1
  xml.Signature "xmlns" => ::Xml::Kit::Namespaces::XMLDSIG do
2
2
  xml.SignedInfo do
3
- xml.CanonicalizationMethod Algorithm: "http://www.w3.org/2001/10/xml-exc-c14n#"
3
+ xml.CanonicalizationMethod Algorithm: ::Xml::Kit::Namespaces::CANONICALIZATION
4
4
  xml.SignatureMethod Algorithm: signature_method
5
5
  xml.Reference URI: "##{reference_id}" do
6
6
  xml.Transforms do
7
- xml.Transform Algorithm: "http://www.w3.org/2000/09/xmldsig#enveloped-signature"
8
- xml.Transform Algorithm: "http://www.w3.org/2001/10/xml-exc-c14n#"
7
+ xml.Transform Algorithm: "#{::Xml::Kit::Namespaces::XMLDSIG}enveloped-signature"
8
+ xml.Transform Algorithm: ::Xml::Kit::Namespaces::CANONICALIZATION
9
9
  end
10
10
  xml.DigestMethod Algorithm: digest_method
11
11
  xml.DigestValue ""
@@ -1,5 +1,5 @@
1
1
  module Xml
2
2
  module Kit
3
- VERSION = "0.1.0"
3
+ VERSION = "0.1.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xml-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - mo khan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-28 00:00:00.000000000 Z
11
+ date: 2017-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -168,28 +168,28 @@ files:
168
168
  - bin/console
169
169
  - bin/setup
170
170
  - lib/xml/kit.rb
171
- - lib/xml/kit/builders/encryption.rb
172
- - lib/xml/kit/builders/signature.rb
173
- - lib/xml/kit/builders/templates/certificate.builder
174
- - lib/xml/kit/builders/templates/encryption.builder
175
- - lib/xml/kit/builders/templates/nil_class.builder
176
- - lib/xml/kit/builders/templates/signature.builder
177
171
  - lib/xml/kit/certificate.rb
178
172
  - lib/xml/kit/crypto.rb
179
173
  - lib/xml/kit/crypto/oaep_cipher.rb
180
174
  - lib/xml/kit/crypto/rsa_cipher.rb
181
- - lib/xml/kit/crypto/simple_cipher.rb
175
+ - lib/xml/kit/crypto/symmetric_cipher.rb
182
176
  - lib/xml/kit/crypto/unknown_cipher.rb
183
177
  - lib/xml/kit/decryption.rb
184
178
  - lib/xml/kit/document.rb
179
+ - lib/xml/kit/encryption.rb
185
180
  - lib/xml/kit/fingerprint.rb
186
181
  - lib/xml/kit/id.rb
187
182
  - lib/xml/kit/key_pair.rb
188
183
  - lib/xml/kit/namespaces.rb
189
184
  - lib/xml/kit/self_signed_certificate.rb
185
+ - lib/xml/kit/signature.rb
190
186
  - lib/xml/kit/signatures.rb
191
187
  - lib/xml/kit/templatable.rb
192
188
  - lib/xml/kit/template.rb
189
+ - lib/xml/kit/templates/certificate.builder
190
+ - lib/xml/kit/templates/encryption.builder
191
+ - lib/xml/kit/templates/nil_class.builder
192
+ - lib/xml/kit/templates/signature.builder
193
193
  - lib/xml/kit/version.rb
194
194
  - xml-kit.gemspec
195
195
  homepage: http://www.mokhan.ca
@@ -1,20 +0,0 @@
1
- module Xml
2
- module Kit
3
- module Builders
4
- class Encryption
5
- attr_reader :public_key
6
- attr_reader :key, :iv, :encrypted
7
-
8
- def initialize(raw_xml, public_key)
9
- @public_key = public_key
10
- cipher = OpenSSL::Cipher.new('AES-256-CBC')
11
- cipher.encrypt
12
- @key = cipher.random_key
13
- @iv = cipher.random_iv
14
- @encrypted = cipher.update(raw_xml) + cipher.final
15
- end
16
- end
17
- end
18
- end
19
- end
20
-
@@ -1,34 +0,0 @@
1
- module Xml
2
- module Kit
3
- module Builders
4
- class Signature
5
- SIGNATURE_METHODS = {
6
- SHA1: "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
7
- SHA224: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha224",
8
- SHA256: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
9
- SHA384: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
10
- SHA512: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
11
- }.freeze
12
- DIGEST_METHODS = {
13
- SHA1: "http://www.w3.org/2000/09/xmldsig#SHA1",
14
- SHA224: "http://www.w3.org/2001/04/xmldsig-more#sha224",
15
- SHA256: "http://www.w3.org/2001/04/xmlenc#sha256",
16
- SHA384: "http://www.w3.org/2001/04/xmldsig-more#sha384",
17
- SHA512: "http://www.w3.org/2001/04/xmlenc#sha512",
18
- }.freeze
19
-
20
- attr_reader :certificate
21
- attr_reader :digest_method
22
- attr_reader :reference_id
23
- attr_reader :signature_method
24
-
25
- def initialize(reference_id, signature_method: :SH256, digest_method: :SHA256, certificate:)
26
- @certificate = certificate
27
- @digest_method = DIGEST_METHODS[digest_method]
28
- @reference_id = reference_id
29
- @signature_method = SIGNATURE_METHODS[signature_method]
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,14 +0,0 @@
1
- xml.EncryptedData xmlns: ::Xml::Kit::Namespaces::XMLENC do
2
- xml.EncryptionMethod Algorithm: "http://www.w3.org/2001/04/xmlenc#aes256-cbc"
3
- xml.KeyInfo xmlns: ::Xml::Kit::Namespaces::XMLDSIG do
4
- xml.EncryptedKey xmlns: ::Xml::Kit::Namespaces::XMLENC do
5
- xml.EncryptionMethod Algorithm: "http://www.w3.org/2001/04/xmlenc#rsa-1_5"
6
- xml.CipherData do
7
- xml.CipherValue Base64.encode64(public_key.public_encrypt(key))
8
- end
9
- end
10
- end
11
- xml.CipherData do
12
- xml.CipherValue Base64.encode64(iv + encrypted)
13
- end
14
- end
@@ -1,34 +0,0 @@
1
- module Xml
2
- module Kit
3
- module Crypto
4
- class SimpleCipher
5
- ALGORITHMS = {
6
- 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc' => 'DES-EDE3-CBC',
7
- 'http://www.w3.org/2001/04/xmlenc#aes128-cbc' => 'AES-128-CBC',
8
- 'http://www.w3.org/2001/04/xmlenc#aes192-cbc' => 'AES-192-CBC',
9
- 'http://www.w3.org/2001/04/xmlenc#aes256-cbc' => 'AES-256-CBC',
10
- }
11
-
12
- def initialize(algorithm, private_key)
13
- @algorithm = algorithm
14
- @private_key = private_key
15
- end
16
-
17
- def self.matches?(algorithm)
18
- ALGORITHMS[algorithm]
19
- end
20
-
21
- def decrypt(cipher_text)
22
- cipher = OpenSSL::Cipher.new(ALGORITHMS[@algorithm])
23
- cipher.decrypt
24
- iv = cipher_text[0..cipher.iv_len-1]
25
- data = cipher_text[cipher.iv_len..-1]
26
- #cipher.padding = 0
27
- cipher.key = @private_key
28
- cipher.iv = iv
29
- cipher.update(data) + cipher.final
30
- end
31
- end
32
- end
33
- end
34
- end