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 +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
|