Skip to content

Commit

Permalink
Specs
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnyshields committed Nov 25, 2023
1 parent d222ced commit 299047d
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* [#673](https://github.com/SAML-Toolkits/ruby-saml/pull/673) Support multiple simultaneous SP decryption keys via `Settings#sp_cert_multi` parameter.
* [#673](https://github.com/SAML-Toolkits/ruby-saml/pull/673) Deprecate `Settings#certificate_new` parameter.
* [#673](https://github.com/SAML-Toolkits/ruby-saml/pull/673) `:check_sp_cert_expiration` will use the first non-expired certificate/key when signing/decrypting. It will raise an error only if there are no valid certificates/keys.
* [#673](https://github.com/SAML-Toolkits/ruby-saml/pull/673) `:check_sp_cert_expiration` now validates the certificate `not_before` condition; previously it was only validating `not_after`.

### 1.16.0 (Oct 09, 2023)
* [#671](https://github.com/SAML-Toolkits/ruby-saml/pull/671) Add support on LogoutRequest with Encrypted NameID
Expand Down
6 changes: 4 additions & 2 deletions lib/onelogin/ruby-saml/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -266,13 +266,14 @@ def self.status_error_msg(error_msg, raw_status_code = nil, status_message = nil
error_msg
end


# Obtains the decrypted string from an Encrypted node element in XML,
# given multiple private keys to try.
# @param encrypted_node [REXML::Element] The Encrypted element
# @param private_keys [Array<OpenSSL::PKey::RSA>] The Service provider private key
# @return [String] The decrypted data
def self.decrypt_multi(encrypted_node, private_keys)
raise ArgumentError.new('private_keys must be specified') if !private_keys || private_keys.empty?

error = nil
private_keys.each do |key|
begin
Expand All @@ -281,7 +282,8 @@ def self.decrypt_multi(encrypted_node, private_keys)
error ||= e
end
end
raise error

raise(error) if error
end

# Obtains the decrypted string from an Encrypted node element in XML
Expand Down
95 changes: 91 additions & 4 deletions test/utils_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ def result(duration, reference = 0)
invalid_chained_certificate1 = read_certificate("invalid_chained_certificate1")
assert_equal formatted_chained_certificate, OneLogin::RubySaml::Utils.format_cert(invalid_chained_certificate1)
end

end

describe ".format_private_key" do
Expand Down Expand Up @@ -151,7 +150,49 @@ def result(duration, reference = 0)
end
end

describe "build_query" do
describe '.build_cert_object' do
it 'returns a certificate object for valid certificate string' do
cert_object = OneLogin::RubySaml::Utils.build_cert_object(ruby_saml_cert_text)
assert_instance_of OpenSSL::X509::Certificate, cert_object
end

it 'returns nil for nil certificate string' do
assert_nil OneLogin::RubySaml::Utils.build_cert_object(nil)
end

it 'returns nil for empty certificate string' do
assert_nil OneLogin::RubySaml::Utils.build_cert_object('')
end

it 'raises error when given an invalid certificate string' do
assert_raises OpenSSL::X509::CertificateError do
OneLogin::RubySaml::Utils.build_cert_object('Foobar')
end
end
end

describe '.build_private_key_object' do
it 'returns a private key object for valid private key string' do
private_key_object = OneLogin::RubySaml::Utils.build_private_key_object(ruby_saml_key_text)
assert_instance_of OpenSSL::PKey::RSA, private_key_object
end

it 'returns nil for nil private key string' do
assert_nil OneLogin::RubySaml::Utils.build_private_key_object(nil)
end

it 'returns nil for empty private key string' do
assert_nil OneLogin::RubySaml::Utils.build_private_key_object('')
end

it 'raises error when given an invalid private key string' do
assert_raises OpenSSL::PKey::RSAError do
OneLogin::RubySaml::Utils.build_private_key_object('Foobar')
end
end
end

describe ".build_query" do
it "returns the query string" do
params = {}
params[:type] = "SAMLRequest"
Expand All @@ -163,7 +204,7 @@ def result(duration, reference = 0)
end
end

describe "#verify_signature" do
describe ".verify_signature" do
before do
@params = {}
@params[:cert] = ruby_saml_cert
Expand All @@ -182,7 +223,7 @@ def result(duration, reference = 0)
end
end

describe "#status_error_msg" do
describe ".status_error_msg" do
it "returns a error msg with status_code and status message" do
error_msg = "The status code of the Logout Response was not Success"
status_code = "urn:oasis:names:tc:SAML:2.0:status:Requester"
Expand Down Expand Up @@ -301,7 +342,53 @@ def result(duration, reference = 0)
element = REXML::Document.new('<element></element>').elements.first
assert_equal '', OneLogin::RubySaml::Utils.element_text(element)
end
end

describe '.decrypt_multi' do
let(:private_key) { ruby_saml_key }
let(:invalid_key1) { OpenSSL::PKey::RSA.new(1024) }
let(:invalid_key2) { OpenSSL::PKey::RSA.new(1024) }
let(:settings) { OneLogin::RubySaml::Settings.new(:private_key => private_key.to_pem) }
let(:response) { OneLogin::RubySaml::Response.new(signed_message_encrypted_unsigned_assertion, :settings => settings) }
let(:encrypted) do
REXML::XPath.first(
response.document,
"(/p:Response/EncryptedAssertion/)|(/p:Response/a:EncryptedAssertion/)",
{ "p" => "urn:oasis:names:tc:SAML:2.0:protocol", "a" => "urn:oasis:names:tc:SAML:2.0:assertion" }
)
end

it 'successfully decrypts with the first private key' do
assert_match /\A<saml:Assertion/, OneLogin::RubySaml::Utils.decrypt_multi(encrypted, [private_key])
end

it 'successfully decrypts with a subsequent private key' do
assert_match /\A<saml:Assertion/, OneLogin::RubySaml::Utils.decrypt_multi(encrypted, [invalid_key1, private_key])
end

it 'raises an error when there is only one key and it fails to decrypt' do
assert_raises OpenSSL::PKey::PKeyError do
OneLogin::RubySaml::Utils.decrypt_multi(encrypted, [invalid_key1])
end
end

it 'raises an error when all keys fail to decrypt' do
assert_raises OpenSSL::PKey::PKeyError do
OneLogin::RubySaml::Utils.decrypt_multi(encrypted, [invalid_key1, invalid_key2])
end
end

it 'raises an error when private keys is an empty array' do
assert_raises ArgumentError do
OneLogin::RubySaml::Utils.decrypt_multi(encrypted, [])
end
end

it 'raises an error when private keys is nil' do
assert_raises ArgumentError do
OneLogin::RubySaml::Utils.decrypt_multi(encrypted, [])
end
end
end
end
end

0 comments on commit 299047d

Please sign in to comment.