xml-kit 0.1.14 → 0.5.0
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/.rubocop.yml +23 -5
- data/.travis.yml +7 -5
- data/CHANGELOG.md +60 -0
- data/README.md +14 -22
- data/bin/cibuild +1 -1
- data/lib/xml/kit.rb +11 -2
- data/lib/xml/kit/certificate.rb +6 -4
- data/lib/xml/kit/crypto.rb +14 -0
- data/lib/xml/kit/crypto/oaep_cipher.rb +5 -2
- data/lib/xml/kit/crypto/rsa_cipher.rb +4 -2
- data/lib/xml/kit/crypto/symmetric_cipher.rb +30 -9
- data/lib/xml/kit/crypto/unknown_cipher.rb +6 -1
- data/lib/xml/kit/decryption.rb +29 -20
- data/lib/xml/kit/document.rb +5 -4
- data/lib/xml/kit/encrypted_data.rb +51 -0
- data/lib/xml/kit/encrypted_key.rb +35 -0
- data/lib/xml/kit/encryption.rb +27 -18
- data/lib/xml/kit/fingerprint.rb +1 -1
- data/lib/xml/kit/key_info.rb +71 -0
- data/lib/xml/kit/key_info/key_value.rb +19 -0
- data/lib/xml/kit/key_info/retrieval_method.rb +19 -0
- data/lib/xml/kit/key_info/rsa_key_value.rb +15 -0
- data/lib/xml/kit/key_pair.rb +8 -3
- data/lib/xml/kit/namespaces.rb +12 -12
- data/lib/xml/kit/self_signed_certificate.rb +16 -3
- data/lib/xml/kit/signature.rb +9 -2
- data/lib/xml/kit/signatures.rb +4 -1
- data/lib/xml/kit/templatable.rb +75 -24
- data/lib/xml/kit/templates/certificate.builder +1 -5
- data/lib/xml/kit/templates/encrypted_data.builder +9 -0
- data/lib/xml/kit/templates/encrypted_key.builder +9 -0
- data/lib/xml/kit/templates/key_info.builder +14 -0
- data/lib/xml/kit/templates/key_value.builder +5 -0
- data/lib/xml/kit/templates/retrieval_method.builder +3 -0
- data/lib/xml/kit/templates/rsa_key_value.builder +6 -0
- data/lib/xml/kit/templates/signature.builder +1 -1
- data/lib/xml/kit/version.rb +1 -1
- data/xml-kit.gemspec +4 -4
- metadata +29 -18
- data/.rubocop_todo.yml +0 -22
- data/lib/xml/kit/templates/encryption.builder +0 -16
@@ -3,9 +3,11 @@
|
|
3
3
|
module Xml
|
4
4
|
module Kit
|
5
5
|
class SelfSignedCertificate
|
6
|
-
SUBJECT = '/C=CA/ST=AB/L=Calgary/O=XmlKit/OU=XmlKit/CN=XmlKit'
|
6
|
+
SUBJECT = '/C=CA/ST=AB/L=Calgary/O=XmlKit/OU=XmlKit/CN=XmlKit'
|
7
7
|
|
8
|
-
def create(algorithm: 'AES-256-CBC',
|
8
|
+
def create(algorithm: 'AES-256-CBC',
|
9
|
+
passphrase: nil,
|
10
|
+
key_pair: OpenSSL::PKey::RSA.new(2048))
|
9
11
|
certificate = certificate_for(key_pair.public_key)
|
10
12
|
certificate.sign(key_pair, OpenSSL::Digest::SHA256.new)
|
11
13
|
[certificate.to_pem, export(key_pair, algorithm, passphrase)]
|
@@ -24,14 +26,25 @@ module Xml
|
|
24
26
|
|
25
27
|
def certificate_for(public_key)
|
26
28
|
certificate = OpenSSL::X509::Certificate.new
|
27
|
-
certificate.subject =
|
29
|
+
certificate.subject =
|
30
|
+
certificate.issuer = OpenSSL::X509::Name.parse(SUBJECT)
|
28
31
|
certificate.not_before = Time.now
|
29
32
|
certificate.not_after = certificate.not_before + 30 * 24 * 60 * 60 # 30 days
|
30
33
|
certificate.public_key = public_key
|
31
34
|
certificate.serial = 0x0
|
32
35
|
certificate.version = 2
|
36
|
+
apply_ski_extension_to(certificate)
|
33
37
|
certificate
|
34
38
|
end
|
39
|
+
|
40
|
+
def apply_ski_extension_to(certificate)
|
41
|
+
extensions = OpenSSL::X509::ExtensionFactory.new
|
42
|
+
extensions.subject_certificate = certificate
|
43
|
+
extensions.issuer_certificate = certificate
|
44
|
+
certificate.add_extension(
|
45
|
+
extensions.create_extension('subjectKeyIdentifier', 'hash', false)
|
46
|
+
)
|
47
|
+
end
|
35
48
|
end
|
36
49
|
end
|
37
50
|
end
|
data/lib/xml/kit/signature.rb
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
module Xml
|
4
4
|
module Kit
|
5
|
+
# An implementation of the Signature element.
|
6
|
+
# https://www.w3.org/TR/xmldsig-core1/#sec-Signature
|
7
|
+
#
|
8
|
+
# @since 0.1.0
|
5
9
|
class Signature
|
6
10
|
SIGNATURE_METHODS = {
|
7
11
|
SHA1: 'http://www.w3.org/2000/09/xmldsig#rsa-sha1',
|
@@ -11,7 +15,7 @@ module Xml
|
|
11
15
|
SHA512: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512',
|
12
16
|
}.freeze
|
13
17
|
DIGEST_METHODS = {
|
14
|
-
SHA1: 'http://www.w3.org/2000/09/xmldsig#
|
18
|
+
SHA1: 'http://www.w3.org/2000/09/xmldsig#sha1',
|
15
19
|
SHA224: 'http://www.w3.org/2001/04/xmldsig-more#sha224',
|
16
20
|
SHA256: 'http://www.w3.org/2001/04/xmlenc#sha256',
|
17
21
|
SHA384: 'http://www.w3.org/2001/04/xmldsig-more#sha384',
|
@@ -23,7 +27,10 @@ module Xml
|
|
23
27
|
attr_reader :reference_id
|
24
28
|
attr_reader :signature_method
|
25
29
|
|
26
|
-
def initialize(reference_id,
|
30
|
+
def initialize(reference_id,
|
31
|
+
signature_method: :SH256,
|
32
|
+
digest_method: :SHA256,
|
33
|
+
certificate:)
|
27
34
|
@certificate = certificate
|
28
35
|
@digest_method = DIGEST_METHODS[digest_method]
|
29
36
|
@reference_id = reference_id
|
data/lib/xml/kit/signatures.rb
CHANGED
@@ -39,7 +39,10 @@ module Xml
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# @!visibility private
|
42
|
-
def self.sign(xml: ::Builder::XmlMarkup.new,
|
42
|
+
def self.sign(xml: ::Builder::XmlMarkup.new,
|
43
|
+
key_pair:,
|
44
|
+
signature_method: :SHA256,
|
45
|
+
digest_method: :SHA256)
|
43
46
|
signatures = new(
|
44
47
|
key_pair: key_pair,
|
45
48
|
signature_method: signature_method,
|
data/lib/xml/kit/templatable.rb
CHANGED
@@ -17,22 +17,79 @@ module Xml
|
|
17
17
|
# The [Xml::Kit::Certificate] that contains the public key to use for encrypting the document.
|
18
18
|
attr_accessor :encryption_certificate
|
19
19
|
|
20
|
+
# Allows you to specify the digest method algorithm. (Default: SHA256)
|
21
|
+
# A list of digest methods can be found in [Xml::Kit::Signature].
|
22
|
+
attr_accessor :digest_method
|
23
|
+
|
24
|
+
# Allows you to specify the signature method algorithm. (Default: SHA256)
|
25
|
+
# A list of signature methods can be found in [Xml::Kit::Signature].
|
26
|
+
attr_accessor :signature_method
|
27
|
+
|
20
28
|
# Returns the generated XML document with an XML Digital Signature and XML Encryption.
|
21
|
-
def to_xml(xml: ::Builder::XmlMarkup.new)
|
22
|
-
signatures.complete(render(self, xml: xml))
|
29
|
+
def to_xml(xml: ::Builder::XmlMarkup.new, pretty: false)
|
30
|
+
result = signatures.complete(render(self, xml: xml))
|
31
|
+
pretty ? Nokogiri::XML(result).to_xml(indent: 2) : result
|
32
|
+
end
|
33
|
+
|
34
|
+
# Generates an {#Xml::Kit::EncryptedKey} section. https://www.w3.org/TR/xmlenc-core1/#sec-EncryptedKey
|
35
|
+
#
|
36
|
+
# @since 0.3.0
|
37
|
+
# @param xml [Builder::XmlMarkup] the xml builder instance
|
38
|
+
# @param id [String] the id of EncryptedKey element
|
39
|
+
def encrypt_key_for(xml:, id:, key_info: nil)
|
40
|
+
::Xml::Kit::EncryptedKey.new(
|
41
|
+
id: id,
|
42
|
+
asymmetric_cipher: asymmetric_cipher,
|
43
|
+
symmetric_cipher: symmetric_cipher,
|
44
|
+
key_info: key_info
|
45
|
+
).to_xml(xml: xml)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @deprecated Use {#encrypt_data_for} instead of this
|
49
|
+
def encryption_for(*args, &block)
|
50
|
+
::Xml::Kit.deprecate(
|
51
|
+
'encryption_for is deprecated. Use encrypt_data_for instead.'
|
52
|
+
)
|
53
|
+
encrypt_data_for(*args, &block)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Generates an {#Xml::Kit::EncryptedData} section. https://www.w3.org/TR/xmlenc-core1/#sec-EncryptedData
|
57
|
+
#
|
58
|
+
# @since 0.3.0
|
59
|
+
# @param xml [Builder::XmlMarkup] the xml builder instance
|
60
|
+
# @param key_info [Xml::Kit::KeyInfo] the key info to render in the EncryptedData
|
61
|
+
def encrypt_data_for(xml:, key_info: nil)
|
62
|
+
return yield xml unless encrypt?
|
63
|
+
|
64
|
+
temp = ::Builder::XmlMarkup.new
|
65
|
+
yield temp
|
66
|
+
::Xml::Kit::EncryptedData.new(
|
67
|
+
signatures.complete(temp.target!),
|
68
|
+
symmetric_cipher: symmetric_cipher,
|
69
|
+
asymmetric_cipher: asymmetric_cipher,
|
70
|
+
key_info: key_info
|
71
|
+
).to_xml(xml: xml)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Provides a default RSA asymmetric cipher. Can be overridden to provide custom ciphers.
|
75
|
+
#
|
76
|
+
# @abstract
|
77
|
+
# @since 0.3.0
|
78
|
+
def asymmetric_cipher(algorithm: Crypto::RsaCipher::ALGORITHM)
|
79
|
+
raise Xml::Kit::Error, 'encryption_certificate is not specified.' unless encryption_certificate
|
80
|
+
|
81
|
+
@asymmetric_cipher ||= Crypto.cipher_for(
|
82
|
+
algorithm,
|
83
|
+
encryption_certificate.public_key
|
84
|
+
)
|
23
85
|
end
|
24
86
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
encryption_certificate.public_key
|
32
|
-
).to_xml(xml: xml)
|
33
|
-
else
|
34
|
-
yield xml
|
35
|
-
end
|
87
|
+
# Provides a default aes256-cbc symmetric cipher. Can be overridden to provide custom ciphers.
|
88
|
+
#
|
89
|
+
# @abstract
|
90
|
+
# @since 0.3.0
|
91
|
+
def symmetric_cipher
|
92
|
+
@symmetric_cipher ||= Crypto::SymmetricCipher.new
|
36
93
|
end
|
37
94
|
|
38
95
|
def render(model, options)
|
@@ -48,9 +105,11 @@ module Xml
|
|
48
105
|
# Allows you to specify which key pair to use for generating an XML digital signature.
|
49
106
|
#
|
50
107
|
# @param key_pair [Xml::Kit::KeyPair] the key pair to use for signing.
|
51
|
-
def sign_with(key_pair)
|
108
|
+
def sign_with(key_pair, signature_method: :SHA256, digest_method: :SHA256)
|
52
109
|
self.signing_key_pair = key_pair
|
53
110
|
self.embed_signature = true
|
111
|
+
self.signature_method = signature_method
|
112
|
+
self.digest_method = digest_method
|
54
113
|
signatures.sign_with(key_pair)
|
55
114
|
end
|
56
115
|
|
@@ -72,19 +131,11 @@ module Xml
|
|
72
131
|
def signatures
|
73
132
|
@signatures ||= ::Xml::Kit::Signatures.new(
|
74
133
|
key_pair: signing_key_pair,
|
75
|
-
digest_method: digest_method,
|
76
|
-
signature_method: signature_method
|
134
|
+
digest_method: digest_method || :SHA256,
|
135
|
+
signature_method: signature_method || :SHA256
|
77
136
|
)
|
78
137
|
end
|
79
138
|
|
80
|
-
def digest_method
|
81
|
-
:SHA256
|
82
|
-
end
|
83
|
-
|
84
|
-
def signature_method
|
85
|
-
:SHA256
|
86
|
-
end
|
87
|
-
|
88
139
|
# @!visibility private
|
89
140
|
def encrypt?
|
90
141
|
encrypt && encryption_certificate
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
xml.EncryptedKey Id: id, xmlns: ::Xml::Kit::Namespaces::XMLENC do
|
4
|
+
xml.EncryptionMethod Algorithm: asymmetric_cipher.algorithm
|
5
|
+
render(key_info, xml: xml) if key_info
|
6
|
+
xml.CipherData do
|
7
|
+
xml.CipherValue cipher_value
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
xml.KeyInfo xmlns: ::Xml::Kit::Namespaces::XMLDSIG do
|
4
|
+
xml.KeyName key_name if key_name
|
5
|
+
render(key_value, xml: xml) if @key_value
|
6
|
+
render(retrieval_method, xml: xml) if @retrieval_method
|
7
|
+
if x509_data
|
8
|
+
xml.X509Data do
|
9
|
+
xml.X509SKI subject_key_identifier
|
10
|
+
xml.X509Certificate ::Xml::Kit::Certificate.strip(x509_data.to_pem)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
render(encrypted_key, xml: xml) if encrypted_key
|
14
|
+
end
|
@@ -6,7 +6,7 @@ xml.Signature 'xmlns' => ::Xml::Kit::Namespaces::XMLDSIG do
|
|
6
6
|
xml.SignatureMethod Algorithm: signature_method
|
7
7
|
xml.Reference URI: "##{reference_id}" do
|
8
8
|
xml.Transforms do
|
9
|
-
xml.Transform Algorithm:
|
9
|
+
xml.Transform Algorithm: ::Xml::Kit::Namespaces::ENVELOPED_SIG
|
10
10
|
xml.Transform Algorithm: ::Xml::Kit::Namespaces::CANONICALIZATION
|
11
11
|
end
|
12
12
|
xml.DigestMethod Algorithm: digest_method
|
data/lib/xml/kit/version.rb
CHANGED
data/xml-kit.gemspec
CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.description = 'A simple toolkit for working with XML.'
|
15
15
|
spec.homepage = 'https://github.com/saml-kit/xml-kit'
|
16
16
|
spec.license = 'MIT'
|
17
|
-
spec.required_ruby_version = '>= 2.
|
17
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
|
18
18
|
|
19
19
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
20
20
|
f.match(%r{^(test|spec|features)/})
|
@@ -26,13 +26,13 @@ Gem::Specification.new do |spec|
|
|
26
26
|
|
27
27
|
spec.add_dependency 'activemodel', '>= 4.2.0'
|
28
28
|
spec.add_dependency 'builder', '~> 3.2'
|
29
|
-
spec.add_dependency 'nokogiri', '
|
29
|
+
spec.add_dependency 'nokogiri', '~> 1.10'
|
30
30
|
spec.add_dependency 'tilt', '>= 1.4.1'
|
31
31
|
spec.add_dependency 'xmldsig', '~> 0.6'
|
32
|
-
spec.add_development_dependency 'bundler', '~>
|
32
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
33
33
|
spec.add_development_dependency 'bundler-audit', '~> 0.6'
|
34
34
|
spec.add_development_dependency 'ffaker', '~> 2.7'
|
35
|
-
spec.add_development_dependency 'rake', '~>
|
35
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
36
36
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
37
37
|
spec.add_development_dependency 'rubocop', '~> 0.52'
|
38
38
|
spec.add_development_dependency 'rubocop-rspec', '~> 1.22'
|
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.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mo khan
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -42,16 +42,16 @@ dependencies:
|
|
42
42
|
name: nokogiri
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 1.
|
47
|
+
version: '1.10'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 1.
|
54
|
+
version: '1.10'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: tilt
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '2.0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '2.0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: bundler-audit
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,14 +128,14 @@ dependencies:
|
|
128
128
|
requirements:
|
129
129
|
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
131
|
+
version: '13.0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
138
|
+
version: '13.0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: rspec
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -203,9 +203,10 @@ files:
|
|
203
203
|
- ".gitlab-ci.yml"
|
204
204
|
- ".rspec"
|
205
205
|
- ".rubocop.yml"
|
206
|
-
- ".rubocop_todo.yml"
|
207
206
|
- ".travis.yml"
|
207
|
+
- CHANGELOG.md
|
208
208
|
- Gemfile
|
209
|
+
- Gemfile.lock
|
209
210
|
- LICENSE.txt
|
210
211
|
- README.md
|
211
212
|
- Rakefile
|
@@ -225,9 +226,15 @@ files:
|
|
225
226
|
- lib/xml/kit/decryption.rb
|
226
227
|
- lib/xml/kit/decryption_error.rb
|
227
228
|
- lib/xml/kit/document.rb
|
229
|
+
- lib/xml/kit/encrypted_data.rb
|
230
|
+
- lib/xml/kit/encrypted_key.rb
|
228
231
|
- lib/xml/kit/encryption.rb
|
229
232
|
- lib/xml/kit/fingerprint.rb
|
230
233
|
- lib/xml/kit/id.rb
|
234
|
+
- lib/xml/kit/key_info.rb
|
235
|
+
- lib/xml/kit/key_info/key_value.rb
|
236
|
+
- lib/xml/kit/key_info/retrieval_method.rb
|
237
|
+
- lib/xml/kit/key_info/rsa_key_value.rb
|
231
238
|
- lib/xml/kit/key_pair.rb
|
232
239
|
- lib/xml/kit/namespaces.rb
|
233
240
|
- lib/xml/kit/self_signed_certificate.rb
|
@@ -236,8 +243,13 @@ files:
|
|
236
243
|
- lib/xml/kit/templatable.rb
|
237
244
|
- lib/xml/kit/template.rb
|
238
245
|
- lib/xml/kit/templates/certificate.builder
|
239
|
-
- lib/xml/kit/templates/
|
246
|
+
- lib/xml/kit/templates/encrypted_data.builder
|
247
|
+
- lib/xml/kit/templates/encrypted_key.builder
|
248
|
+
- lib/xml/kit/templates/key_info.builder
|
249
|
+
- lib/xml/kit/templates/key_value.builder
|
240
250
|
- lib/xml/kit/templates/nil_class.builder
|
251
|
+
- lib/xml/kit/templates/retrieval_method.builder
|
252
|
+
- lib/xml/kit/templates/rsa_key_value.builder
|
241
253
|
- lib/xml/kit/templates/signature.builder
|
242
254
|
- lib/xml/kit/version.rb
|
243
255
|
- xml-kit.gemspec
|
@@ -246,7 +258,7 @@ licenses:
|
|
246
258
|
- MIT
|
247
259
|
metadata:
|
248
260
|
yard.run: yri
|
249
|
-
post_install_message:
|
261
|
+
post_install_message:
|
250
262
|
rdoc_options: []
|
251
263
|
require_paths:
|
252
264
|
- lib
|
@@ -254,16 +266,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
254
266
|
requirements:
|
255
267
|
- - ">="
|
256
268
|
- !ruby/object:Gem::Version
|
257
|
-
version: 2.
|
269
|
+
version: 2.5.0
|
258
270
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
259
271
|
requirements:
|
260
272
|
- - ">="
|
261
273
|
- !ruby/object:Gem::Version
|
262
274
|
version: '0'
|
263
275
|
requirements: []
|
264
|
-
|
265
|
-
|
266
|
-
signing_key:
|
276
|
+
rubygems_version: 3.2.3
|
277
|
+
signing_key:
|
267
278
|
specification_version: 4
|
268
279
|
summary: A simple toolkit for working with XML.
|
269
280
|
test_files: []
|