diff --git a/Gemfile b/Gemfile
index 817f62a8..851fabc2 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,2 +1,2 @@
-source 'http://rubygems.org'
+source 'https://rubygems.org'
gemspec
diff --git a/Gemfile.lock b/Gemfile.lock
index c18e1a4f..db9cf51a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
- saml_idp (0.23.3.pre.18f)
+ saml_idp (0.23.4.pre.18f)
activesupport
builder
faraday
@@ -9,7 +9,7 @@ PATH
pkcs11
GEM
- remote: http://rubygems.org/
+ remote: https://rubygems.org/
specs:
actioncable (7.1.3.4)
actionpack (= 7.1.3.4)
@@ -317,7 +317,7 @@ DEPENDENCIES
simplecov (~> 0.22.0)
sqlite3
timecop
- xmlenc (>= 0.7.1)
+ xmlenc (>= 0.8.0)
BUNDLED WITH
2.5.7
diff --git a/lib/saml_idp/encryptor.rb b/lib/saml_idp/encryptor.rb
index c1e3d594..aa729d6b 100644
--- a/lib/saml_idp/encryptor.rb
+++ b/lib/saml_idp/encryptor.rb
@@ -3,6 +3,16 @@ module SamlIdp
class Encryptor
attr_accessor :encryption_key, :block_encryption, :key_transport, :cert
+ # Encryption algorithms enumerated in:
+ # https://github.com/digidentity/xmlenc/blob/937ca2f/lib/xmlenc/encrypted_data.rb#L3-L10
+ ENCRYPTION_ALGORITHMS_NS = {
+ 'aes128-cbc' => 'http://www.w3.org/2001/04/xmlenc#aes128-cbc',
+ 'aes256-cbc' => 'http://www.w3.org/2001/04/xmlenc#aes256-cbc',
+ 'aes128-gcm' => 'http://www.w3.org/2009/xmlenc11#aes128-gcm',
+ 'aes192-gcm' => 'http://www.w3.org/2009/xmlenc11#aes192-gcm',
+ 'aes256-gcm' => 'http://www.w3.org/2009/xmlenc11#aes256-gcm',
+ }
+
def initialize(opts)
self.block_encryption = opts[:block_encryption]
self.key_transport = opts[:key_transport]
@@ -35,7 +45,7 @@ def openssl_cert
private :openssl_cert
def block_encryption_ns
- "http://www.w3.org/2001/04/xmlenc##{block_encryption}"
+ ENCRYPTION_ALGORITHMS_NS[block_encryption]
end
private :block_encryption_ns
diff --git a/lib/saml_idp/version.rb b/lib/saml_idp/version.rb
index c7cd3504..e7592673 100644
--- a/lib/saml_idp/version.rb
+++ b/lib/saml_idp/version.rb
@@ -1,3 +1,3 @@
module SamlIdp
- VERSION = '0.23.3-18f'.freeze
+ VERSION = '0.23.4-18f'.freeze
end
diff --git a/saml_idp.gemspec b/saml_idp.gemspec
index 555e8c0c..f01b13ad 100644
--- a/saml_idp.gemspec
+++ b/saml_idp.gemspec
@@ -42,6 +42,6 @@ Gem::Specification.new do |s|
s.add_development_dependency 'simplecov', '~> 0.22.0'
s.add_development_dependency 'sqlite3'
s.add_development_dependency('timecop')
- s.add_development_dependency('xmlenc', '>= 0.7.1')
+ s.add_development_dependency('xmlenc', '>= 0.8.0')
s.metadata['rubygems_mfa_required'] = 'true'
end
diff --git a/spec/lib/saml_idp/controller_spec.rb b/spec/lib/saml_idp/controller_spec.rb
index 59b4cba8..6ef85552 100644
--- a/spec/lib/saml_idp/controller_spec.rb
+++ b/spec/lib/saml_idp/controller_spec.rb
@@ -1,4 +1,5 @@
require 'spec_helper'
+require 'saml_idp/encryptor'
describe SamlIdp::Controller do
include SamlIdp::Controller
@@ -56,13 +57,6 @@ def head(status, options = {}); end
end
let(:principal) { double email_address: 'foo@example.com' }
- let(:encryption_opts) do
- {
- cert: SamlIdp::Default::X509_CERTIFICATE,
- block_encryption: 'aes256-cbc',
- key_transport: 'rsa-oaep-mgf1p',
- }
- end
it 'creates a SAML Response' do
saml_response = encode_response(principal)
@@ -116,17 +110,25 @@ def head(status, options = {}); end
expect(response.is_valid?).to be_truthy
end
- it 'encrypts SAML Response assertion' do
- self.algorithm = algorithm_name
- saml_response = encode_response(principal, encryption: encryption_opts)
- resp_settings = saml_settings
- resp_settings.private_key = SamlIdp::Default::SECRET_KEY
- response = OneLogin::RubySaml::Response.new(saml_response, settings: resp_settings)
- expect(response.document.to_s).not_to match('foo@example.com')
- expect(response.decrypted_document.to_s).to match('foo@example.com')
- expect(response.name_id).to eq('foo@example.com')
- expect(response.issuers.first).to eq('http://example.com')
- expect(response.is_valid?).to be_truthy
+ SamlIdp::Encryptor::ENCRYPTION_ALGORITHMS_NS.keys.each do |encryption_algorithm|
+ it "encrypts SAML Response assertion using #{encryption_algorithm}" do
+ self.algorithm = algorithm_name
+ encryption_opts = {
+ cert: SamlIdp::Default::X509_CERTIFICATE,
+ block_encryption: encryption_algorithm,
+ key_transport: 'rsa-oaep-mgf1p',
+ }
+
+ saml_response = encode_response(principal, encryption: encryption_opts)
+ resp_settings = saml_settings
+ resp_settings.private_key = SamlIdp::Default::SECRET_KEY
+ response = OneLogin::RubySaml::Response.new(saml_response, settings: resp_settings)
+ expect(response.document.to_s).not_to match('foo@example.com')
+ expect(response.decrypted_document.to_s).to match('foo@example.com')
+ expect(response.name_id).to eq('foo@example.com')
+ expect(response.issuers.first).to eq('http://example.com')
+ expect(response.is_valid?).to be_truthy
+ end
end
end
end
diff --git a/spec/lib/saml_idp/encryptor_spec.rb b/spec/lib/saml_idp/encryptor_spec.rb
index d8d7ab74..95f789ad 100644
--- a/spec/lib/saml_idp/encryptor_spec.rb
+++ b/spec/lib/saml_idp/encryptor_spec.rb
@@ -14,15 +14,18 @@ module SamlIdp
subject { described_class.new encryption_opts }
- it 'encrypts XML' do
- raw_xml = 'bar'
- encrypted_xml = subject.encrypt(raw_xml)
- expect(encrypted_xml).not_to match 'bar'
- encrypted_doc = Nokogiri::XML::Document.parse(encrypted_xml)
- encrypted_data = Xmlenc::EncryptedData.new(encrypted_doc.at_xpath('//xenc:EncryptedData',
- Xmlenc::NAMESPACES))
- decrypted_xml = encrypted_data.decrypt(subject.encryption_key)
- expect(decrypted_xml).to eq(raw_xml)
+ SamlIdp::Encryptor::ENCRYPTION_ALGORITHMS_NS.keys.each do |encryption_algorithm|
+ it "encrypts XML with #{encryption_algorithm}" do
+ encryption_opts[:block_encryption] = encryption_algorithm
+ raw_xml = 'bar'
+ encrypted_xml = subject.encrypt(raw_xml)
+ expect(encrypted_xml).not_to match 'bar'
+ encrypted_doc = Nokogiri::XML::Document.parse(encrypted_xml)
+ encrypted_data = Xmlenc::EncryptedData.new(encrypted_doc.at_xpath('//xenc:EncryptedData',
+ Xmlenc::NAMESPACES))
+ decrypted_xml = encrypted_data.decrypt(subject.encryption_key)
+ expect(decrypted_xml).to eq(raw_xml)
+ end
end
it 'does not have a KeyName element' do
@@ -32,5 +35,15 @@ module SamlIdp
expect(encrypted_doc.remove_namespaces!.xpath('//KeyName')).to be_empty
end
+
+ context 'invalid block_encryption' do
+ it 'raises an exception' do
+ encryption_opts[:block_encryption] = 'abc123'
+
+ expect do
+ subject.encrypt('bar')
+ end.to raise_error(Xmlenc::UnsupportedError)
+ end
+ end
end
end