saml-kit 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/saml-kit-create-self-signed-certificate +1 -1
- data/exe/saml-kit-decode-http-post +1 -3
- data/exe/saml-kit-decode-http-redirect +2 -3
- data/lib/saml/kit.rb +1 -14
- data/lib/saml/kit/assertion.rb +14 -11
- data/lib/saml/kit/bindings/url_builder.rb +1 -1
- data/lib/saml/kit/builders.rb +2 -2
- data/lib/saml/kit/builders/assertion.rb +3 -2
- data/lib/saml/kit/builders/authentication_request.rb +3 -2
- data/lib/saml/kit/builders/encrypted_assertion.rb +20 -0
- data/lib/saml/kit/builders/identity_provider_metadata.rb +4 -3
- data/lib/saml/kit/builders/logout_request.rb +3 -2
- data/lib/saml/kit/builders/logout_response.rb +3 -2
- data/lib/saml/kit/builders/metadata.rb +4 -3
- data/lib/saml/kit/builders/response.rb +14 -5
- data/lib/saml/kit/builders/service_provider_metadata.rb +2 -1
- data/lib/saml/kit/builders/templates/assertion.builder +21 -23
- data/lib/saml/kit/builders/templates/encrypted_assertion.builder +5 -0
- data/lib/saml/kit/configuration.rb +2 -2
- data/lib/saml/kit/document.rb +11 -1
- data/lib/saml/kit/metadata.rb +13 -6
- data/lib/saml/kit/namespaces.rb +0 -11
- data/lib/saml/kit/signature.rb +1 -1
- data/lib/saml/kit/trustable.rb +7 -1
- data/lib/saml/kit/version.rb +1 -1
- data/lib/saml/kit/xml_templatable.rb +37 -0
- data/saml-kit.gemspec +1 -3
- metadata +10 -56
- data/lib/saml/kit/builders/templates/certificate.builder +0 -7
- data/lib/saml/kit/builders/templates/nil_class.builder +0 -0
- data/lib/saml/kit/builders/templates/xml_encryption.builder +0 -16
- data/lib/saml/kit/builders/templates/xml_signature.builder +0 -20
- data/lib/saml/kit/builders/xml_encryption.rb +0 -20
- data/lib/saml/kit/builders/xml_signature.rb +0 -40
- data/lib/saml/kit/certificate.rb +0 -96
- data/lib/saml/kit/crypto.rb +0 -17
- data/lib/saml/kit/crypto/oaep_cipher.rb +0 -22
- data/lib/saml/kit/crypto/rsa_cipher.rb +0 -23
- data/lib/saml/kit/crypto/simple_cipher.rb +0 -38
- data/lib/saml/kit/crypto/unknown_cipher.rb +0 -18
- data/lib/saml/kit/fingerprint.rb +0 -50
- data/lib/saml/kit/id.rb +0 -14
- data/lib/saml/kit/key_pair.rb +0 -29
- data/lib/saml/kit/self_signed_certificate.rb +0 -28
- data/lib/saml/kit/signatures.rb +0 -57
- data/lib/saml/kit/templatable.rb +0 -67
- data/lib/saml/kit/template.rb +0 -33
- data/lib/saml/kit/xml.rb +0 -80
- data/lib/saml/kit/xml_decryption.rb +0 -44
data/lib/saml/kit/crypto.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'saml/kit/crypto/oaep_cipher'
|
2
|
-
require 'saml/kit/crypto/rsa_cipher'
|
3
|
-
require 'saml/kit/crypto/simple_cipher'
|
4
|
-
require 'saml/kit/crypto/unknown_cipher'
|
5
|
-
|
6
|
-
module Saml
|
7
|
-
module Kit
|
8
|
-
module Crypto
|
9
|
-
DECRYPTORS = [ SimpleCipher, RsaCipher, OaepCipher, UnknownCipher ]
|
10
|
-
|
11
|
-
# @!visibility private
|
12
|
-
def self.decryptor_for(algorithm, key)
|
13
|
-
DECRYPTORS.find { |x| x.matches?(algorithm) }.new(algorithm, key)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Saml
|
2
|
-
module Kit
|
3
|
-
module Crypto
|
4
|
-
class OaepCipher
|
5
|
-
ALGORITHMS = {
|
6
|
-
'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' => true,
|
7
|
-
}
|
8
|
-
def initialize(algorithm, key)
|
9
|
-
@key = key
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.matches?(algorithm)
|
13
|
-
ALGORITHMS[algorithm]
|
14
|
-
end
|
15
|
-
|
16
|
-
def decrypt(cipher_text)
|
17
|
-
@key.private_decrypt(cipher_text, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module Saml
|
2
|
-
module Kit
|
3
|
-
module Crypto
|
4
|
-
class RsaCipher
|
5
|
-
ALGORITHMS = {
|
6
|
-
'http://www.w3.org/2001/04/xmlenc#rsa-1_5' => true,
|
7
|
-
}
|
8
|
-
|
9
|
-
def initialize(algorithm, key)
|
10
|
-
@key = key
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.matches?(algorithm)
|
14
|
-
ALGORITHMS[algorithm]
|
15
|
-
end
|
16
|
-
|
17
|
-
def decrypt(cipher_text)
|
18
|
-
@key.private_decrypt(cipher_text)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
module Saml
|
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
|
-
|
30
|
-
Saml::Kit.logger.debug ['-key', @private_key].inspect
|
31
|
-
Saml::Kit.logger.debug ['-iv', iv].inspect
|
32
|
-
|
33
|
-
cipher.update(data) + cipher.final
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
data/lib/saml/kit/fingerprint.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
module Saml
|
2
|
-
module Kit
|
3
|
-
# This generates a fingerprint for an X509 Certificate.
|
4
|
-
#
|
5
|
-
# certificate, _ = Saml::Kit::SelfSignedCertificate.new("password").create
|
6
|
-
#
|
7
|
-
# puts Saml::Kit::Fingerprint.new(certificate).to_s
|
8
|
-
# # B7:AB:DC:BD:4D:23:58:65:FD:1A:99:0C:5F:89:EA:87:AD:F1:D7:83:34:7A:E9:E4:88:12:DD:46:1F:38:05:93
|
9
|
-
#
|
10
|
-
# {include:file:spec/saml/fingerprint_spec.rb}
|
11
|
-
class Fingerprint
|
12
|
-
# The OpenSSL::X509::Certificate
|
13
|
-
attr_reader :x509
|
14
|
-
|
15
|
-
def initialize(raw_certificate)
|
16
|
-
@x509 = Certificate.to_x509(raw_certificate)
|
17
|
-
end
|
18
|
-
|
19
|
-
# Generates a formatted fingerprint using the specified hash algorithm.
|
20
|
-
#
|
21
|
-
# @param algorithm [OpenSSL::Digest] the openssl algorithm to use `OpenSSL::Digest::SHA256`, `OpenSSL::Digest::SHA1`.
|
22
|
-
# @return [String] in the format of `"BF:ED:C5:F1:6C:AB:F5:B2:15:1F:BF:BD:7D:68:1A:F9:A5:4E:4C:19:30:BC:6D:25:B1:8E:98:D4:23:FD:B4:09"`
|
23
|
-
def algorithm(algorithm)
|
24
|
-
pretty_fingerprint(algorithm.new.hexdigest(x509.to_der))
|
25
|
-
end
|
26
|
-
|
27
|
-
def ==(other)
|
28
|
-
self.to_s == other.to_s
|
29
|
-
end
|
30
|
-
|
31
|
-
def eql?(other)
|
32
|
-
self == other
|
33
|
-
end
|
34
|
-
|
35
|
-
def hash
|
36
|
-
to_s.hash
|
37
|
-
end
|
38
|
-
|
39
|
-
def to_s
|
40
|
-
algorithm(OpenSSL::Digest::SHA256)
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def pretty_fingerprint(fingerprint)
|
46
|
-
fingerprint.upcase.scan(/../).join(":")
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
data/lib/saml/kit/id.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
module Saml
|
2
|
-
module Kit
|
3
|
-
# This class is used primary for generating ID.
|
4
|
-
#https://www.w3.org/2001/XMLSchema.xsd
|
5
|
-
class Id
|
6
|
-
|
7
|
-
# Generate an ID that conforms to the XML Schema.
|
8
|
-
# https://www.w3.org/2001/XMLSchema.xsd
|
9
|
-
def self.generate
|
10
|
-
"_#{SecureRandom.uuid}"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
data/lib/saml/kit/key_pair.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
module Saml
|
2
|
-
module Kit
|
3
|
-
class KeyPair # :nodoc:
|
4
|
-
attr_reader :certificate, :private_key, :use
|
5
|
-
|
6
|
-
def initialize(certificate, private_key, passphrase, use)
|
7
|
-
@use = use
|
8
|
-
@certificate = Saml::Kit::Certificate.new(certificate, use: use)
|
9
|
-
@private_key = OpenSSL::PKey::RSA.new(private_key, passphrase)
|
10
|
-
end
|
11
|
-
|
12
|
-
# Returns true if the key pair is the designated use.
|
13
|
-
#
|
14
|
-
# @param use [Symbol] Can be either `:signing` or `:encryption`.
|
15
|
-
def for?(use)
|
16
|
-
@use == use
|
17
|
-
end
|
18
|
-
|
19
|
-
# Returns a generated self signed certificate with private key.
|
20
|
-
#
|
21
|
-
# @param use [Symbol] Can be either `:signing` or `:encryption`.
|
22
|
-
# @param passphrase [String] the passphrase to use to encrypt the private key.
|
23
|
-
def self.generate(use:, passphrase: SecureRandom.uuid)
|
24
|
-
certificate, private_key = SelfSignedCertificate.new(passphrase).create
|
25
|
-
new(certificate, private_key, passphrase, use)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
module Saml
|
2
|
-
module Kit
|
3
|
-
class SelfSignedCertificate
|
4
|
-
SUBJECT="/C=CA/ST=Alberta/L=Calgary/O=SamlKit/OU=SamlKit/CN=SamlKit"
|
5
|
-
|
6
|
-
def initialize(passphrase)
|
7
|
-
@passphrase = passphrase
|
8
|
-
end
|
9
|
-
|
10
|
-
def create
|
11
|
-
rsa_key = OpenSSL::PKey::RSA.new(2048)
|
12
|
-
public_key = rsa_key.public_key
|
13
|
-
certificate = OpenSSL::X509::Certificate.new
|
14
|
-
certificate.subject = certificate.issuer = OpenSSL::X509::Name.parse(SUBJECT)
|
15
|
-
certificate.not_before = DateTime.now.beginning_of_day
|
16
|
-
certificate.not_after = 30.days.from_now
|
17
|
-
certificate.public_key = public_key
|
18
|
-
certificate.serial = 0x0
|
19
|
-
certificate.version = 2
|
20
|
-
certificate.sign(rsa_key, OpenSSL::Digest::SHA256.new)
|
21
|
-
[
|
22
|
-
certificate.to_pem,
|
23
|
-
rsa_key.to_pem(OpenSSL::Cipher.new('AES-256-CBC'), @passphrase)
|
24
|
-
]
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
data/lib/saml/kit/signatures.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
module Saml
|
2
|
-
module Kit
|
3
|
-
# @!visibility private
|
4
|
-
class Signatures # :nodoc:
|
5
|
-
# @!visibility private
|
6
|
-
attr_reader :configuration
|
7
|
-
|
8
|
-
# @!visibility private
|
9
|
-
def initialize(configuration:)
|
10
|
-
@configuration = configuration
|
11
|
-
@key_pair = configuration.key_pairs(use: :signing).last
|
12
|
-
end
|
13
|
-
|
14
|
-
# @!visibility private
|
15
|
-
def sign_with(key_pair)
|
16
|
-
@key_pair = key_pair
|
17
|
-
end
|
18
|
-
|
19
|
-
# @!visibility private
|
20
|
-
def build(reference_id)
|
21
|
-
return nil unless configuration.sign?
|
22
|
-
certificate = @key_pair.certificate
|
23
|
-
Saml::Kit::Builders::XmlSignature.new(reference_id, configuration: configuration, certificate: certificate)
|
24
|
-
end
|
25
|
-
|
26
|
-
# @!visibility private
|
27
|
-
def complete(raw_xml)
|
28
|
-
return raw_xml unless configuration.sign?
|
29
|
-
private_key = @key_pair.private_key
|
30
|
-
Xmldsig::SignedDocument.new(raw_xml).sign(private_key)
|
31
|
-
end
|
32
|
-
|
33
|
-
# @!visibility private
|
34
|
-
def self.sign(xml: ::Builder::XmlMarkup.new, configuration: Saml::Kit.configuration)
|
35
|
-
signatures = Saml::Kit::Signatures.new(configuration: configuration)
|
36
|
-
yield xml, XmlSignatureTemplate.new(xml, signatures)
|
37
|
-
signatures.complete(xml.target!)
|
38
|
-
end
|
39
|
-
|
40
|
-
class XmlSignatureTemplate # :nodoc:
|
41
|
-
# @!visibility private
|
42
|
-
attr_reader :signatures, :xml
|
43
|
-
|
44
|
-
# @!visibility private
|
45
|
-
def initialize(xml, signatures)
|
46
|
-
@signatures = signatures
|
47
|
-
@xml = xml
|
48
|
-
end
|
49
|
-
|
50
|
-
# @!visibility private
|
51
|
-
def template(reference_id)
|
52
|
-
Template.new(signatures.build(reference_id)).to_xml(xml: xml)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
data/lib/saml/kit/templatable.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
module Saml
|
2
|
-
module Kit
|
3
|
-
module Templatable
|
4
|
-
# Can be used to disable embeding a signature.
|
5
|
-
# By default a signature will be embedded if a signing
|
6
|
-
# certificate is available via the configuration.
|
7
|
-
attr_accessor :embed_signature
|
8
|
-
|
9
|
-
# @deprecated Use {#embed_signature=} instead of this method.
|
10
|
-
def sign=(value)
|
11
|
-
Saml::Kit.deprecate("sign= is deprecated. Use embed_signature= instead")
|
12
|
-
self.embed_signature = value
|
13
|
-
end
|
14
|
-
|
15
|
-
# Returns the generated XML document with an XML Digital Signature and XML Encryption.
|
16
|
-
def to_xml(xml: ::Builder::XmlMarkup.new)
|
17
|
-
signatures.complete(render(self, xml: xml))
|
18
|
-
end
|
19
|
-
|
20
|
-
# @!visibility private
|
21
|
-
def signature_for(reference_id:, xml:)
|
22
|
-
return unless sign?
|
23
|
-
render(signatures.build(reference_id), xml: xml)
|
24
|
-
end
|
25
|
-
|
26
|
-
# Allows you to specify which key pair to use for generating an XML digital signature.
|
27
|
-
#
|
28
|
-
# @param key_pair [Saml::Kit::KeyPair] the key pair to use for signing.
|
29
|
-
def sign_with(key_pair)
|
30
|
-
signatures.sign_with(key_pair)
|
31
|
-
end
|
32
|
-
|
33
|
-
# Returns true if an embedded signature is requested and at least one signing certificate is available via the configuration.
|
34
|
-
def sign?
|
35
|
-
embed_signature.nil? ? configuration.sign? : embed_signature && configuration.sign?
|
36
|
-
end
|
37
|
-
|
38
|
-
# @!visibility private
|
39
|
-
def signatures
|
40
|
-
@signatures ||= Saml::Kit::Signatures.new(configuration: configuration)
|
41
|
-
end
|
42
|
-
|
43
|
-
# @!visibility private
|
44
|
-
def encryption_for(xml:)
|
45
|
-
if encrypt?
|
46
|
-
temp = ::Builder::XmlMarkup.new
|
47
|
-
yield temp
|
48
|
-
signed_xml = signatures.complete(temp.target!)
|
49
|
-
xml_encryption = Saml::Kit::Builders::XmlEncryption.new(signed_xml, encryption_certificate.public_key)
|
50
|
-
render(xml_encryption, xml: xml)
|
51
|
-
else
|
52
|
-
yield xml
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# @!visibility private
|
57
|
-
def encrypt?
|
58
|
-
encrypt && encryption_certificate
|
59
|
-
end
|
60
|
-
|
61
|
-
# @!visibility private
|
62
|
-
def render(model, options)
|
63
|
-
Saml::Kit::Template.new(model).to_xml(options)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
data/lib/saml/kit/template.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
module Saml
|
2
|
-
module Kit
|
3
|
-
class Template
|
4
|
-
attr_reader :target
|
5
|
-
|
6
|
-
def initialize(target)
|
7
|
-
@target = target
|
8
|
-
end
|
9
|
-
|
10
|
-
# Returns the compiled template as a [String].
|
11
|
-
#
|
12
|
-
# @param options [Hash] The options hash to pass to the template engine.
|
13
|
-
def to_xml(options)
|
14
|
-
template.render(target, options)
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def template_name
|
20
|
-
"#{target.class.name.split("::").last.underscore}.builder"
|
21
|
-
end
|
22
|
-
|
23
|
-
def template_path
|
24
|
-
root_path = File.expand_path(File.dirname(__FILE__))
|
25
|
-
File.join(root_path, "builders/templates/", template_name)
|
26
|
-
end
|
27
|
-
|
28
|
-
def template
|
29
|
-
Tilt.new(template_path)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
data/lib/saml/kit/xml.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
module Saml
|
2
|
-
module Kit
|
3
|
-
# {include:file:spec/saml/xml_spec.rb}
|
4
|
-
class Xml # :nodoc:
|
5
|
-
include ActiveModel::Validations
|
6
|
-
NAMESPACES = {
|
7
|
-
"NameFormat": Namespaces::ATTR_SPLAT,
|
8
|
-
"ds": Namespaces::XMLDSIG,
|
9
|
-
"md": Namespaces::METADATA,
|
10
|
-
"saml": Namespaces::ASSERTION,
|
11
|
-
"samlp": Namespaces::PROTOCOL,
|
12
|
-
}.freeze
|
13
|
-
|
14
|
-
validate :validate_signatures
|
15
|
-
validate :validate_certificates
|
16
|
-
|
17
|
-
def initialize(raw_xml)
|
18
|
-
@raw_xml = raw_xml
|
19
|
-
@document = Nokogiri::XML(raw_xml)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Returns the first XML node found by searching the document with the provided XPath.
|
23
|
-
#
|
24
|
-
# @param xpath [String] the XPath to use to search the document
|
25
|
-
def find_by(xpath)
|
26
|
-
document.at_xpath(xpath, NAMESPACES)
|
27
|
-
end
|
28
|
-
|
29
|
-
# Returns all XML nodes found by searching the document with the provided XPath.
|
30
|
-
#
|
31
|
-
# @param xpath [String] the XPath to use to search the document
|
32
|
-
def find_all(xpath)
|
33
|
-
document.search(xpath, NAMESPACES)
|
34
|
-
end
|
35
|
-
|
36
|
-
# Return the XML document as a [String].
|
37
|
-
#
|
38
|
-
# @param pretty [Boolean] return the XML string in a human readable format if true.
|
39
|
-
def to_xml(pretty: true)
|
40
|
-
pretty ? document.to_xml(indent: 2) : raw_xml
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
attr_reader :raw_xml, :document
|
46
|
-
|
47
|
-
def validate_signatures
|
48
|
-
invalid_signatures.flat_map(&:errors).uniq.each do |error|
|
49
|
-
errors.add(error, "is invalid")
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def invalid_signatures
|
54
|
-
signed_document = Xmldsig::SignedDocument.new(document, id_attr: 'ID=$uri or @Id')
|
55
|
-
signed_document.signatures.find_all do |signature|
|
56
|
-
x509_certificates.all? do |certificate|
|
57
|
-
!signature.valid?(certificate)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def validate_certificates(now = Time.current)
|
63
|
-
return if find_by('//ds:Signature').nil?
|
64
|
-
|
65
|
-
x509_certificates.each do |certificate|
|
66
|
-
inactive = now < certificate.not_before
|
67
|
-
errors.add(:certificate, "Not valid before #{certificate.not_before}") if inactive
|
68
|
-
|
69
|
-
expired = now > certificate.not_after
|
70
|
-
errors.add(:certificate, "Not valid after #{certificate.not_after}") if expired
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def x509_certificates
|
75
|
-
xpath = "//ds:KeyInfo/ds:X509Data/ds:X509Certificate"
|
76
|
-
find_all(xpath).map { |item| Certificate.to_x509(item.text) }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|