diff --git a/README.md b/README.md
index 50f99ebe..d8c48dd7 100644
--- a/README.md
+++ b/README.md
@@ -78,11 +78,6 @@ KEY DATA
-----END RSA PRIVATE KEY-----
CERT
- # x509_certificate, secret_key, and password may also be set from within a proc, for example:
- # config.x509_certificate = -> { File.read("cert.pem") }
- # config.secret_key = -> { SecretKeyFinder.key_for(id: 1) }
- # config.password = -> { "password" }
-
# config.password = "secret_key_password"
# config.algorithm = :sha256 # Default: sha1 only for development.
# config.organization_name = "Your Organization"
diff --git a/lib/saml_idp/algorithmable.rb b/lib/saml_idp/algorithmable.rb
index 354dbb92..182d6114 100644
--- a/lib/saml_idp/algorithmable.rb
+++ b/lib/saml_idp/algorithmable.rb
@@ -1,10 +1,9 @@
module SamlIdp
module Algorithmable
def algorithm
- algorithm_check = raw_algorithm || SamlIdp.config.algorithm
- return algorithm_check if algorithm_check.respond_to?(:digest)
+ return raw_algorithm if raw_algorithm.respond_to?(:digest)
begin
- OpenSSL::Digest.const_get(algorithm_check.to_s.upcase)
+ OpenSSL::Digest.const_get(raw_algorithm.to_s.upcase)
rescue NameError
OpenSSL::Digest::SHA1
end
diff --git a/lib/saml_idp/assertion_builder.rb b/lib/saml_idp/assertion_builder.rb
index 8e0170fa..482ab16a 100644
--- a/lib/saml_idp/assertion_builder.rb
+++ b/lib/saml_idp/assertion_builder.rb
@@ -18,23 +18,29 @@ class AssertionBuilder
attr_accessor :session_expiry
attr_accessor :name_id_formats_opts
attr_accessor :asserted_attributes_opts
+ attr_accessor :public_cert
+ attr_accessor :private_key
+ attr_accessor :pv_key_password
delegate :config, to: :SamlIdp
def initialize(
- reference_id,
- issuer_uri,
- principal,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- raw_algorithm,
- authn_context_classref,
- expiry=60*60,
- encryption_opts=nil,
- session_expiry=nil,
- name_id_formats_opts = nil,
- asserted_attributes_opts = nil
+ reference_id:,
+ issuer_uri:,
+ principal:,
+ audience_uri:,
+ saml_request_id:,
+ saml_acs_url:,
+ raw_algorithm:,
+ authn_context_classref:,
+ public_cert:,
+ private_key:,
+ pv_key_password:,
+ expiry: 60*60,
+ encryption_opts: nil,
+ session_expiry: nil,
+ name_id_formats_opts: nil,
+ asserted_attributes_opts: nil
)
self.reference_id = reference_id
self.issuer_uri = issuer_uri
@@ -49,6 +55,17 @@ def initialize(
self.session_expiry = session_expiry.nil? ? config.session_expiry : session_expiry
self.name_id_formats_opts = name_id_formats_opts
self.asserted_attributes_opts = asserted_attributes_opts
+ self.public_cert = public_cert
+ self.private_key = private_key
+ self.pv_key_password = pv_key_password
+ end
+
+ def encrypt(opts = {})
+ raise "Must set encryption_opts to encrypt" unless encryption_opts
+ raw_xml = opts[:sign] ? signed : raw
+ require 'saml_idp/encryptor'
+ encryptor = Encryptor.new encryption_opts
+ encryptor.encrypt(raw_xml)
end
def fresh
@@ -105,15 +122,8 @@ def fresh
end
end
alias_method :raw, :fresh
- private :fresh
- def encrypt(opts = {})
- raise "Must set encryption_opts to encrypt" unless encryption_opts
- raw_xml = opts[:sign] ? signed : raw
- require 'saml_idp/encryptor'
- encryptor = Encryptor.new encryption_opts
- encryptor.encrypt(raw_xml)
- end
+ private
def asserted_attributes
if asserted_attributes_opts.present? && !asserted_attributes_opts.empty?
@@ -124,7 +134,6 @@ def asserted_attributes
config.attributes
end
end
- private :asserted_attributes
def get_values_for(friendly_name, getter)
result = nil
@@ -141,12 +150,10 @@ def get_values_for(friendly_name, getter)
end
Array(result)
end
- private :get_values_for
def name_id
name_id_getter.call principal
end
- private :name_id
def name_id_getter
getter = name_id_format[:getter]
@@ -156,56 +163,45 @@ def name_id_getter
->(principal) { principal.public_send getter.to_s }
end
end
- private :name_id_getter
def name_id_format
@name_id_format ||= NameIdFormatter.new(name_id_formats).chosen
end
- private :name_id_format
def name_id_formats
@name_id_formats ||= (name_id_formats_opts || config.name_id.formats)
end
- private :name_id_formats
def reference_string
"_#{reference_id}"
end
- private :reference_string
def now
@now ||= Time.now.utc
end
- private :now
def now_iso
iso { now }
end
- private :now_iso
def not_before
iso { now - 5 }
end
- private :not_before
def not_on_or_after_condition
iso { now + expiry }
end
- private :not_on_or_after_condition
def not_on_or_after_subject
iso { now + 3 * 60 }
end
- private :not_on_or_after_subject
def session_not_on_or_after
iso { now + session_expiry }
end
- private :session_not_on_or_after
def iso
yield.iso8601
end
- private :iso
end
end
diff --git a/lib/saml_idp/configurator.rb b/lib/saml_idp/configurator.rb
index 99a662a0..e645f912 100644
--- a/lib/saml_idp/configurator.rb
+++ b/lib/saml_idp/configurator.rb
@@ -25,8 +25,8 @@ class Configurator
attr_accessor :logger
def initialize
- self.x509_certificate = -> { Default::X509_CERTIFICATE }
- self.secret_key = -> { Default::SECRET_KEY }
+ self.x509_certificate = Default::X509_CERTIFICATE
+ self.secret_key = Default::SECRET_KEY
self.algorithm = :sha1
self.reference_id_generator = ->() { SecureRandom.uuid }
self.service_provider = OpenStruct.new
diff --git a/lib/saml_idp/controller.rb b/lib/saml_idp/controller.rb
index 26ebbf29..283aff38 100644
--- a/lib/saml_idp/controller.rb
+++ b/lib/saml_idp/controller.rb
@@ -34,10 +34,7 @@ def acs_url
def validate_saml_request(raw_saml_request = params[:SAMLRequest])
decode_request(raw_saml_request, params[:Signature], params[:SigAlg], params[:RelayState])
- return true if valid_saml_request?
-
- head :forbidden if defined?(::Rails)
- false
+ valid_saml_request?
end
def decode_request(raw_saml_request, signature, sig_algorithm, relay_state)
@@ -60,6 +57,9 @@ def encode_authn_response(principal, opts = {})
audience_uri = opts[:audience_uri] || saml_request.issuer || saml_acs_url[/^(.*?\/\/.*?\/)/, 1]
opt_issuer_uri = opts[:issuer_uri] || issuer_uri
my_authn_context_classref = opts[:authn_context_classref] || authn_context_classref
+ public_cert = opts[:public_cert] || SamlIdp.config.x509_certificate
+ private_key = opts[:private_key] || SamlIdp.config.secret_key
+ pv_key_password = opts[:pv_key_password] || SamlIdp.config.password
acs_url = opts[:acs_url] || saml_acs_url
expiry = opts[:expiry] || 60*60
session_expiry = opts[:session_expiry]
@@ -73,33 +73,39 @@ def encode_authn_response(principal, opts = {})
compress_opts = opts[:compress] || false
SamlResponse.new(
- reference_id,
- response_id,
- opt_issuer_uri,
- principal,
- audience_uri,
- saml_request_id,
- acs_url,
- (opts[:algorithm] || algorithm || default_algorithm),
- my_authn_context_classref,
- expiry,
- encryption_opts,
- session_expiry,
- name_id_formats_opts,
- asserted_attributes_opts,
- signed_message_opts,
- signed_assertion_opts,
- compress_opts
+ reference_id: reference_id,
+ response_id: response_id,
+ issuer_uri: opt_issuer_uri,
+ principal: principal,
+ audience_uri: audience_uri,
+ saml_request_id: saml_request_id,
+ saml_acs_url: acs_url,
+ algorithm: (opts[:algorithm] || algorithm || default_algorithm),
+ authn_context_classref: my_authn_context_classref,
+ public_cert: public_cert,
+ private_key: private_key,
+ pv_key_password: pv_key_password,
+ expiry: expiry,
+ encryption_opts: encryption_opts,
+ session_expiry: session_expiry,
+ name_id_formats_opts: name_id_formats_opts,
+ asserted_attributes_opts: asserted_attributes_opts,
+ signed_message_opts: signed_message_opts,
+ signed_assertion_opts: signed_assertion_opts,
+ compression_opts: compress_opts
).build
end
def encode_logout_response(_principal, opts = {})
SamlIdp::LogoutResponseBuilder.new(
- get_saml_response_id,
- (opts[:issuer_uri] || issuer_uri),
- saml_logout_url,
- saml_request_id,
- (opts[:algorithm] || algorithm || default_algorithm)
+ response_id: get_saml_response_id,
+ issuer_uri: (opts[:issuer_uri] || issuer_uri),
+ saml_slo_url: saml_logout_url,
+ saml_request_id: saml_request_id,
+ algorithm: (opts[:algorithm] || algorithm || default_algorithm),
+ public_cert: opts[:public_cert] || SamlIdp.config.x509_certificate,
+ private_key: opts[:private_key] || SamlIdp.config.secret_key,
+ pv_key_password: opts[:pv_key_password] || SamlIdp.config.password
).signed
end
diff --git a/lib/saml_idp/logout_builder.rb b/lib/saml_idp/logout_builder.rb
index 7d049dd6..230e898c 100644
--- a/lib/saml_idp/logout_builder.rb
+++ b/lib/saml_idp/logout_builder.rb
@@ -7,12 +7,26 @@ class LogoutBuilder
attr_accessor :issuer_uri
attr_accessor :saml_slo_url
attr_accessor :algorithm
+ attr_accessor :public_cert
+ attr_accessor :private_key
+ attr_accessor :pv_key_password
- def initialize(response_id, issuer_uri, saml_slo_url, algorithm)
+ def initialize(
+ response_id:,
+ issuer_uri:,
+ saml_slo_url:,
+ algorithm:,
+ public_cert:,
+ private_key:,
+ pv_key_password:
+ )
self.response_id = response_id
self.issuer_uri = issuer_uri
self.saml_slo_url = saml_slo_url
self.algorithm = algorithm
+ self.public_cert = public_cert
+ self.private_key = private_key
+ self.pv_key_password = pv_key_password
end
# this is an abstract base class.
diff --git a/lib/saml_idp/logout_request_builder.rb b/lib/saml_idp/logout_request_builder.rb
index b75f9315..87f76c89 100644
--- a/lib/saml_idp/logout_request_builder.rb
+++ b/lib/saml_idp/logout_request_builder.rb
@@ -3,8 +3,25 @@ module SamlIdp
class LogoutRequestBuilder < LogoutBuilder
attr_accessor :name_id
- def initialize(response_id, issuer_uri, saml_slo_url, name_id, algorithm)
- super(response_id, issuer_uri, saml_slo_url, algorithm)
+ def initialize(
+ response_id:,
+ issuer_uri:,
+ saml_slo_url:,
+ name_id:,
+ algorithm:,
+ public_cert:,
+ private_key:,
+ pv_key_password: nil
+ )
+ super(
+ response_id: response_id,
+ issuer_uri: issuer_uri,
+ saml_slo_url: saml_slo_url,
+ algorithm: algorithm,
+ public_cert: public_cert,
+ private_key: private_key,
+ pv_key_password: pv_key_password
+ )
self.name_id = name_id
end
diff --git a/lib/saml_idp/logout_response_builder.rb b/lib/saml_idp/logout_response_builder.rb
index fd14116b..ee9370cb 100644
--- a/lib/saml_idp/logout_response_builder.rb
+++ b/lib/saml_idp/logout_response_builder.rb
@@ -3,8 +3,25 @@ module SamlIdp
class LogoutResponseBuilder < LogoutBuilder
attr_accessor :saml_request_id
- def initialize(response_id, issuer_uri, saml_slo_url, saml_request_id, algorithm)
- super(response_id, issuer_uri, saml_slo_url, algorithm)
+ def initialize(
+ response_id:,
+ issuer_uri:,
+ saml_slo_url:,
+ saml_request_id:,
+ algorithm:,
+ public_cert:,
+ private_key:,
+ pv_key_password: nil
+ )
+ super(
+ response_id: response_id,
+ issuer_uri: issuer_uri,
+ saml_slo_url: saml_slo_url,
+ algorithm: algorithm,
+ public_cert: public_cert,
+ private_key: private_key,
+ pv_key_password: pv_key_password
+ )
self.saml_request_id = saml_request_id
end
diff --git a/lib/saml_idp/metadata_builder.rb b/lib/saml_idp/metadata_builder.rb
index 92258e38..5d77caad 100644
--- a/lib/saml_idp/metadata_builder.rb
+++ b/lib/saml_idp/metadata_builder.rb
@@ -160,6 +160,16 @@ def x509_certificate
.gsub(/\n/, "")
end
+ alias_method :public_cert, :x509_certificate
+
+ def private_key
+ SamlIdp.config.secret_key
+ end
+
+ def pv_key_password
+ nil
+ end
+
%w[
support_email
organization_name
diff --git a/lib/saml_idp/response_builder.rb b/lib/saml_idp/response_builder.rb
index 0686cd9b..fc278b98 100644
--- a/lib/saml_idp/response_builder.rb
+++ b/lib/saml_idp/response_builder.rb
@@ -11,16 +11,32 @@ class ResponseBuilder
attr_accessor :saml_request_id
attr_accessor :assertion_and_signature
attr_accessor :raw_algorithm
+ attr_accessor :public_cert
+ attr_accessor :private_key
+ attr_accessor :pv_key_password
alias_method :reference_id, :response_id
- def initialize(response_id, issuer_uri, saml_acs_url, saml_request_id, assertion_and_signature, raw_algorithm)
+ def initialize(
+ response_id:,
+ issuer_uri:,
+ saml_acs_url:,
+ saml_request_id:,
+ assertion_and_signature:,
+ raw_algorithm:,
+ public_cert:,
+ private_key:,
+ pv_key_password:
+ )
self.response_id = response_id
self.issuer_uri = issuer_uri
self.saml_acs_url = saml_acs_url
self.saml_request_id = saml_request_id
self.assertion_and_signature = assertion_and_signature
self.raw_algorithm = raw_algorithm
+ self.public_cert = public_cert
+ self.private_key = private_key
+ self.pv_key_password = pv_key_password
end
def encoded(signed_message: false, compress: false)
@@ -31,15 +47,15 @@ def raw
build
end
+ private
+
def encode_raw_message(compress)
Base64.strict_encode64(compress ? deflate(raw) : raw)
end
- private :encode_raw_message
def encode_signed_message(compress)
Base64.strict_encode64(compress ? deflate(signed) : signed)
end
- private :encode_signed_message
def build
resp_options = {}
@@ -61,22 +77,17 @@ def build
response << assertion_and_signature
end
end
- private :build
def response_id_string
"_#{response_id}"
end
- alias_method :reference_id, :response_id
- private :response_id_string
def now_iso
Time.now.utc.iso8601
end
- private :now_iso
def deflate(inflated)
Zlib::Deflate.deflate(inflated, 9)[2..-5]
end
- private :deflate
end
end
diff --git a/lib/saml_idp/saml_response.rb b/lib/saml_idp/saml_response.rb
index 85cf48b1..ecda5cfe 100644
--- a/lib/saml_idp/saml_response.rb
+++ b/lib/saml_idp/saml_response.rb
@@ -12,8 +12,9 @@ class SamlResponse
attr_accessor :saml_request_id
attr_accessor :saml_acs_url
attr_accessor :algorithm
- attr_accessor :secret_key
- attr_accessor :x509_certificate
+ attr_accessor :private_key
+ attr_accessor :pv_key_password
+ attr_accessor :public_cert
attr_accessor :authn_context_classref
attr_accessor :expiry
attr_accessor :encryption_opts
@@ -25,23 +26,26 @@ class SamlResponse
attr_accessor :compression_opts
def initialize(
- reference_id,
- response_id,
- issuer_uri,
- principal,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- algorithm,
- authn_context_classref,
- expiry = 60 * 60,
- encryption_opts = nil,
- session_expiry = 0,
- name_id_formats_opts = nil,
- asserted_attributes_opts = nil,
- signed_message_opts = false,
- signed_assertion_opts = true,
- compression_opts = false
+ reference_id:,
+ response_id:,
+ issuer_uri:,
+ principal:,
+ audience_uri:,
+ saml_request_id:,
+ saml_acs_url:,
+ algorithm:,
+ authn_context_classref:,
+ public_cert:,
+ private_key:,
+ pv_key_password:,
+ expiry: 60 * 60,
+ encryption_opts: nil,
+ session_expiry: 0,
+ name_id_formats_opts: nil,
+ asserted_attributes_opts: nil,
+ signed_message_opts: false,
+ signed_assertion_opts: true,
+ compression_opts: false
)
self.reference_id = reference_id
@@ -52,8 +56,9 @@ def initialize(
self.saml_request_id = saml_request_id
self.saml_acs_url = saml_acs_url
self.algorithm = algorithm
- self.secret_key = secret_key
- self.x509_certificate = x509_certificate
+ self.private_key = private_key
+ self.pv_key_password = pv_key_password
+ self.public_cert = public_cert
self.authn_context_classref = authn_context_classref
self.expiry = expiry
self.encryption_opts = encryption_opts
@@ -80,7 +85,8 @@ def signed_assertion
assertion_builder.raw
end
end
- private :signed_assertion
+
+ private
def encoded_message
if signed_message_opts
@@ -89,29 +95,41 @@ def encoded_message
response_builder.encoded(signed_message: false, compress: compression_opts)
end
end
- private :encoded_message
def response_builder
- ResponseBuilder.new(response_id, issuer_uri, saml_acs_url, saml_request_id, signed_assertion, algorithm)
+ ResponseBuilder.new(
+ response_id: response_id,
+ issuer_uri: issuer_uri,
+ saml_acs_url: saml_acs_url,
+ saml_request_id: saml_request_id,
+ assertion_and_signature: signed_assertion,
+ raw_algorithm: algorithm,
+ public_cert: public_cert,
+ private_key: private_key,
+ pv_key_password: pv_key_password,
+ )
end
- private :response_builder
def assertion_builder
@assertion_builder ||=
- AssertionBuilder.new(reference_id || SecureRandom.uuid,
- issuer_uri,
- principal,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- algorithm,
- authn_context_classref,
- expiry,
- encryption_opts,
- session_expiry,
- name_id_formats_opts,
- asserted_attributes_opts)
+ AssertionBuilder.new(
+ reference_id: (reference_id || SecureRandom.uuid),
+ issuer_uri: issuer_uri,
+ principal: principal,
+ audience_uri: audience_uri,
+ saml_request_id: saml_request_id,
+ saml_acs_url: saml_acs_url,
+ raw_algorithm: algorithm,
+ authn_context_classref: authn_context_classref,
+ public_cert: public_cert,
+ private_key: private_key,
+ pv_key_password: pv_key_password,
+ expiry: expiry,
+ encryption_opts: encryption_opts,
+ session_expiry: session_expiry,
+ name_id_formats_opts: name_id_formats_opts,
+ asserted_attributes_opts: asserted_attributes_opts
+ )
end
- private :assertion_builder
end
end
diff --git a/lib/saml_idp/signable.rb b/lib/saml_idp/signable.rb
index 0a330a18..14c923a8 100644
--- a/lib/saml_idp/signable.rb
+++ b/lib/saml_idp/signable.rb
@@ -5,6 +5,7 @@
# * algorithm
require 'saml_idp/signed_info_builder'
require 'saml_idp/signature_builder'
+
module SamlIdp
module Signable
def self.included(base)
@@ -24,6 +25,8 @@ def sign(el)
el << signature if sign?
end
+ private
+
def generated_reference_id
if reference_id
fin = yield reference_id if block_given?
@@ -34,12 +37,10 @@ def generated_reference_id
end
block_given? ? fin : ref
end
- private :generated_reference_id
def reference_id_generator
SamlIdp.config.reference_id_generator
end
- private :reference_id_generator
def with_signature
original = @sign
@@ -48,7 +49,6 @@ def with_signature
@sign = original
end
end
- private :with_signature
def without_signature
original = @sign
@@ -57,49 +57,52 @@ def without_signature
@sign = original
end
end
- private :without_signature
def sign?
!!@sign
end
- private :sign?
def signature
- SignatureBuilder.new(signed_info_builder).raw
+ SignatureBuilder.new(signed_info_builder, get_public_cert).raw
end
- private :signature
def signed_info_builder
- SignedInfoBuilder.new(get_reference_id, get_digest, get_algorithm)
+ SignedInfoBuilder.new(get_reference_id, get_digest, get_algorithm, get_private_key, pv_key_password)
end
- private :signed_info_builder
def get_reference_id
send(self.class.reference_id_method)
end
- private :get_reference_id
def get_digest
without_signature do
send(self.class.digest_method)
end
end
- private :get_digest
def get_algorithm
send(self.class.algorithm_method)
end
- private :get_algorithm
def get_raw
send(self.class.raw_method)
end
- private :get_raw
+
+ def get_public_cert
+ send(self.class.public_cert_method)
+ end
+
+ def get_private_key
+ send(self.class.private_key_method)
+ end
+
+ def pv_key_password
+ send(self.class.pv_key_password_method)
+ end
def noko_raw
Nokogiri::XML::Document.parse(get_raw)
end
- private :noko_raw
def digest
# Make it check for inclusive at some point (https://github.com/onelogin/ruby-saml/blob/master/lib/xml_security.rb#L159)
@@ -111,7 +114,6 @@ def digest
hash = digest_algorithm.digest(canon_hashed_element)
Base64.strict_encode64(hash).gsub(/\n/, '')
end
- private :digest
module ClassMethods
def self.module_method(name, default = nil)
@@ -125,6 +127,9 @@ def self.module_method(name, default = nil)
module_method :digest
module_method :algorithm
module_method :reference_id
+ module_method :public_cert
+ module_method :private_key
+ module_method :pv_key_password
end
end
end
diff --git a/lib/saml_idp/signature_builder.rb b/lib/saml_idp/signature_builder.rb
index 0406715c..fe6e4c39 100644
--- a/lib/saml_idp/signature_builder.rb
+++ b/lib/saml_idp/signature_builder.rb
@@ -1,10 +1,12 @@
require 'builder'
+
module SamlIdp
class SignatureBuilder
- attr_accessor :signed_info_builder
+ attr_accessor :signed_info_builder, :x509_certificate
- def initialize(signed_info_builder)
+ def initialize(signed_info_builder, x509_certificate)
self.signed_info_builder = signed_info_builder
+ self.x509_certificate = x509_certificate
end
def raw
@@ -14,30 +16,31 @@ def raw
signature.tag! "ds:SignatureValue", signature_value
signature.KeyInfo xmlns: "http://www.w3.org/2000/09/xmldsig#" do |key_info|
key_info.tag! "ds:X509Data" do |x509|
- x509.tag! "ds:X509Certificate", x509_certificate
+ x509.tag! "ds:X509Certificate", der_certificate
end
end
end
end
- def x509_certificate
- certificate = SamlIdp.config.x509_certificate.is_a?(Proc) ? SamlIdp.config.x509_certificate.call : SamlIdp.config.x509_certificate
- certificate
- .to_s
- .gsub(/-----BEGIN CERTIFICATE-----/,"")
- .gsub(/-----END CERTIFICATE-----/,"")
- .gsub(/\n/, "")
+ private
+
+ def der_certificate
+ certificate_formatter(x509_certificate)
end
- private :x509_certificate
def signed_info
signed_info_builder.raw
end
- private :signed_info
def signature_value
signed_info_builder.signed
end
- private :signature_value
+
+ def certificate_formatter(pem_certificate)
+ pem_certificate
+ .gsub(/-----BEGIN CERTIFICATE-----/,"")
+ .gsub(/-----END CERTIFICATE-----/,"")
+ .gsub(/\n/, "")
+ end
end
end
diff --git a/lib/saml_idp/signed_info_builder.rb b/lib/saml_idp/signed_info_builder.rb
index 4b0ff224..a858197e 100644
--- a/lib/saml_idp/signed_info_builder.rb
+++ b/lib/saml_idp/signed_info_builder.rb
@@ -22,11 +22,15 @@ class SignedInfoBuilder
attr_accessor :reference_id
attr_accessor :digest_value
attr_accessor :raw_algorithm
+ attr_accessor :private_key
+ attr_accessor :pv_key_password
- def initialize(reference_id, digest_value, raw_algorithm)
+ def initialize(reference_id, digest_value, raw_algorithm, private_key, pv_key_password)
self.reference_id = reference_id
self.digest_value = digest_value
self.raw_algorithm = raw_algorithm
+ self.private_key = private_key
+ self.pv_key_password = pv_key_password
end
def raw
@@ -49,40 +53,27 @@ def signed
encoded.gsub(/\n/, "")
end
+ private
+
def digest_method
DIGEST_METHODS.fetch(clean_algorithm_name, DIGEST_METHODS["sha1"])
end
- private :digest_method
def signature_method
SIGNATURE_METHODS.fetch(clean_algorithm_name, SIGNATURE_METHODS["sha1"])
end
- private :signature_method
def clean_algorithm_name
algorithm_name.to_s.downcase
end
- private :clean_algorithm_name
-
- def secret_key
- SamlIdp.config.secret_key.is_a?(Proc) ? SamlIdp.config.secret_key.call : SamlIdp.config.secret_key
- end
- private :secret_key
-
- def password
- SamlIdp.config.password.is_a?(Proc) ? SamlIdp.config.password.call : SamlIdp.config.password
- end
- private :password
def encoded
- key = OpenSSL::PKey::RSA.new(secret_key, password)
+ key = OpenSSL::PKey::RSA.new(private_key, pv_key_password)
Base64.strict_encode64(key.sign(algorithm.new, raw))
end
- private :encoded
def reference_string
"#_#{reference_id}"
end
- private :reference_string
end
end
diff --git a/spec/lib/saml_idp/assertion_builder_spec.rb b/spec/lib/saml_idp/assertion_builder_spec.rb
index 9e267464..8592cd3f 100644
--- a/spec/lib/saml_idp/assertion_builder_spec.rb
+++ b/spec/lib/saml_idp/assertion_builder_spec.rb
@@ -1,4 +1,6 @@
require 'spec_helper'
+require 'debug'
+
module SamlIdp
describe AssertionBuilder do
let(:reference_id) { "abc" }
@@ -22,16 +24,21 @@ module SamlIdp
let(:session_expiry) { nil }
let(:name_id_formats_opt) { nil }
let(:asserted_attributes_opt) { nil }
+ let(:principal) { Struct.new(:email, :asserted_attributes).new('foo@example.com', { emailAddress: { getter: :email } })}
+
subject { described_class.new(
- reference_id,
- issuer_uri,
- name_id,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- algorithm,
- authn_context_classref,
- expiry
+ reference_id: reference_id,
+ issuer_uri: issuer_uri,
+ principal: name_id,
+ audience_uri: audience_uri,
+ saml_request_id: saml_request_id,
+ saml_acs_url: saml_acs_url,
+ raw_algorithm: algorithm,
+ authn_context_classref: authn_context_classref,
+ public_cert: sp_encrypted_pv_key[:sp_public_cert],
+ private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key],
+ pv_key_password: sp_encrypted_pv_key[:pv_key_password],
+ expiry: expiry
) }
context "No Request ID" do
@@ -70,18 +77,19 @@ module SamlIdp
describe "with principal.asserted_attributes" do
it "delegates attributes to principal" do
- Principal = Struct.new(:email, :asserted_attributes)
- principal = Principal.new('foo@example.com', { emailAddress: { getter: :email } })
builder = described_class.new(
- reference_id,
- issuer_uri,
- principal,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- algorithm,
- authn_context_classref,
- expiry
+ reference_id: reference_id,
+ issuer_uri: issuer_uri,
+ principal: principal,
+ audience_uri: audience_uri,
+ saml_request_id: saml_request_id,
+ saml_acs_url: saml_acs_url,
+ raw_algorithm: algorithm,
+ authn_context_classref: authn_context_classref,
+ public_cert: sp_encrypted_pv_key[:sp_public_cert],
+ private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key],
+ pv_key_password: sp_encrypted_pv_key[:pv_key_password],
+ expiry: expiry
)
Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do
expect(builder.raw).to eq("http://sportngin.comfoo@example.comhttp://example.comurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordfoo@example.com")
@@ -91,16 +99,19 @@ module SamlIdp
it "builds encrypted XML" do
builder = described_class.new(
- reference_id,
- issuer_uri,
- name_id,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- algorithm,
- authn_context_classref,
- expiry,
- encryption_opts
+ reference_id: reference_id,
+ issuer_uri: issuer_uri,
+ principal: name_id,
+ audience_uri: audience_uri,
+ saml_request_id: saml_request_id,
+ saml_acs_url: saml_acs_url,
+ raw_algorithm: algorithm,
+ authn_context_classref: authn_context_classref,
+ public_cert: sp_encrypted_pv_key[:sp_public_cert],
+ private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key],
+ pv_key_password: sp_encrypted_pv_key[:pv_key_password],
+ expiry: expiry,
+ encryption_opts: encryption_opts
)
encrypted_xml = builder.encrypt
expect(encrypted_xml).to_not match(audience_uri)
@@ -118,19 +129,22 @@ module SamlIdp
UserWithUniqueId = Struct.new(:unique_identifier, :email, :asserted_attributes)
principal = UserWithUniqueId.new('unique_identifier_123456', 'foo@example.com', { emailAddress: { getter: :email } })
builder = described_class.new(
- reference_id,
- issuer_uri,
- principal,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- algorithm,
- authn_context_classref,
- expiry,
- encryption_opts,
- session_expiry,
- name_id_formats_opt,
- asserted_attributes_opt
+ reference_id: reference_id,
+ issuer_uri: issuer_uri,
+ principal: principal,
+ audience_uri: audience_uri,
+ saml_request_id: saml_request_id,
+ saml_acs_url: saml_acs_url,
+ raw_algorithm: algorithm,
+ authn_context_classref: authn_context_classref,
+ public_cert: sp_encrypted_pv_key[:sp_public_cert],
+ private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key],
+ pv_key_password: sp_encrypted_pv_key[:pv_key_password],
+ expiry: expiry,
+ encryption_opts: encryption_opts,
+ session_expiry: session_expiry,
+ name_id_formats_opts: name_id_formats_opt,
+ asserted_attributes_opts: asserted_attributes_opt
)
Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do
expect(builder.raw).to eq("http://sportngin.comunique_identifier_123456http://example.comurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordfoo@example.com")
@@ -156,19 +170,22 @@ module SamlIdp
UserWithName = Struct.new(:email, :first_name, :last_name)
principal = UserWithName.new('foo@example.com', 'George', 'Washington')
builder = described_class.new(
- reference_id,
- issuer_uri,
- principal,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- algorithm,
- authn_context_classref,
- expiry,
- encryption_opts,
- session_expiry,
- name_id_formats_opt,
- asserted_attributes_opt
+ reference_id: reference_id,
+ issuer_uri: issuer_uri,
+ principal: principal,
+ audience_uri: audience_uri,
+ saml_request_id: saml_request_id,
+ saml_acs_url: saml_acs_url,
+ raw_algorithm: algorithm,
+ authn_context_classref: authn_context_classref,
+ public_cert: sp_encrypted_pv_key[:sp_public_cert],
+ private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key],
+ pv_key_password: sp_encrypted_pv_key[:pv_key_password],
+ expiry: expiry,
+ encryption_opts: encryption_opts,
+ session_expiry: session_expiry,
+ name_id_formats_opts: name_id_formats_opt,
+ asserted_attributes_opts: asserted_attributes_opt
)
Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do
expect(builder.raw).to eq("http://sportngin.comfoo@example.comhttp://example.comurn:oasis:names:tc:SAML:2.0:ac:classes:PasswordGeorgeWashington")
@@ -185,16 +202,19 @@ module SamlIdp
it "sets default session_expiry from config" do
builder = described_class.new(
- reference_id,
- issuer_uri,
- name_id,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- algorithm,
- authn_context_classref,
- expiry,
- encryption_opts
+ reference_id: reference_id,
+ issuer_uri: issuer_uri,
+ principal: name_id,
+ audience_uri: audience_uri,
+ saml_request_id: saml_request_id,
+ saml_acs_url: saml_acs_url,
+ raw_algorithm: algorithm,
+ authn_context_classref: authn_context_classref,
+ public_cert: sp_encrypted_pv_key[:sp_public_cert],
+ private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key],
+ pv_key_password: sp_encrypted_pv_key[:pv_key_password],
+ expiry: expiry,
+ encryption_opts: encryption_opts
)
expect(builder.session_expiry).to eq(8)
end
@@ -212,19 +232,22 @@ module SamlIdp
UserWithUniqueId = Struct.new(:unique_identifier, :email, :asserted_attributes)
principal = UserWithUniqueId.new('unique_identifier_123456', 'foo@example.com', { emailAddress: { getter: :email } })
builder = described_class.new(
- reference_id,
- issuer_uri,
- principal,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- algorithm,
- authn_context_classref,
- expiry,
- encryption_opts,
- session_expiry,
- name_id_formats_opt,
- asserted_attributes_opt
+ reference_id: reference_id,
+ issuer_uri: issuer_uri,
+ principal: principal,
+ audience_uri: audience_uri,
+ saml_request_id: saml_request_id,
+ saml_acs_url: saml_acs_url,
+ raw_algorithm: algorithm,
+ authn_context_classref: authn_context_classref,
+ public_cert: sp_encrypted_pv_key[:sp_public_cert],
+ private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key],
+ pv_key_password: sp_encrypted_pv_key[:pv_key_password],
+ expiry: expiry,
+ encryption_opts: encryption_opts,
+ session_expiry: session_expiry,
+ name_id_formats_opts: name_id_formats_opt,
+ asserted_attributes_opts: asserted_attributes_opt
)
Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do
expect(builder.raw).to eq("http://sportngin.comunique_identifier_123456http://example.comurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordfoo@example.com")
@@ -250,19 +273,22 @@ module SamlIdp
UserWithName = Struct.new(:email, :first_name, :last_name)
principal = UserWithName.new('foo@example.com', 'George', 'Washington')
builder = described_class.new(
- reference_id,
- issuer_uri,
- principal,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- algorithm,
- authn_context_classref,
- expiry,
- encryption_opts,
- session_expiry,
- name_id_formats_opt,
- asserted_attributes_opt
+ reference_id: reference_id,
+ issuer_uri: issuer_uri,
+ principal: principal,
+ audience_uri: audience_uri,
+ saml_request_id: saml_request_id,
+ saml_acs_url: saml_acs_url,
+ raw_algorithm: algorithm,
+ authn_context_classref: authn_context_classref,
+ public_cert: sp_encrypted_pv_key[:sp_public_cert],
+ private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key],
+ pv_key_password: sp_encrypted_pv_key[:pv_key_password],
+ expiry: expiry,
+ encryption_opts: encryption_opts,
+ session_expiry: session_expiry,
+ name_id_formats_opts: name_id_formats_opt,
+ asserted_attributes_opts: asserted_attributes_opt
)
Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do
expect(builder.raw).to eq("http://sportngin.comfoo@example.comhttp://example.comurn:oasis:names:tc:SAML:2.0:ac:classes:PasswordGeorgeWashington")
diff --git a/spec/lib/saml_idp/configurator_spec.rb b/spec/lib/saml_idp/configurator_spec.rb
index 80da3b14..59c399a8 100644
--- a/spec/lib/saml_idp/configurator_spec.rb
+++ b/spec/lib/saml_idp/configurator_spec.rb
@@ -20,11 +20,11 @@ module SamlIdp
it { should respond_to :logger }
it "has a valid x509_certificate" do
- expect(subject.x509_certificate.call).to eq(Default::X509_CERTIFICATE)
+ expect(subject.x509_certificate).to eq(Default::X509_CERTIFICATE)
end
it "has a valid secret_key" do
- expect(subject.secret_key.call).to eq(Default::SECRET_KEY)
+ expect(subject.secret_key).to eq(Default::SECRET_KEY)
end
it "has a valid algorithm" do
diff --git a/spec/lib/saml_idp/logout_request_builder_spec.rb b/spec/lib/saml_idp/logout_request_builder_spec.rb
index 73f0a626..26890159 100644
--- a/spec/lib/saml_idp/logout_request_builder_spec.rb
+++ b/spec/lib/saml_idp/logout_request_builder_spec.rb
@@ -19,11 +19,13 @@ module SamlIdp
subject do
described_class.new(
- response_id,
- issuer_uri,
- saml_slo_url,
- name_id,
- algorithm
+ response_id: response_id,
+ issuer_uri: issuer_uri,
+ saml_slo_url: saml_slo_url,
+ name_id: name_id,
+ algorithm: algorithm,
+ public_cert: SamlIdp::Default::X509_CERTIFICATE,
+ private_key: SamlIdp::Default::SECRET_KEY
)
end
diff --git a/spec/lib/saml_idp/logout_response_builder_spec.rb b/spec/lib/saml_idp/logout_response_builder_spec.rb
index a4ca7bfd..44f730dd 100644
--- a/spec/lib/saml_idp/logout_response_builder_spec.rb
+++ b/spec/lib/saml_idp/logout_response_builder_spec.rb
@@ -19,11 +19,13 @@ module SamlIdp
subject do
described_class.new(
- response_id,
- issuer_uri,
- saml_slo_url,
- request_id,
- algorithm
+ response_id: response_id,
+ issuer_uri: issuer_uri,
+ saml_slo_url: saml_slo_url,
+ saml_request_id: request_id,
+ algorithm: algorithm,
+ public_cert: SamlIdp::Default::X509_CERTIFICATE,
+ private_key: SamlIdp::Default::SECRET_KEY
)
end
diff --git a/spec/lib/saml_idp/response_builder_spec.rb b/spec/lib/saml_idp/response_builder_spec.rb
index 9105eede..ce5224e8 100644
--- a/spec/lib/saml_idp/response_builder_spec.rb
+++ b/spec/lib/saml_idp/response_builder_spec.rb
@@ -8,12 +8,15 @@ module SamlIdp
let(:assertion_and_signature) { "http://sportngin.comstuffjon.phenow@sportngin.comhttp://example.comjon.phenow@sportngin.comurn:federation:authentication:windows" }
let(:algorithm) { :sha256 }
subject { described_class.new(
- response_id,
- issuer_uri,
- saml_acs_url,
- saml_request_id,
- assertion_and_signature,
- algorithm
+ response_id: response_id,
+ issuer_uri: issuer_uri,
+ saml_acs_url: saml_acs_url,
+ saml_request_id: saml_request_id,
+ assertion_and_signature: assertion_and_signature,
+ raw_algorithm: algorithm,
+ public_cert: sp_encrypted_pv_key[:sp_public_cert],
+ private_key: sp_encrypted_pv_key[:sp_encrypted_pv_key],
+ pv_key_password: sp_encrypted_pv_key[:pv_key_password],
) }
before do
diff --git a/spec/lib/saml_idp/saml_response_spec.rb b/spec/lib/saml_idp/saml_response_spec.rb
index b79f8a2b..f702054c 100644
--- a/spec/lib/saml_idp/saml_response_spec.rb
+++ b/spec/lib/saml_idp/saml_response_spec.rb
@@ -28,43 +28,50 @@ module SamlIdp
let(:unsigned_response_opts) { false }
let(:signed_assertion_opts) { true }
let(:compress_opts) { false }
- let(:subject_encrypted) { described_class.new(reference_id,
- response_id,
- issuer_uri,
- name_id,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- algorithm,
- authn_context_classref,
- expiry,
- encryption_opts,
- session_expiry,
- nil,
- nil,
- unsigned_response_opts,
- signed_assertion_opts,
- compress_opts
+ let(:subject_encrypted) { described_class.new(
+ reference_id: reference_id,
+ response_id: response_id,
+ issuer_uri: issuer_uri,
+ principal: name_id,
+ audience_uri: audience_uri,
+ saml_request_id: saml_request_id,
+ saml_acs_url: saml_acs_url,
+ algorithm: algorithm,
+ authn_context_classref: authn_context_classref,
+ public_cert: x509_certificate,
+ private_key: secret_key,
+ pv_key_password: nil,
+ expiry: expiry,
+ encryption_opts: encryption_opts,
+ session_expiry: session_expiry,
+ name_id_formats_opts: nil,
+ asserted_attributes_opts: nil,
+ signed_message_opts: unsigned_response_opts,
+ signed_assertion_opts: signed_assertion_opts,
+ compression_opts: compress_opts
)
}
- subject { described_class.new(reference_id,
- response_id,
- issuer_uri,
- name_id,
- audience_uri,
- saml_request_id,
- saml_acs_url,
- algorithm,
- authn_context_classref,
- expiry,
- nil,
- session_expiry,
- nil,
- nil,
- signed_response_opts,
- signed_assertion_opts,
- compress_opts
+ subject { described_class.new(reference_id: reference_id,
+ response_id: response_id,
+ issuer_uri: issuer_uri,
+ principal: name_id,
+ audience_uri: audience_uri,
+ saml_request_id: saml_request_id,
+ saml_acs_url: saml_acs_url,
+ algorithm: algorithm,
+ authn_context_classref: authn_context_classref,
+ public_cert: x509_certificate,
+ private_key: secret_key,
+ pv_key_password: nil,
+ expiry: expiry,
+ encryption_opts: nil,
+ session_expiry: session_expiry,
+ name_id_formats_opts: nil,
+ asserted_attributes_opts: nil,
+ signed_message_opts: signed_response_opts,
+ signed_assertion_opts: signed_assertion_opts,
+ compression_opts: compress_opts
)
}
diff --git a/spec/lib/saml_idp/signable_spec.rb b/spec/lib/saml_idp/signable_spec.rb
index cd9a90ae..0d033780 100644
--- a/spec/lib/saml_idp/signable_spec.rb
+++ b/spec/lib/saml_idp/signable_spec.rb
@@ -1,7 +1,9 @@
# encoding: utf-8
require 'spec_helper'
+
class MockSignable
include SamlIdp::Signable
+ include SecurityHelpers
def raw
builder = Builder::XmlMarkup.new
@@ -21,6 +23,18 @@ def digest
def algorithm
OpenSSL::Digest::SHA1
end
+
+ def private_key
+ sp_encrypted_pv_key[:sp_encrypted_pv_key]
+ end
+
+ def pv_key_password
+ sp_encrypted_pv_key[:pv_key_password]
+ end
+
+ def public_cert
+ sp_encrypted_pv_key[:sp_public_cert]
+ end
end
module SamlIdp
@@ -72,6 +86,5 @@ module SamlIdp
it "has a valid signed" do
expect(subject.signed).to match all_regex
end
-
end
end
diff --git a/spec/lib/saml_idp/signature_builder_spec.rb b/spec/lib/saml_idp/signature_builder_spec.rb
index ff28575a..8fe612b2 100644
--- a/spec/lib/saml_idp/signature_builder_spec.rb
+++ b/spec/lib/saml_idp/signature_builder_spec.rb
@@ -5,7 +5,8 @@ module SamlIdp
let(:raw_info) { "em8csGAWynywpe8S4nN64o56/4DosXi2XWMY6RJ6YfA=" }
let(:signed_info) { double raw: raw_info, signed: signed }
subject { described_class.new(
- signed_info
+ signed_info,
+ SamlIdp::Default::X509_CERTIFICATE
) }
before do
diff --git a/spec/lib/saml_idp/signed_info_builder_spec.rb b/spec/lib/saml_idp/signed_info_builder_spec.rb
index 4685d39a..0ac39966 100644
--- a/spec/lib/saml_idp/signed_info_builder_spec.rb
+++ b/spec/lib/saml_idp/signed_info_builder_spec.rb
@@ -1,4 +1,5 @@
require 'spec_helper'
+
module SamlIdp
describe SignedInfoBuilder do
let(:reference_id) { "abc" }
@@ -7,7 +8,9 @@ module SamlIdp
subject { described_class.new(
reference_id,
digest,
- algorithm
+ algorithm,
+ sp_encrypted_pv_key[:sp_encrypted_pv_key],
+ sp_encrypted_pv_key[:pv_key_password]
) }
before do
@@ -19,7 +22,7 @@ module SamlIdp
end
it "builds a legit digest of the XML file" do
- expect(subject.signed).to eq("hKLeWLRgatHcV6N5Fc8aKveqNp6Y/J4m2WSYp0awGFtsCTa/2nab32wI3du+3kuuIy59EDKeUhHVxEfyhoHUo6xTZuO2N7XcTpSonuZ/CB3WjozC2Q/9elss3z1rOC3154v5pW4puirLPRoG+Pwi8SmptxNRHczr6NvmfYmmGfo=")
+ expect(subject.signed).to eq("YP2e6cTEfRj1vI1/gaaSApLAMxPBQzyuBvbvulbS99x17LCLDSKvqA6MyU4WLavmVba5qiF88e97f0XKLsse7gEGOfnF/6jaRV3fePXk6+LFaeYUHZ11u7PkZ1/ucO459ASsuPN/9P9xCY2t+jtVKvIrcSZQbomymfsWGt9P/oY83elKU712aAwqcfvINsa1N+RefZRwdAW4ATBwwcDjE3VTR6mKOyGMsPJ4HQcPrNiEmuwd1QaPH0H1LLzxtewGQGmIL2UqNE/QMe/kKiSTFZ0loBKuSEc9WBw5XuH31QxbzpLJjqM/C1qy4aykPqDUuJtQ4csx78GgfFS4uiqowg==")
end
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index ffc9f9a8..61819b77 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -17,6 +17,7 @@
require 'ruby-saml'
require 'saml_idp'
require 'timecop'
+require 'debug'
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
diff --git a/spec/support/certificates/sp_encrypted_pv_key.pem b/spec/support/certificates/sp_encrypted_pv_key.pem
new file mode 100644
index 00000000..2fecdc96
--- /dev/null
+++ b/spec/support/certificates/sp_encrypted_pv_key.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,89BFDC1035C5C7A2277D87B8F0763A70
+
+9Tpy80djhnb8S7Xq7O94TkH6ec38gO54JWbMbC3xTtVnR8lqvX6kIeF5gLjbySUI
+Q30F+1bZ1/AiT1PeJ9Mg+TUEFDxiNrRw+liS3F6mhM5XyGe96FVOGEKp+WbCEznV
+ZgLzzMXXwcAzKblsVNAiBAozqyfdhyGg/BhTcPXpAXt3wxy4VfbwHs1CW5+Ar+iN
+qlYXDFyg+UPh0EbKQc7FUB6NKcgZ76yuaWQlkUfAbBjx4f7zpHSwYO29Gv2Hq/E4
+REhS4GXuJDTZLSDW3n6TcOszyudVYNSNFEjDWtc88/l3gQW5ZtJVnLarNMOfQF48
+MFFQBT/ksT/9GbCIKOonr12D+XlGgHJpNJrHQ+Hzee3sU8U4tn2/4sM2ZMrjOiMh
+giuJq1OiM95ohK3XcdcE5apbMtCTzBjcwumG6MaI/okQURHuHvMvdhivhp5CC1Ix
+dRx9cnCmXidEdhsgKBq5vBvcqt4VJqqkaGEA0YBAge//LZbzc1fp8Ghzjdev78Sb
+SeW/QnzGTPW4FX/UMLrZPuwNpx9fJ1pJdI8UOOWBxIBkvl+1dM9WOVP+07b80RO1
+rJm+QKZVEbrHZKX8Gq3+DyvI2a+FUWv0WTDxp4fcPMAGy+Kr8Xratxh/fQhvksbV
+ZK6/m/8f97zfxsUU5tM0B+WwIv6/KQm3wwloeL226OgmBX8x+WKthFe+MozchVLI
+UNvXCw5NeGmIbLWlcoZuzsvHHcfNJ/iDaBLl6itJxd1sNiuamTHfpTQlxoDCwaQO
+OqRRMfq8pjEgHYXHMm0us3sQ235yN5W32K2N79YlTQOQUA9QYHLlpmMvVRtOSRQY
+GNhIPNWqLWP7+CAtfXVA0o97p5Wd0ySWwOcv3iJuAxywBg0a6s6iYV2lkRHHkJY2
+dvDH39hbaqRakPUKFOPkCHdHvN+cM7trvdxpzURj67u9IKLPMwK64FJ3LEerqSgh
+FIcwTcN8jQBLdcsi9XHNPRJEaa+4Sf7KpeUYe79yZlFNDKU6yG8DMpt2uJ6p17C7
+R2L11AdsPC0MAgxaj2yNV1/CSP3wc6Y36AMSnRJtMsUX7BjZT6TSUjOj21zPfu9R
+h2aJYe1224EpT6bb31Sgfky2TcIOXAY60g8slRLniCDzmexB6u/EUvF7A4fYXFRK
+pgcbWVAfYr1/GqXs9srLLAeYRbFcg6aaTD63uTe0rf/Vse5h7c9tmMZ6/Wk/rkwQ
+oguzl8rXvXd2mpJdhvT/NDI2AI6jzIDcCb/F21qlyfEk8K5Rlykm8BDoRNx6+wW/
+SuUZfnXJmywovvpRSsEaGTYo/3eERZVdIZqV5nLHVJtcTRzvh3QuCm2JC8S1HNHE
+PboWwv1BHZOR9/llB/voip+DJuIGkBVwbN9mDUC+uf7L/y6Xj8kOvI7g3zaJR/ac
+t2YjhgL3sxORZp8lIsYlwZYHT39jGkYP4Pi1HoVWH1sKyn+P55nF8f9BrQCmhyFU
+t1K+p2AwzuWxYw6YThQYy2SdiGSaZ9axGrwlu1kdh9Vq2YDctXX+yR1Bs3DytK/6
+PzdLSUAJt4HoLCND+lXG8Ii79WWTCqX9UrYWTJN4PhApCnN+/RYft2Bjd8ZGl0E2
+-----END RSA PRIVATE KEY-----
diff --git a/spec/support/certificates/sp_public_cert.pem b/spec/support/certificates/sp_public_cert.pem
new file mode 100644
index 00000000..02bea35a
--- /dev/null
+++ b/spec/support/certificates/sp_public_cert.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICjTCCAXWgAwIBAgIVAOTwdQ89937l4RyuaJ7Ni1K2YifEMA0GCSqGSIb3DQEB
+CwUAMAAwHhcNMjQxMTAxMjIyMzQ4WhcNMzQxMTAxMjIyMzQ4WjAAMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1Ddn+u21iDGHHcLLsThAgdAXLnvL8Pqi
+aXKu+MoMu2LYu/pHPk6ZuCmecdM6Tsqdc69S1fCJGu45zSbSuQNzZnW+iLItzBYj
+WWv5cgQdOTkT6WVUBsA7NU9sKKmCqsU/3DOCXbZ8OYPxnftZGRIZdydsENOG49f6
+195VJ7h3FybXUnqpaw+bO+pepl4UNl6Y6nIKv4eZnAXJ8P7sJX2iHiu5zl2y/eht
+rrL9faNdiSdb2wERkcIZKDrnoGlTvxkFd7fr7sIHIIJvxCBvBpBrgSNfQrHtqjsG
+STQ4IK1f5Vtwy8jVkuK+SBEzA+Ft6IlWDkTW3oTnFgVjwwOv0NQdNwIDAQABMA0G
+CSqGSIb3DQEBCwUAA4IBAQC2nUkoFXCBVvmkJ9iwXnmJwTGPuDFlZh0zVAuDnVCi
+DAcb5z+96GV1dPucFGP/0dtSVazHw3bpw1b9sm1844ne11XjU6PFGEkVAbAyA72Z
+Vi0t+ksEVlXP044XjSvZLuWnETJU31w8MjUcoi4BUhdlPtgqYd5jWMSKTncpZCmp
+zggCKpz6tSpJcBl7kBAudcxP3kCrWNku5V1OW/4Z4A27ISJLE+Gzi2Q+O/lKHydr
+ebXtjQpuuCuMnNwWaLRnxQaQWmYdbVvCuXIweoC6pSPffwjbMpU4ZTpHn1UoPqUQ
+9JfW50G2IUKQjq9ssjZAKcGsQIRAIwzwWLvNtl62OeoK
+-----END CERTIFICATE-----
diff --git a/spec/support/security_helpers.rb b/spec/support/security_helpers.rb
index f6952ce7..93b57391 100644
--- a/spec/support/security_helpers.rb
+++ b/spec/support/security_helpers.rb
@@ -68,4 +68,12 @@ def sp_pv_key
def sp_x509_cert
@sp_x509_cert ||= File.read(File.join(File.dirname(__FILE__), 'certificates', 'sp_x509_cert.crt'))
end
+
+ def sp_encrypted_pv_key
+ @sp_encrypted_pv_key ||= {
+ sp_encrypted_pv_key: File.read(File.join(File.dirname(__FILE__), 'certificates', 'sp_encrypted_pv_key.pem')),
+ sp_public_cert: File.read(File.join(File.dirname(__FILE__), 'certificates', 'sp_public_cert.pem')),
+ pv_key_password: 'dccf0b7614b554fbe16b0f31'
+ }
+ end
end