xml-kit 0.1.0 → 0.1.1

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