diff --git a/CHANGELOG.md b/CHANGELOG.md index af816e5b..1dad6457 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * [#685](https://github.com/SAML-Toolkits/ruby-saml/pull/685) Create namespace alias `OneLogin = Object` for backward compatibility, to be removed in version `2.1.0`. * [#685](https://github.com/SAML-Toolkits/ruby-saml/pull/685) Change directly structure from `lib/onelogin/ruby-saml` to `lib/ruby_saml`. * [#685](https://github.com/SAML-Toolkits/ruby-saml/pull/685) Move schema files from `lib/onelogin/schemas` to `lib/ruby_saml/schemas`. +* [#686](https://github.com/SAML-Toolkits/ruby-saml/pull/686) Use SHA-256 as the default hashing algorithm everywhere instead of SHA-1, including signatures, fingerprints, and digests. * [#689](https://github.com/SAML-Toolkits/ruby-saml/pull/689) Remove `settings.compress_request` and `settings.compess_response` parameters. ### 1.17.0 diff --git a/README.md b/README.md index 9d037ae1..9aed3671 100644 --- a/README.md +++ b/README.md @@ -200,7 +200,7 @@ def saml_settings settings.idp_slo_service_url = "https://app.onelogin.com/trust/saml2/http-redirect/slo/#{OneLoginAppId}" settings.idp_slo_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" # or :post, :redirect settings.idp_cert_fingerprint = OneLoginAppCertFingerPrint - settings.idp_cert_fingerprint_algorithm = "http://www.w3.org/2000/09/xmldsig#sha1" + settings.idp_cert_fingerprint_algorithm = "http://www.w3.org/2000/09/xmldsig#sha256" settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" # Optional for most SAML IdPs diff --git a/UPGRADING.md b/UPGRADING.md index 13362ee1..bc011908 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -2,13 +2,13 @@ ## Updating from 1.17.x to 2.0.0 -### Before Upgrading +### Before upgrading Before attempting to upgrade to `2.0.0`: - Upgrade your project to minimum Ruby 3.0, JRuby 9.4, or TruffleRuby 22. - Upgrade RubySaml to `1.17.x`. Note that RubySaml `1.17.x` is compatible with up to Ruby 3.3. -### Root Namespace Changed to RubySaml +### Root namespace changed to RubySaml RubySaml version `2.0.0` changes the root namespace from `OneLogin::RubySaml::` to just `RubySaml::`. This will require you to search your codebase for the string `OneLogin::` and remove it as appropriate. Aside from this namespace change, @@ -17,6 +17,24 @@ the class names themselves have intentionally been kept the same. For backward compatibility, the alias `OneLogin = Object` has been set, so `OneLogin::RubySaml::` will still work. This alias will be removed in RubySaml version `2.1.0`. +### Security: Change default hashing algorithm to SHA-256 (was SHA-1) + +For security reasons, RubySaml version `2.0.0` uses SHA-256 as its default hashing algorithm everywhere +instead of the now-obsolete SHA-1. This affects: +- The default signature and digest algorithms used when generating SP metadata. +- The default signature algorithm used when generating SP messages such as AuthnRequests. +- The default fingerprint of IdP metadata (`:idp_cert_fingerprint` as generated by `RubySaml::IdpMetadataParser`) + +To preserve the old insecure SHA-1 behavior *(not recommended)*, you may set `RubySaml::Settings` as follows: + +```ruby +# Preserve RubySaml 1.x insecure SHA-1 behavior +settings = RubySaml::Settings.new +settings.idp_cert_fingerprint_algorithm = XMLSecurity::Document::SHA1 +settings.security[:digest_method] = XMLSecurity::Document::SHA1 +settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1 +``` + ### Removal of Compression Settings The `settings.compress_request` and `settings.compress_response` parameters have been removed. diff --git a/lib/ruby_saml/idp_metadata_parser.rb b/lib/ruby_saml/idp_metadata_parser.rb index 0c2443d5..270137fa 100644 --- a/lib/ruby_saml/idp_metadata_parser.rb +++ b/lib/ruby_saml/idp_metadata_parser.rb @@ -376,7 +376,7 @@ def certificates # @return [String|nil] the fingerpint of the X509Certificate if it exists # - def fingerprint(certificate, fingerprint_algorithm = XMLSecurity::Document::SHA1) + def fingerprint(certificate, fingerprint_algorithm = XMLSecurity::Document::SHA256) @fingerprint ||= begin return unless certificate diff --git a/lib/ruby_saml/settings.rb b/lib/ruby_saml/settings.rb index 37103951..e0fad2f4 100644 --- a/lib/ruby_saml/settings.rb +++ b/lib/ruby_saml/settings.rb @@ -275,7 +275,7 @@ def get_binding(value) DEFAULTS = { assertion_consumer_service_binding: Utils::BINDINGS[:post], single_logout_service_binding: Utils::BINDINGS[:redirect], - idp_cert_fingerprint_algorithm: XMLSecurity::Document::SHA1, + idp_cert_fingerprint_algorithm: XMLSecurity::Document::SHA256, message_max_bytesize: 250_000, soft: true, double_quote_xml_attribute_values: false, @@ -288,8 +288,8 @@ def get_binding(value) want_name_id: false, metadata_signed: false, embed_sign: false, # Deprecated - digest_method: XMLSecurity::Document::SHA1, - signature_method: XMLSecurity::Document::RSA_SHA1, + digest_method: XMLSecurity::Document::SHA256, + signature_method: XMLSecurity::Document::RSA_SHA256, check_idp_cert_expiration: false, check_sp_cert_expiration: false, strict_audience_validation: false, diff --git a/lib/xml_security.rb b/lib/xml_security.rb index ea3354a8..fb791d42 100644 --- a/lib/xml_security.rb +++ b/lib/xml_security.rb @@ -71,11 +71,11 @@ def algorithm(element) algorithm = algorithm && algorithm =~ /(rsa-)?sha(.*?)$/i && ::Regexp.last_match(2).to_i case algorithm - when 256 then OpenSSL::Digest::SHA256 + when 1 then OpenSSL::Digest::SHA1 when 384 then OpenSSL::Digest::SHA384 when 512 then OpenSSL::Digest::SHA512 else - OpenSSL::Digest::SHA1 + OpenSSL::Digest::SHA256 end end @@ -114,7 +114,7 @@ def uuid # # # - def sign_document(private_key, certificate, signature_method = RSA_SHA1, digest_method = SHA1) + def sign_document(private_key, certificate, signature_method = RSA_SHA256, digest_method = SHA256) noko = Nokogiri::XML(to_s) do |config| config.options = XMLSecurity::BaseDocument::NOKOGIRI_OPTIONS end @@ -216,7 +216,7 @@ def validate_document(idp_cert_fingerprint, soft = true, options = {}) if options[:fingerprint_alg] fingerprint_alg = XMLSecurity::BaseDocument.new.algorithm(options[:fingerprint_alg]).new else - fingerprint_alg = OpenSSL::Digest.new('SHA1') + fingerprint_alg = OpenSSL::Digest.new('SHA256') end fingerprint = fingerprint_alg.hexdigest(cert.to_der) diff --git a/test/idp_metadata_parser_test.rb b/test/idp_metadata_parser_test.rb index c616c299..860aecce 100644 --- a/test/idp_metadata_parser_test.rb +++ b/test/idp_metadata_parser_test.rb @@ -26,7 +26,7 @@ def initialize; end assert_equal "https://hello.example.com/access/saml/idp.xml", settings.idp_entity_id assert_equal "https://hello.example.com/access/saml/login", settings.idp_sso_service_url assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", settings.idp_sso_service_binding - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", settings.idp_cert_fingerprint assert_equal "https://hello.example.com/access/saml/logout", settings.idp_slo_service_url assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", settings.idp_slo_service_binding assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified", settings.name_identifier_format @@ -38,7 +38,7 @@ def initialize; end idp_metadata_parser = RubySaml::IdpMetadataParser.new idp_metadata = idp_metadata_descriptor settings = idp_metadata_parser.parse(idp_metadata) - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", settings.idp_cert_fingerprint end it "extract certificate from md:KeyDescriptor[@use='encryption']" do @@ -46,7 +46,7 @@ def initialize; end idp_metadata = idp_metadata_descriptor idp_metadata = idp_metadata.sub(/(.*?)<\/md:KeyDescriptor>/m, "") settings = idp_metadata_parser.parse(idp_metadata) - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", settings.idp_cert_fingerprint end it "extract certificate from md:KeyDescriptor" do @@ -55,7 +55,7 @@ def initialize; end idp_metadata = idp_metadata.sub(/(.*?)<\/md:KeyDescriptor>/m, "") idp_metadata = idp_metadata.sub('', '') settings = idp_metadata_parser.parse(idp_metadata) - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", settings.idp_cert_fingerprint end it "extract SSO endpoint with no specific binding, it takes the first" do @@ -162,7 +162,7 @@ def initialize; end } } }) - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", settings.idp_cert_fingerprint assert_equal XMLSecurity::Document::SHA256, settings.security[:digest_method] assert_equal XMLSecurity::Document::RSA_SHA256, settings.security[:signature_method] end @@ -175,7 +175,7 @@ def initialize; end RubySaml::IdpMetadataParser.new.parse(idp_metadata_descriptor, :settings => settings) - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", settings.idp_cert_fingerprint assert_equal XMLSecurity::Document::SHA256, settings.security[:digest_method] assert_equal XMLSecurity::Document::RSA_SHA256, settings.security[:signature_method] end @@ -190,7 +190,7 @@ def initialize; end assert_equal "https://hello.example.com/access/saml/idp.xml", metadata[:idp_entity_id] assert_equal "https://hello.example.com/access/saml/login", metadata[:idp_sso_service_url] assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", metadata[:idp_sso_service_binding] - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", metadata[:idp_cert_fingerprint] + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", metadata[:idp_cert_fingerprint] assert_equal "https://hello.example.com/access/saml/logout", metadata[:idp_slo_service_url] assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", metadata[:idp_slo_service_binding] assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified", metadata[:name_identifier_format] @@ -202,7 +202,7 @@ def initialize; end idp_metadata_parser = RubySaml::IdpMetadataParser.new idp_metadata = idp_metadata_descriptor metadata = idp_metadata_parser.parse_to_hash(idp_metadata) - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", metadata[:idp_cert_fingerprint] + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", metadata[:idp_cert_fingerprint] end it "extract certificate from md:KeyDescriptor[@use='encryption']" do @@ -210,7 +210,7 @@ def initialize; end idp_metadata = idp_metadata_descriptor idp_metadata = idp_metadata.sub(/(.*?)<\/md:KeyDescriptor>/m, "") parsed_metadata = idp_metadata_parser.parse_to_hash(idp_metadata) - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", parsed_metadata[:idp_cert_fingerprint] + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", parsed_metadata[:idp_cert_fingerprint] end it "extract certificate from md:KeyDescriptor" do @@ -219,7 +219,7 @@ def initialize; end idp_metadata = idp_metadata.sub(/(.*?)<\/md:KeyDescriptor>/m, "") idp_metadata = idp_metadata.sub('', '') parsed_metadata = idp_metadata_parser.parse_to_hash(idp_metadata) - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", parsed_metadata[:idp_cert_fingerprint] + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", parsed_metadata[:idp_cert_fingerprint] end it "extract SSO endpoint with no specific binding, it takes the first" do @@ -261,7 +261,7 @@ def initialize; end } } }) - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", parsed_metadata[:idp_cert_fingerprint] + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", parsed_metadata[:idp_cert_fingerprint] assert_nil parsed_metadata[:security] end @@ -272,8 +272,8 @@ def initialize; end metadata1 = idp_metadata_parser.parse_to_hash(idp_metadata1) metadata2 = idp_metadata_parser.parse_to_hash(idp_metadata2) - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", metadata1[:idp_cert_fingerprint] - assert_equal "CD:2B:2B:DA:FF:F5:DB:64:10:7C:AC:FD:FE:0F:CB:5D:73:5F:16:07", metadata2[:idp_cert_fingerprint] + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", metadata1[:idp_cert_fingerprint] + assert_equal "E5:52:D9:2C:3C:DC:3D:09:5C:90:76:82:AB:B6:75:B4:92:92:2C:42:87:7E:18:EB:17:F3:1F:39:FE:9F:7C:6A", metadata2[:idp_cert_fingerprint] end end @@ -320,7 +320,7 @@ def initialize; end assert_equal "https://hello.example.com/access/saml/idp.xml", settings.idp_entity_id assert_equal "https://hello.example.com/access/saml/login", settings.idp_sso_service_url assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", settings.idp_sso_service_binding - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", settings.idp_cert_fingerprint assert_equal "https://hello.example.com/access/saml/logout", settings.idp_slo_service_url assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", settings.idp_slo_service_binding assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified", settings.name_identifier_format @@ -356,7 +356,7 @@ def initialize; end assert_equal "https://hello.example.com/access/saml/idp.xml", parsed_metadata[:idp_entity_id] assert_equal "https://hello.example.com/access/saml/login", parsed_metadata[:idp_sso_service_url] assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", parsed_metadata[:idp_sso_service_binding] - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", parsed_metadata[:idp_cert_fingerprint] + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", parsed_metadata[:idp_cert_fingerprint] assert_equal "https://hello.example.com/access/saml/logout", parsed_metadata[:idp_slo_service_url] assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", parsed_metadata[:idp_slo_service_binding] assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified", parsed_metadata[:name_identifier_format] @@ -467,7 +467,7 @@ def initialize; end assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified", @settings.name_identifier_format assert_equal "https://hello.example.com/access/saml/login", @settings.idp_sso_service_url assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", @settings.idp_sso_service_binding - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", @settings.idp_cert_fingerprint + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", @settings.idp_cert_fingerprint assert_equal "https://hello.example.com/access/saml/logout", @settings.idp_slo_service_url assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", @settings.idp_slo_service_binding assert_equal ["AuthToken", "SSOStartPage"], @settings.idp_attribute_names @@ -477,10 +477,10 @@ def initialize; end it "should handle multiple descriptors at once" do settings = @idp_metadata_parser.parse_to_array(@idp_metadata) assert_equal "https://foo.example.com/access/saml/idp.xml", settings.first[:idp_entity_id] - assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.first[:idp_cert_fingerprint] + assert_equal "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21", settings.first[:idp_cert_fingerprint] assert_equal '2014-04-17T18:02:33.910Z', settings.first[:valid_until] assert_equal "https://bar.example.com/access/saml/idp.xml", settings.last[:idp_entity_id] - assert_equal "08:EB:6E:60:A2:14:4E:89:EC:FA:05:74:9D:72:BF:5D:BE:54:F0:1A", settings.last[:idp_cert_fingerprint] + assert_equal "74:E4:FA:29:20:26:36:8A:72:5E:9D:CF:4F:8E:1F:DC:D4:CE:E2:3C:9D:6F:93:35:A1:A7:8A:4D:79:83:21:D0", settings.last[:idp_cert_fingerprint] assert_equal '2014-04-17T18:02:33.910Z', settings.last[:valid_until] end end @@ -649,7 +649,7 @@ def initialize; end it "should return idp_cert and idp_cert_fingerprint and no idp_cert_multi" do assert_equal(expected_cert, @settings.idp_cert) - assert_equal("2D:A9:40:88:28:EE:67:BB:4A:5B:E0:58:A7:CC:71:95:2D:1B:C9:D3", @settings.idp_cert_fingerprint) + assert_equal("46:E3:68:F4:ED:61:43:2B:EC:36:E3:99:E9:03:4B:99:E5:B3:58:EF:A9:A9:00:FC:2D:C8:7C:14:C6:60:E3:8F", @settings.idp_cert_fingerprint) assert_equal({ :signing => [expected_cert], :encryption => [expected_cert] }, @settings.idp_cert_multi) assert_equal("https://app.onelogin.com/saml/metadata/383123", @settings.idp_entity_id) assert_equal("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", @settings.name_identifier_format) diff --git a/test/logoutrequest_test.rb b/test/logoutrequest_test.rb index 22543add..9d0ab804 100644 --- a/test/logoutrequest_test.rb +++ b/test/logoutrequest_test.rb @@ -123,8 +123,8 @@ class RequestTest < Minitest::Test inflated = unauth_req.create_xml_document(settings).to_s refute_match %r[([a-zA-Z0-9/+=]+)], inflated - refute_match %r[], inflated - refute_match %r[], inflated + refute_match %r[], inflated + refute_match %r[], inflated end it "sign unsigned request" do @@ -133,14 +133,14 @@ class RequestTest < Minitest::Test inflated = unauth_req_doc.to_s refute_match %r[([a-zA-Z0-9/+=]+)], inflated - refute_match %r[], inflated - refute_match %r[], inflated + refute_match %r[], inflated + refute_match %r[], inflated inflated = unauth_req.sign_document(unauth_req_doc, settings).to_s assert_match %r[([a-zA-Z0-9/+=]+)], inflated - assert_match %r[], inflated - assert_match %r[], inflated + assert_match %r[], inflated + assert_match %r[], inflated end it "signs through create_logout_request_xml_doc" do @@ -148,8 +148,8 @@ class RequestTest < Minitest::Test inflated = unauth_req.create_logout_request_xml_doc(settings).to_s assert_match %r[([a-zA-Z0-9/+=]+)], inflated - assert_match %r[], inflated - assert_match %r[], inflated + assert_match %r[], inflated + assert_match %r[], inflated end it "create an uncompressed signed logout request" do @@ -157,8 +157,8 @@ class RequestTest < Minitest::Test request_xml = Base64.decode64(params["SAMLRequest"]) assert_match %r[([a-zA-Z0-9/+=]+)], request_xml - assert_match %r[], request_xml - assert_match %r[], request_xml + assert_match %r[], request_xml + assert_match %r[], request_xml end it "create a signed logout request with 256 digest and signature method" do @@ -198,8 +198,8 @@ class RequestTest < Minitest::Test request_xml = Base64.decode64(params["SAMLRequest"]) assert_match %r[([a-zA-Z0-9/+=]+)], request_xml - assert_match %r[], request_xml - assert_match %r[], request_xml + assert_match %r[], request_xml + assert_match %r[], request_xml end it "create a signed logout request using the first valid certificate and key when :check_sp_cert_expiration is true" do @@ -217,8 +217,8 @@ class RequestTest < Minitest::Test request_xml = Base64.decode64(params["SAMLRequest"]) assert_match %r[([a-zA-Z0-9/+=]+)], request_xml - assert_match %r[], request_xml - assert_match %r[], request_xml + assert_match %r[], request_xml + assert_match %r[], request_xml end it "raises error when no valid certs and :check_sp_cert_expiration is true" do @@ -359,8 +359,8 @@ class RequestTest < Minitest::Test inflated = unauth_req.create_logout_request_xml_doc(settings).to_s assert_match %r[([a-zA-Z0-9/+=]+)], inflated - assert_match %r[], inflated - assert_match %r[], inflated + assert_match %r[], inflated + assert_match %r[], inflated end end diff --git a/test/metadata_test.rb b/test/metadata_test.rb index e72928da..2b30c399 100644 --- a/test/metadata_test.rb +++ b/test/metadata_test.rb @@ -337,8 +337,8 @@ class MetadataTest < Minitest::Test it "creates a signed metadata" do assert_match %r[([a-zA-Z0-9/+=]+)]m, xml_text - assert_match %r[], xml_text - assert_match %r[], xml_text + assert_match %r[], xml_text + assert_match %r[], xml_text signed_metadata = XMLSecurity::SignedDocument.new(xml_text) assert signed_metadata.validate_document(ruby_saml_cert_fingerprint, false) @@ -397,8 +397,8 @@ def add_extras(root, _settings) assert_equal first_child.name, 'Signature' assert_match %r[([a-zA-Z0-9/+=]+)]m, xml_text - assert_match %r[], xml_text - assert_match %r[], xml_text + assert_match %r[], xml_text + assert_match %r[], xml_text signed_metadata = XMLSecurity::SignedDocument.new(xml_text) assert signed_metadata.validate_document(ruby_saml_cert_fingerprint, false) diff --git a/test/request_test.rb b/test/request_test.rb index 0c404716..f7f03408 100644 --- a/test/request_test.rb +++ b/test/request_test.rb @@ -253,7 +253,7 @@ class RequestTest < Minitest::Test params = RubySaml::Authrequest.new.create_params(settings) request_xml = Base64.decode64(params["SAMLRequest"]) assert_match %r[([a-zA-Z0-9/+=]+)], request_xml - assert_match %r[], request_xml + assert_match %r[], request_xml end it "create a signed request with 256 digest and signature methods" do @@ -282,7 +282,7 @@ class RequestTest < Minitest::Test request_xml = Base64.decode64(params["SAMLRequest"]) assert_match %r[([a-zA-Z0-9/+=]+)], request_xml - assert_match %r[], request_xml + assert_match %r[], request_xml end it "creates a signed request using the first valid certificate and key when :check_sp_cert_expiration is true" do @@ -300,7 +300,7 @@ class RequestTest < Minitest::Test request_xml = Base64.decode64(params["SAMLRequest"]) assert_match %r[([a-zA-Z0-9/+=]+)], request_xml - assert_match %r[], request_xml + assert_match %r[], request_xml end it "raises error when no valid certs and :check_sp_cert_expiration is true" do @@ -440,7 +440,7 @@ class RequestTest < Minitest::Test params = RubySaml::Authrequest.new.create_params(settings) request_xml = Base64.decode64(params["SAMLRequest"]) assert_match %r[([a-zA-Z0-9/+=]+)], request_xml - assert_match %r[], request_xml + assert_match %r[], request_xml end end diff --git a/test/response_test.rb b/test/response_test.rb index 31240648..588c3b61 100644 --- a/test/response_test.rb +++ b/test/response_test.rb @@ -381,7 +381,7 @@ def generate_audience_error(expected, actual) no_signature_response.stubs(:conditions).returns(nil) no_signature_response.stubs(:validate_subject_confirmation).returns(true) no_signature_response.settings = settings - no_signature_response.settings.idp_cert_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA" + no_signature_response.settings.idp_cert_fingerprint = "3D:C5:BC:58:60:5D:19:64:94:E3:BA:C8:3D:49:01:D5:56:34:44:65:C2:85:0A:A8:65:A5:AC:76:7E:65:1F:F7" XMLSecurity::SignedDocument.any_instance.expects(:validate_signature).returns(true) assert no_signature_response.is_valid? end @@ -390,7 +390,7 @@ def generate_audience_error(expected, actual) adfs_response = RubySaml::Response.new(fixture(:adfs_response_sha256)) adfs_response.stubs(:conditions).returns(nil) adfs_response.stubs(:validate_subject_confirmation).returns(true) - settings.idp_cert_fingerprint = "28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA" + settings.idp_cert_fingerprint = "3D:C5:BC:58:60:5D:19:64:94:E3:BA:C8:3D:49:01:D5:56:34:44:65:C2:85:0A:A8:65:A5:AC:76:7E:65:1F:F7" adfs_response.settings = settings adfs_response.soft = true assert adfs_response.is_valid? @@ -878,14 +878,14 @@ def generate_audience_error(expected, actual) end it "return true when the signature is valid and ds namespace is at the root" do - settings.idp_cert_fingerprint = '5614657ab692b960480389723a36446a5fe1f7ec' + settings.idp_cert_fingerprint = '19a4fff2e8fcc7f3ea5046348dbf1d81320654d1f712028cc97933cb1247fc99' response_with_ds_namespace_at_the_root.settings = settings assert response_with_ds_namespace_at_the_root.send(:validate_signature) assert_empty response_with_ds_namespace_at_the_root.errors end it "return true when the signature is valid and fingerprint provided" do - settings.idp_cert_fingerprint = '49:EC:3F:A4:71:8A:1E:C9:DB:70:A7:CC:33:36:96:F0:48:8C:4E:DA' + settings.idp_cert_fingerprint = 'D0:35:89:BB:11:16:CB:3C:26:B0:D4:DA:CE:2A:91:B9:E0:A6:D8:E8:BF:93:C2:5B:74:0D:52:01:47:72:CE:E4' xml = 'PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIERlc3RpbmF0aW9uPSJodHRwczovL2NvZGVycGFkLmlvL3NhbWwvYWNzIiBJRD0iXzEwOGE1ZTg0MDllYzRjZjlhY2QxYzQ2OWU5ZDcxNGFkIiBJblJlc3BvbnNlVG89Il80ZmZmYWE2MC02OTZiLTAxMzMtMzg4Ni0wMjQxZjY1YzA2OTMiIElzc3VlSW5zdGFudD0iMjAxNS0xMS0wOVQyMzo1NTo0M1oiIFZlcnNpb249IjIuMCI+PHNhbWw6SXNzdWVyIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPmh0dHBzOi8vbG9naW4uaHVsdS5jb208L3NhbWw6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIj48L2RzOkNhbm9uaWNhbGl6YXRpb25NZXRob2Q+PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNyc2Etc2hhMSI+PC9kczpTaWduYXR1cmVNZXRob2Q+PGRzOlJlZmVyZW5jZSBVUkk9IiNfMTA4YTVlODQwOWVjNGNmOWFjZDFjNDY5ZTlkNzE0YWQiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSI+PC9kczpUcmFuc2Zvcm0+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyI+PC9kczpUcmFuc2Zvcm0+PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjc2hhMSI+PC9kczpEaWdlc3RNZXRob2Q+PGRzOkRpZ2VzdFZhbHVlPm9sQllXbTQyRi9oZm0xdHJYTHk2a3V6MXlMUT08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+dXNRTmY5WGpKTDRlOXVucnVCdWViSnQ3R0tXM2hJUk9teWVqTm1NMHM4WFhlWHN3WHc4U3ZCZi8zeDNNWEpkWnpNV0pOM3ExN2tGWHN2bTVna1JzbkE9PTwvZHM6U2lnbmF0dXJlVmFsdWU+PGRzOktleUluZm8+PGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJQ1FEQ0NBZXFnQXdJQkFnSUpBSVZOdzVLRzR1aTFNQTBHQ1NxR1NJYjNEUUVCQlFVQU1Fd3hDekFKQmdOVkJBWVRBa2RDTVJJd0VBWURWUVFJRXdsQ1pYSnJjMmhwY21VeEVEQU9CZ05WQkFjVEIwNWxkMkoxY25reEZ6QVZCZ05WQkFvVERrMTVJRU52YlhCaGJua2dUSFJrTUI0WERURXlNVEF5TlRBMk1qY3pORm9YRFRJeU1UQXlNekEyTWpjek5Gb3dUREVMTUFrR0ExVUVCaE1DUjBJeEVqQVFCZ05WQkFnVENVSmxjbXR6YUdseVpURVFNQTRHQTFVRUJ4TUhUbVYzWW5WeWVURVhNQlVHQTFVRUNoTU9UWGtnUTI5dGNHRnVlU0JNZEdRd1hEQU5CZ2txaGtpRzl3MEJBUUVGQUFOTEFEQklBa0VBd1NOL2dpMzNSbXBBUW9MUWo3UDZ6QW5OVDBSbjdiakMzMjNuM3ExT25mdm52UjBmUWp2TnQ3ckRrQTVBdjVRbk02VjRZVU5Vbk1mYk9RcTBXTGJMU3dJREFRQUJvNEd1TUlHck1CMEdBMVVkRGdRV0JCUWZJSDFvZkJWcHNSQWNJTUsyaGJsN25nTVRZREI4QmdOVkhTTUVkVEJ6Z0JRZklIMW9mQlZwc1JBY0lNSzJoYmw3bmdNVFlLRlFwRTR3VERFTE1Ba0dBMVVFQmhNQ1IwSXhFakFRQmdOVkJBZ1RDVUpsY210emFHbHlaVEVRTUE0R0ExVUVCeE1IVG1WM1luVnllVEVYTUJVR0ExVUVDaE1PVFhrZ1EyOXRjR0Z1ZVNCTWRHU0NDUUNGVGNPU2h1TG90VEFNQmdOVkhSTUVCVEFEQVFIL01BMEdDU3FHU0liM0RRRUJCUVVBQTBFQXFvZ1YzdVBjbEtYRG1EWk1UN3ZsUFl4TEFxQ0dIWnRsQ3h6NGhNNEtTdGxEMi9HTmMxWGlMYjFoL0swQ0pMRG9zckVJYm0zd2lPMk12VEVSclZZU01RPT08L2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz48L2RzOlNpZ25hdHVyZT48c2FtbHA6U3RhdHVzPjxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiPjwvc2FtbHA6U3RhdHVzQ29kZT48L3NhbWxwOlN0YXR1cz48c2FtbDpBc3NlcnRpb24geG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9Il8wMTg4MmRhOTM2OTQ0ZDFlYTZlZmY0NDA2NTc2MzFiNSIgSXNzdWVJbnN0YW50PSIyMDE1LTExLTA5VDIzOjU1OjQzWiIgVmVyc2lvbj0iMi4wIj48c2FtbDpJc3N1ZXI+aHR0cHM6Ly9sb2dpbi5odWx1LmNvbTwvc2FtbDpJc3N1ZXI+PGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PGRzOlNpZ25lZEluZm8+PGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiPjwvZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZD48ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3JzYS1zaGExIj48L2RzOlNpZ25hdHVyZU1ldGhvZD48ZHM6UmVmZXJlbmNlIFVSST0iI18wMTg4MmRhOTM2OTQ0ZDFlYTZlZmY0NDA2NTc2MzFiNSI+PGRzOlRyYW5zZm9ybXM+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIj48L2RzOlRyYW5zZm9ybT48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIj48L2RzOlRyYW5zZm9ybT48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNzaGExIj48L2RzOkRpZ2VzdE1ldGhvZD48ZHM6RGlnZXN0VmFsdWU+cmo2YzhucC9BUmV0ZkJ1dWVOSzNPS0xDYnowPTwvZHM6RGlnZXN0VmFsdWU+PC9kczpSZWZlcmVuY2U+PC9kczpTaWduZWRJbmZvPjxkczpTaWduYXR1cmVWYWx1ZT5hR05FemZHM1dLcExKc2ZLRGJSNmpva2d6OEFnZ0FIRVVESEZyd0dsTHVQeWpyNEl3M09NcFNkV2gyL01YK1F3M1dPTk5mNHJNalh5TGVZSFJIVGpMQT09PC9kczpTaWduYXR1cmVWYWx1ZT48ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE+PGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlDUURDQ0FlcWdBd0lCQWdJSkFJVk53NUtHNHVpMU1BMEdDU3FHU0liM0RRRUJCUVVBTUV3eEN6QUpCZ05WQkFZVEFrZENNUkl3RUFZRFZRUUlFd2xDWlhKcmMyaHBjbVV4RURBT0JnTlZCQWNUQjA1bGQySjFjbmt4RnpBVkJnTlZCQW9URGsxNUlFTnZiWEJoYm5rZ1RIUmtNQjRYRFRFeU1UQXlOVEEyTWpjek5Gb1hEVEl5TVRBeU16QTJNamN6TkZvd1RERUxNQWtHQTFVRUJoTUNSMEl4RWpBUUJnTlZCQWdUQ1VKbGNtdHphR2x5WlRFUU1BNEdBMVVFQnhNSFRtVjNZblZ5ZVRFWE1CVUdBMVVFQ2hNT1RYa2dRMjl0Y0dGdWVTQk1kR1F3WERBTkJna3Foa2lHOXcwQkFRRUZBQU5MQURCSUFrRUF3U04vZ2kzM1JtcEFRb0xRajdQNnpBbk5UMFJuN2JqQzMyM24zcTFPbmZ2bnZSMGZRanZOdDdyRGtBNUF2NVFuTTZWNFlVTlVuTWZiT1FxMFdMYkxTd0lEQVFBQm80R3VNSUdyTUIwR0ExVWREZ1FXQkJRZklIMW9mQlZwc1JBY0lNSzJoYmw3bmdNVFlEQjhCZ05WSFNNRWRUQnpnQlFmSUgxb2ZCVnBzUkFjSU1LMmhibDduZ01UWUtGUXBFNHdUREVMTUFrR0ExVUVCaE1DUjBJeEVqQVFCZ05WQkFnVENVSmxjbXR6YUdseVpURVFNQTRHQTFVRUJ4TUhUbVYzWW5WeWVURVhNQlVHQTFVRUNoTU9UWGtnUTI5dGNHRnVlU0JNZEdTQ0NRQ0ZUY09TaHVMb3RUQU1CZ05WSFJNRUJUQURBUUgvTUEwR0NTcUdTSWIzRFFFQkJRVUFBMEVBcW9nVjN1UGNsS1hEbURaTVQ3dmxQWXhMQXFDR0hadGxDeHo0aE00S1N0bEQyL0dOYzFYaUxiMWgvSzBDSkxEb3NyRUlibTN3aU8yTXZURVJyVllTTVE9PTwvZHM6WDUwOUNlcnRpZmljYXRlPjwvZHM6WDUwOURhdGE+PC9kczpLZXlJbmZvPjwvZHM6U2lnbmF0dXJlPjxzYW1sOlN1YmplY3Q+PHNhbWw6TmFtZUlEIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4xOm5hbWVpZC1mb3JtYXQ6ZW1haWxBZGRyZXNzIiBTUE5hbWVRdWFsaWZpZXI9Imh0dHBzOi8vY29kZXJwYWQuaW8iPm1hdHQuanVyaWtAaHVsdS5jb208L3NhbWw6TmFtZUlEPjxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBJblJlc3BvbnNlVG89Il80ZmZmYWE2MC02OTZiLTAxMzMtMzg4Ni0wMjQxZjY1YzA2OTMiIE5vdE9uT3JBZnRlcj0iMjAxNS0xMS0xMFQwMDoxMDo0M1oiIFJlY2lwaWVudD0iaHR0cHM6Ly9jb2RlcnBhZC5pby9zYW1sL2FjcyI+PC9zYW1sOlN1YmplY3RDb25maXJtYXRpb25EYXRhPjwvc2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uPjwvc2FtbDpTdWJqZWN0PjxzYW1sOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDE1LTExLTA5VDIyOjU1OjQzWiIgTm90T25PckFmdGVyPSIyMDE1LTExLTEwVDAwOjEwOjQzWiI+PHNhbWw6QXVkaWVuY2VSZXN0cmljdGlvbj48c2FtbDpBdWRpZW5jZT5odHRwczovL2NvZGVycGFkLmlvPC9zYW1sOkF1ZGllbmNlPjwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPjwvc2FtbDpDb25kaXRpb25zPjxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxNS0xMS0wOVQyMzo1NTo0M1oiPjxzYW1sOkF1dGhuQ29udGV4dD48c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj48L3NhbWw6QXV0aG5Db250ZXh0Pjwvc2FtbDpBdXRoblN0YXRlbWVudD48c2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ+PHNhbWw6QXR0cmlidXRlIE5hbWU9IkdpdmVuLW5hbWUiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlPk1hdHQ8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0iU3VybmFtZSI+PHNhbWw6QXR0cmlidXRlVmFsdWU+SnVyaWs8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0iRW1haWwiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlPm1hdHQuanVyaWtAaHVsdS5jb208L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48L3NhbWw6QXR0cmlidXRlU3RhdGVtZW50Pjwvc2FtbDpBc3NlcnRpb24+PC9zYW1scDpSZXNwb25zZT4=' response_x = RubySaml::Response.new(xml) response_x.settings = settings @@ -1497,7 +1497,7 @@ def generate_audience_error(expected, actual) describe "retrieve nameID and attributes from encrypted assertion" do before do - settings.idp_cert_fingerprint = 'EE:17:4E:FB:A8:81:71:12:0D:2A:78:43:BC:E7:0C:07:58:79:F4:F4' + settings.idp_cert_fingerprint = '55:FD:5F:3F:43:5A:AC:E6:79:89:BF:25:48:81:A1:C4:F3:37:3B:CB:1B:4D:68:A0:3E:A5:C9:FF:61:48:01:3F' settings.sp_entity_id = 'http://rubysaml.com:3000/saml/metadata' settings.assertion_consumer_service_url = 'http://rubysaml.com:3000/saml/acs' settings.certificate = ruby_saml_cert_text diff --git a/test/settings_test.rb b/test/settings_test.rb index bf391dcc..5dd5d51d 100644 --- a/test/settings_test.rb +++ b/test/settings_test.rb @@ -118,14 +118,14 @@ class SettingsTest < Minitest::Test settings = RubySaml::Settings.new settings.security[:authn_requests_signed] = true settings.security[:embed_sign] = true - settings.security[:digest_method] = XMLSecurity::Document::SHA256 - settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256 + settings.security[:digest_method] = XMLSecurity::Document::SHA512 + settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA512 new_settings = RubySaml::Settings.new assert_equal new_settings.security[:authn_requests_signed], false assert_equal new_settings.security[:embed_sign], false - assert_equal new_settings.security[:digest_method], XMLSecurity::Document::SHA1 - assert_equal new_settings.security[:signature_method], XMLSecurity::Document::RSA_SHA1 + assert_equal new_settings.security[:digest_method], XMLSecurity::Document::SHA256 + assert_equal new_settings.security[:signature_method], XMLSecurity::Document::RSA_SHA256 end it "overrides only provided security attributes passing a second parameter" do diff --git a/test/slo_logoutresponse_test.rb b/test/slo_logoutresponse_test.rb index a602af56..142d22a9 100644 --- a/test/slo_logoutresponse_test.rb +++ b/test/slo_logoutresponse_test.rb @@ -109,8 +109,8 @@ class SloLogoutresponseTest < Minitest::Test inflated = unauth_res.create_xml_document(settings).to_s refute_match %r[([a-zA-Z0-9/+=]+)], inflated - refute_match %r[], inflated - refute_match %r[], inflated + refute_match %r[], inflated + refute_match %r[], inflated end it "sign unsigned request" do @@ -119,14 +119,14 @@ class SloLogoutresponseTest < Minitest::Test inflated = unauth_res_doc.to_s refute_match %r[([a-zA-Z0-9/+=]+)], inflated - refute_match %r[], inflated - refute_match %r[], inflated + refute_match %r[], inflated + refute_match %r[], inflated inflated = unauth_res.sign_document(unauth_res_doc, settings).to_s assert_match %r[([a-zA-Z0-9/+=]+)], inflated - assert_match %r[], inflated - assert_match %r[], inflated + assert_match %r[], inflated + assert_match %r[], inflated end it "signs through create_logout_response_xml_doc" do @@ -134,8 +134,8 @@ class SloLogoutresponseTest < Minitest::Test inflated = unauth_res.create_logout_response_xml_doc(settings).to_s assert_match %r[([a-zA-Z0-9/+=]+)], inflated - assert_match %r[], inflated - assert_match %r[], inflated + assert_match %r[], inflated + assert_match %r[], inflated end it "create a signed logout response" do @@ -145,24 +145,24 @@ class SloLogoutresponseTest < Minitest::Test response_xml = Base64.decode64(params["SAMLResponse"]) assert_match %r[([a-zA-Z0-9/+=]+)], response_xml - assert_match(//, response_xml) - assert_match(//, response_xml) + assert_match(//, response_xml) + assert_match(//, response_xml) end - it "create a signed logout response with 256 digest and signature methods" do - settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256 - settings.security[:digest_method] = XMLSecurity::Document::SHA256 + it "create a signed logout response with SHA384 digest and signature method RSA_SHA512" do + settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA512 + settings.security[:digest_method] = XMLSecurity::Document::SHA384 logout_request.settings = settings params = RubySaml::SloLogoutresponse.new.create_params(settings, logout_request.id, "Custom Logout Message") response_xml = Base64.decode64(params["SAMLResponse"]) assert_match %r[([a-zA-Z0-9/+=]+)], response_xml - assert_match(//, response_xml) - assert_match(//, response_xml) + assert_match(//, response_xml) + assert_match(//, response_xml) end - it "create a signed logout response with 512 digest and signature method RSA_SHA384" do + it "create a signed logout response with SHA512 digest and signature method RSA_SHA384" do settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384 settings.security[:digest_method] = XMLSecurity::Document::SHA512 logout_request.settings = settings @@ -190,8 +190,8 @@ class SloLogoutresponseTest < Minitest::Test response_xml = Base64.decode64(params["SAMLResponse"]) assert_match %r[([a-zA-Z0-9/+=]+)], response_xml - assert_match(//, response_xml) - assert_match(//, response_xml) + assert_match(//, response_xml) + assert_match(//, response_xml) end it "create a signed logout response using the first valid certificate and key when :check_sp_cert_expiration is true" do @@ -210,8 +210,8 @@ class SloLogoutresponseTest < Minitest::Test response_xml = Base64.decode64(params["SAMLResponse"]) assert_match %r[([a-zA-Z0-9/+=]+)], response_xml - assert_match(//, response_xml) - assert_match(//, response_xml) + assert_match(//, response_xml) + assert_match(//, response_xml) end it "raises error when no valid certs and :check_sp_cert_expiration is true" do @@ -354,8 +354,8 @@ class SloLogoutresponseTest < Minitest::Test inflated = unauth_res.create_xml_document(settings).to_s refute_match %r[([a-zA-Z0-9/+=]+)], inflated - refute_match %r[], inflated - refute_match %r[], inflated + refute_match %r[], inflated + refute_match %r[], inflated end it "sign unsigned request" do @@ -364,14 +364,14 @@ class SloLogoutresponseTest < Minitest::Test inflated = unauth_res_doc.to_s refute_match %r[([a-zA-Z0-9/+=]+)], inflated - refute_match %r[], inflated - refute_match %r[], inflated + refute_match %r[], inflated + refute_match %r[], inflated inflated = unauth_res.sign_document(unauth_res_doc, settings).to_s assert_match %r[([a-zA-Z0-9/+=]+)], inflated - assert_match %r[], inflated - assert_match %r[], inflated + assert_match %r[], inflated + assert_match %r[], inflated end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 1c8e3e5a..ef5dc344 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -279,7 +279,7 @@ def ruby_saml_cert2 end def ruby_saml_cert_fingerprint - @ruby_saml_cert_fingerprint ||= Digest::SHA1.hexdigest(ruby_saml_cert.to_der).scan(/../).join(":") + @ruby_saml_cert_fingerprint ||= Digest::SHA256.hexdigest(ruby_saml_cert.to_der).scan(/../).join(":") end def ruby_saml_cert_text diff --git a/test/utils_test.rb b/test/utils_test.rb index 23360cb2..b0e7f2b1 100644 --- a/test/utils_test.rb +++ b/test/utils_test.rb @@ -195,9 +195,9 @@ def result(duration, reference = 0) params[:type] = "SAMLRequest" params[:data] = "PHNhbWxwOkF1dGhuUmVxdWVzdCBEZXN0aW5hdGlvbj0naHR0cDovL2V4YW1wbGUuY29tP2ZpZWxkPXZhbHVlJyBJRD0nXzk4NmUxZDEwLWVhY2ItMDEzMi01MGRkLTAwOTBmNWRlZGQ3NycgSXNzdWVJbnN0YW50PScyMDE1LTA2LTAxVDIwOjM0OjU5WicgVmVyc2lvbj0nMi4wJyB4bWxuczpzYW1sPSd1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uJyB4bWxuczpzYW1scD0ndXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sJy8+" params[:relay_state] = "http://example.com" - params[:sig_alg] = "http://www.w3.org/2000/09/xmldsig#rsa-sha1" + params[:sig_alg] = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" query_string = RubySaml::Utils.build_query(params) - assert_equal "SAMLRequest=PHNhbWxwOkF1dGhuUmVxdWVzdCBEZXN0aW5hdGlvbj0naHR0cDovL2V4YW1wbGUuY29tP2ZpZWxkPXZhbHVlJyBJRD0nXzk4NmUxZDEwLWVhY2ItMDEzMi01MGRkLTAwOTBmNWRlZGQ3NycgSXNzdWVJbnN0YW50PScyMDE1LTA2LTAxVDIwOjM0OjU5WicgVmVyc2lvbj0nMi4wJyB4bWxuczpzYW1sPSd1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uJyB4bWxuczpzYW1scD0ndXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sJy8%2B&RelayState=http%3A%2F%2Fexample.com&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1", query_string + assert_equal "SAMLRequest=PHNhbWxwOkF1dGhuUmVxdWVzdCBEZXN0aW5hdGlvbj0naHR0cDovL2V4YW1wbGUuY29tP2ZpZWxkPXZhbHVlJyBJRD0nXzk4NmUxZDEwLWVhY2ItMDEzMi01MGRkLTAwOTBmNWRlZGQ3NycgSXNzdWVJbnN0YW50PScyMDE1LTA2LTAxVDIwOjM0OjU5WicgVmVyc2lvbj0nMi4wJyB4bWxuczpzYW1sPSd1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uJyB4bWxuczpzYW1scD0ndXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sJy8%2B&RelayState=http%3A%2F%2Fexample.com&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256", query_string end end diff --git a/test/xml_security_test.rb b/test/xml_security_test.rb index 5abf3801..59919849 100644 --- a/test/xml_security_test.rb +++ b/test/xml_security_test.rb @@ -111,13 +111,13 @@ class XmlSecurityTest < Minitest::Test alg = OpenSSL::Digest::SHA1 assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2000/09/xmldsig#rsa-sha1") assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2000/09/xmldsig#sha1") - assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("other") end it "SHA256" do alg = OpenSSL::Digest::SHA256 assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256") assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("http://www.w3.org/2001/04/xmldsig-more#sha256") + assert_equal alg, XMLSecurity::BaseDocument.new.algorithm("other") end it "SHA384" do @@ -138,34 +138,35 @@ class XmlSecurityTest < Minitest::Test it "validate using SHA1" do sha1_fingerprint = "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72" - sha1_fingerprint_downcase = "f13c6b80905a030e6c913e5d15faddb016454872" + sha1_fingerprint_downcase = sha1_fingerprint.tr(':', '').downcase - assert response_fingerprint_test.document.validate_document(sha1_fingerprint) - assert response_fingerprint_test.document.validate_document(sha1_fingerprint, true, :fingerprint_alg => XMLSecurity::Document::SHA1) - - assert response_fingerprint_test.document.validate_document(sha1_fingerprint_downcase) - assert response_fingerprint_test.document.validate_document(sha1_fingerprint_downcase, true, :fingerprint_alg => XMLSecurity::Document::SHA1) + assert response_fingerprint_test.document.validate_document(sha1_fingerprint, true, fingerprint_alg: XMLSecurity::Document::SHA1) + assert response_fingerprint_test.document.validate_document(sha1_fingerprint_downcase, true, fingerprint_alg: XMLSecurity::Document::SHA1) end it "validate using SHA256" do sha256_fingerprint = "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21" + sha256_fingerprint_downcase = sha256_fingerprint.tr(':', '').downcase + + assert response_fingerprint_test.document.validate_document(sha256_fingerprint) + assert response_fingerprint_test.document.validate_document(sha256_fingerprint, true, fingerprint_alg: XMLSecurity::Document::SHA256) - assert !response_fingerprint_test.document.validate_document(sha256_fingerprint) - assert response_fingerprint_test.document.validate_document(sha256_fingerprint, true, :fingerprint_alg => XMLSecurity::Document::SHA256) + assert response_fingerprint_test.document.validate_document(sha256_fingerprint_downcase) + assert response_fingerprint_test.document.validate_document(sha256_fingerprint_downcase, true, fingerprint_alg: XMLSecurity::Document::SHA256) end it "validate using SHA384" do sha384_fingerprint = "98:FE:17:90:31:E7:68:18:8A:65:4D:DA:F5:76:E2:09:97:BE:8B:E3:7E:AA:8D:63:64:7C:0C:38:23:9A:AC:A2:EC:CE:48:A6:74:4D:E0:4C:50:80:40:B4:8D:55:14:14" assert !response_fingerprint_test.document.validate_document(sha384_fingerprint) - assert response_fingerprint_test.document.validate_document(sha384_fingerprint, true, :fingerprint_alg => XMLSecurity::Document::SHA384) + assert response_fingerprint_test.document.validate_document(sha384_fingerprint, true, fingerprint_alg: XMLSecurity::Document::SHA384) end it "validate using SHA512" do sha512_fingerprint = "5A:AE:BA:D0:BA:9D:1E:25:05:01:1E:1A:C9:E9:FF:DB:ED:FA:6E:F7:52:EB:45:49:BD:DB:06:D8:A3:7E:CC:63:3A:04:A2:DD:DF:EE:61:05:D9:58:95:2A:77:17:30:4B:EB:4A:9F:48:4A:44:1C:D0:9E:0B:1E:04:77:FD:A3:D2" assert !response_fingerprint_test.document.validate_document(sha512_fingerprint) - assert response_fingerprint_test.document.validate_document(sha512_fingerprint, true, :fingerprint_alg => XMLSecurity::Document::SHA512) + assert response_fingerprint_test.document.validate_document(sha512_fingerprint, true, fingerprint_alg: XMLSecurity::Document::SHA512) end end @@ -173,22 +174,22 @@ class XmlSecurityTest < Minitest::Test describe "Signature Algorithms" do it "validate using SHA1" do document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha1, false)) - assert document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72") + assert document.validate_document("C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21") end it "validate using SHA256" do document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha256, false)) - assert document.validate_document("28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA") + assert document.validate_document("3D:C5:BC:58:60:5D:19:64:94:E3:BA:C8:3D:49:01:D5:56:34:44:65:C2:85:0A:A8:65:A5:AC:76:7E:65:1F:F7") end it "validate using SHA384" do document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha384, false)) - assert document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72") + assert document.validate_document("C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21") end it "validate using SHA512" do document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha512, false)) - assert document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72") + assert document.validate_document("C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21") end end @@ -302,7 +303,7 @@ class XmlSecurityTest < Minitest::Test let (:response) { RubySaml::Response.new(fixture(:starfield_response)) } before do - response.settings = RubySaml::Settings.new(:idp_cert_fingerprint => "8D:BA:53:8E:A3:B6:F9:F1:69:6C:BB:D9:D8:BD:41:B3:AC:4F:9D:4D") + response.settings = RubySaml::Settings.new(idp_cert_fingerprint: "8F:EB:0C:79:30:4A:E4:DF:B4:BD:7F:23:EE:29:3A:29:20:FE:BC:15:11:70:79:53:F4:37:55:05:2B:38:1A:42") end it "be able to validate a good response" do @@ -343,7 +344,7 @@ class XmlSecurityTest < Minitest::Test describe 'when response has signed message and assertion' do let(:document_data) { read_response('response_with_signed_message_and_assertion.xml') } let(:document) { RubySaml::Response.new(document_data).document } - let(:fingerprint) { '4b68c453c7d994aad9025c99d5efcf566287fe8d' } + let(:fingerprint) { '6385109dd146a45d4382799491cb2707bd1ebda3738f27a0e4a4a8159c0fe6cd' } it 'is valid' do assert document.validate_document(fingerprint, true), 'Document should be valid' @@ -353,7 +354,7 @@ class XmlSecurityTest < Minitest::Test describe 'when response has signed assertion' do let(:document_data) { read_response('response_with_signed_assertion_3.xml') } let(:document) { RubySaml::Response.new(document_data).document } - let(:fingerprint) { '4b68c453c7d994aad9025c99d5efcf566287fe8d' } + let(:fingerprint) { '6385109dd146a45d4382799491cb2707bd1ebda3738f27a0e4a4a8159c0fe6cd' } it 'is valid' do assert document.validate_document(fingerprint, true), 'Document should be valid' @@ -374,7 +375,7 @@ class XmlSecurityTest < Minitest::Test describe 'signature wrapping attack - doubled SAML response body' do let(:document_data) { read_invalid_response("response_with_doubled_signed_assertion.xml") } let(:document) { RubySaml::Response.new(document_data) } - let(:fingerprint) { '4b68c453c7d994aad9025c99d5efcf566287fe8d' } + let(:fingerprint) { '6385109dd146a45d4382799491cb2707bd1ebda3738f27a0e4a4a8159c0fe6cd' } it 'is valid, but the unsigned information is ignored in favour of the signed information' do assert document.document.validate_document(fingerprint, true), 'Document should be valid' @@ -385,7 +386,7 @@ class XmlSecurityTest < Minitest::Test describe 'signature wrapping attack - concealed SAML response body' do let(:document_data) { read_invalid_response("response_with_concealed_signed_assertion.xml") } let(:document) { RubySaml::Response.new(document_data) } - let(:fingerprint) { '4b68c453c7d994aad9025c99d5efcf566287fe8d' } + let(:fingerprint) { '6385109dd146a45d4382799491cb2707bd1ebda3738f27a0e4a4a8159c0fe6cd' } it 'is valid, but fails to retrieve information' do assert document.document.validate_document(fingerprint, true), 'Document should be valid'