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 +4 -4
- data/README.md +94 -4
- data/lib/xml/kit.rb +8 -2
- data/lib/xml/kit/crypto.rb +4 -4
- data/lib/xml/kit/crypto/oaep_cipher.rb +11 -1
- data/lib/xml/kit/crypto/rsa_cipher.rb +6 -4
- data/lib/xml/kit/crypto/symmetric_cipher.rb +48 -0
- data/lib/xml/kit/decryption.rb +17 -2
- data/lib/xml/kit/encryption.rb +35 -0
- data/lib/xml/kit/id.rb +1 -1
- data/lib/xml/kit/key_pair.rb +8 -2
- data/lib/xml/kit/namespaces.rb +1 -0
- data/lib/xml/kit/self_signed_certificate.rb +3 -4
- data/lib/xml/kit/signature.rb +36 -0
- data/lib/xml/kit/signatures.rb +1 -1
- data/lib/xml/kit/templatable.rb +4 -6
- data/lib/xml/kit/template.rb +1 -1
- data/lib/xml/kit/{builders/templates → templates}/certificate.builder +0 -0
- data/lib/xml/kit/templates/encryption.builder +14 -0
- data/lib/xml/kit/{builders/templates → templates}/nil_class.builder +0 -0
- data/lib/xml/kit/{builders/templates → templates}/signature.builder +3 -3
- data/lib/xml/kit/version.rb +1 -1
- metadata +9 -9
- data/lib/xml/kit/builders/encryption.rb +0 -20
- data/lib/xml/kit/builders/signature.rb +0 -34
- data/lib/xml/kit/builders/templates/encryption.builder +0 -14
- data/lib/xml/kit/crypto/simple_cipher.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49fff640520abeb3b244774d156af6e18ee85928
|
4
|
+
data.tar.gz: 92f26fb96366f6a9b8991fa4806f40edeff2d11a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 000cccaa63a068e24acaa203dfeb80bcd3704f214be8812bb84feacb3d584e920eef7bd1a17d317e6049055a991f9d3c589cf505b4cf9574969a2ed179e19ad7
|
7
|
+
data.tar.gz: 516d4b2f71e2e9e6bd70d09be1f217234d0d10f5649a73ee97ae5100b32b34af24f42e52705465de3047a0d565c9a61f83c117fb1dfe0dc4149e1ff47413c10c
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Xml::Kit
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
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
|
data/lib/xml/kit/crypto.rb
CHANGED
@@ -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/
|
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
|
-
|
9
|
+
CIPHERS = [ SymmetricCipher, RsaCipher, OaepCipher, UnknownCipher ]
|
10
10
|
|
11
11
|
# @!visibility private
|
12
|
-
def self.
|
13
|
-
|
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,
|
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
|
-
|
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
|
-
|
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
|
data/lib/xml/kit/decryption.rb
CHANGED
@@ -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
|
-
|
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.
|
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
data/lib/xml/kit/key_pair.rb
CHANGED
@@ -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
|
-
|
24
|
-
|
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
|
data/lib/xml/kit/namespaces.rb
CHANGED
@@ -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(
|
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
|
data/lib/xml/kit/signatures.rb
CHANGED
data/lib/xml/kit/templatable.rb
CHANGED
@@ -24,12 +24,10 @@ module Xml
|
|
24
24
|
if encrypt?
|
25
25
|
temp = ::Builder::XmlMarkup.new
|
26
26
|
yield temp
|
27
|
-
|
28
|
-
|
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
|
-
|
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.
|
data/lib/xml/kit/template.rb
CHANGED
@@ -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, "
|
24
|
+
File.join(root_path, "templates/", template_name)
|
25
25
|
end
|
26
26
|
|
27
27
|
def template
|
File without changes
|
@@ -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
|
File without changes
|
@@ -1,11 +1,11 @@
|
|
1
1
|
xml.Signature "xmlns" => ::Xml::Kit::Namespaces::XMLDSIG do
|
2
2
|
xml.SignedInfo do
|
3
|
-
xml.CanonicalizationMethod Algorithm:
|
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: "
|
8
|
-
xml.Transform Algorithm:
|
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 ""
|
data/lib/xml/kit/version.rb
CHANGED
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.
|
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-
|
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/
|
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
|