saml-kit 0.3.0 → 0.3.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/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
|