Comparing changes
v0.2.5
→
v0.2.6
8 commits
10 files changed
Commits
Changed files (10)
lib
saml
kit
builders
templates
locales
spec
saml
builders
lib/saml/kit/builders/templates/assertion.builder
@@ -1,7 +1,7 @@
encryption_for(xml: xml) do |xml|
xml.Assertion(assertion_options) do
xml.Issuer issuer
- signature_for(reference_id: reference_id, xml: xml) unless encrypt
+ signature_for(reference_id: reference_id, xml: xml)
xml.Subject do
xml.NameID name_id, Format: name_id_format
xml.SubjectConfirmation Method: Saml::Kit::Namespaces::BEARER do
lib/saml/kit/locales/en.yml
@@ -4,6 +4,7 @@ en:
errors:
Assertion:
expired: "must not be expired."
+ must_match_issuer: "must match entityId."
AuthnRequest:
invalid: "must contain AuthnRequest."
invalid_fingerprint: "does not match."
@@ -23,7 +24,6 @@ en:
invalid_fingerprint: "does not match."
invalid_response_to: "must match request id."
invalid_version: "must be 2.0."
- must_match_issuer: "must match entityId."
unregistered: "must originate from registered identity provider."
SPSSODescriptor:
invalid: "must contain SPSSODescriptor."
lib/saml/kit/assertion.rb
@@ -63,12 +63,12 @@ module Saml
[]
end
- private
-
def encrypted?
@xml_hash.fetch('Response', {}).fetch('EncryptedAssertion', nil).present?
end
+ private
+
def assertion
if encrypted?
decrypted = XmlDecryption.new(configuration: @configuration).decrypt(@xml_hash['Response']['EncryptedAssertion'])
lib/saml/kit/configuration.rb
@@ -12,14 +12,12 @@ module Saml
@registry = DefaultRegistry.new
@session_timeout = 3.hours
@logger = Logger.new(STDOUT)
+ @key_pairs = []
yield self if block_given?
end
def add_key_pair(certificate, private_key, password:, use: :signing)
- key_pairs.push({
- certificate: Saml::Kit::Certificate.new(certificate, use: use),
- private_key: OpenSSL::PKey::RSA.new(private_key, password)
- })
+ @key_pairs.push(KeyPair.new(certificate, private_key, password, use))
end
def generate_key_pair_for(use:, password: SecureRandom.uuid)
@@ -27,13 +25,16 @@ module Saml
add_key_pair(certificate, private_key, password: password, use: use)
end
+ def key_pairs(use: nil)
+ use.present? ? @key_pairs.find_all { |x| x.for?(use) } : @key_pairs
+ end
+
def certificates(use: nil)
- certificates = key_pairs.map { |x| x[:certificate] }
- use.present? ? certificates.find_all { |x| x.for?(use) } : certificates
+ key_pairs(use: use).flat_map(&:certificate)
end
def private_keys(use: :signing)
- key_pairs.find_all { |x| x[:certificate].for?(use) }.map { |x| x[:private_key] }
+ key_pairs(use: use).flat_map(&:private_key)
end
def encryption_certificate
@@ -54,12 +55,6 @@ module Saml
def sign?
certificates(use: :signing).any?
end
-
- private
-
- def key_pairs
- @key_pairs ||= []
- end
end
end
end
lib/saml/kit/key_pair.rb
@@ -0,0 +1,17 @@
+module Saml
+ module Kit
+ class KeyPair
+ attr_reader :certificate, :private_key
+
+ def initialize(certificate, private_key, password, use)
+ @use = use
+ @certificate = Saml::Kit::Certificate.new(certificate, use: use)
+ @private_key = OpenSSL::PKey::RSA.new(private_key, password)
+ end
+
+ def for?(use)
+ @use == use
+ end
+ end
+ end
+end
lib/saml/kit/templatable.rb
@@ -24,7 +24,8 @@ module Saml
if encrypt?
temp = ::Builder::XmlMarkup.new
yield temp
- xml_encryption = Saml::Kit::Builders::XmlEncryption.new(temp.target!, encryption_certificate.public_key)
+ signed_xml = signatures.complete(temp.target!)
+ xml_encryption = Saml::Kit::Builders::XmlEncryption.new(signed_xml, encryption_certificate.public_key)
render(xml_encryption, xml: xml)
else
yield xml
lib/saml/kit/version.rb
@@ -1,5 +1,5 @@
module Saml
module Kit
- VERSION = "0.2.5"
+ VERSION = "0.2.6"
end
end
lib/saml/kit.rb
@@ -35,6 +35,7 @@ require "saml/kit/configuration"
require "saml/kit/crypto"
require "saml/kit/default_registry"
require "saml/kit/fingerprint"
+require "saml/kit/key_pair"
require "saml/kit/logout_response"
require "saml/kit/logout_request"
require "saml/kit/metadata"
spec/saml/builders/response_spec.rb
@@ -124,5 +124,25 @@ RSpec.describe Saml::Kit::Builders::Response do
expect(result['Response']['Signature']).to be_present
expect(result['Response']['Assertion']['Signature']).to be_present
end
+
+ it 'generates a signed response and signed and encrypted assertion' do
+ subject.encrypt = true
+ subject.sign = true
+
+ result = Saml::Kit::Response.new(subject.to_xml, configuration: configuration)
+ expect(result).to be_signed
+ expect(result.assertion).to be_signed
+ expect(result.assertion).to be_encrypted
+ end
+
+ it 'generates an encrypted assertion' do
+ subject.encrypt = true
+ subject.sign = false
+
+ result = Saml::Kit::Response.new(subject.to_xml, configuration: configuration)
+ expect(result).to_not be_signed
+ expect(result.assertion).to_not be_signed
+ expect(result.assertion).to be_encrypted
+ end
end
end
spec/saml/xml_decryption_spec.rb
@@ -21,13 +21,13 @@ RSpec.describe Saml::Kit::XmlDecryption do
"xmlns:xenc"=>"http://www.w3.org/2001/04/xmlenc#",
"xmlns:dsig"=>"http://www.w3.org/2000/09/xmldsig#",
"Type"=>"http://www.w3.org/2001/04/xmlenc#Element",
- "EncryptionMethod"=> {
+ "EncryptionMethod"=> {
"Algorithm"=>"http://www.w3.org/2001/04/xmlenc#aes128-cbc"
},
"KeyInfo"=> {
"xmlns:dsig"=>"http://www.w3.org/2000/09/xmldsig#",
"EncryptedKey"=> {
- "EncryptionMethod"=>{
+ "EncryptionMethod"=>{
"Algorithm"=>"http://www.w3.org/2001/04/xmlenc#rsa-1_5"
},
"CipherData"=>{
@@ -44,5 +44,49 @@ RSpec.describe Saml::Kit::XmlDecryption do
decrypted = subject.decrypt(data)
expect(decrypted.strip).to eql(secret)
end
+
+ it 'raise an error when it cannot decrypt the data' do
+ certificate_pem, private_key_pem = Saml::Kit::SelfSignedCertificate.new(password).create
+ public_key = OpenSSL::X509::Certificate.new(certificate_pem).public_key
+ private_key = OpenSSL::PKey::RSA.new(private_key_pem, password)
+
+ cipher = OpenSSL::Cipher.new('AES-128-CBC')
+ cipher.encrypt
+ key = cipher.random_key
+ iv = cipher.random_iv
+ encrypted = cipher.update(secret) + cipher.final
+
+ data = {
+ "EncryptedData"=> {
+ "xmlns:xenc"=>"http://www.w3.org/2001/04/xmlenc#",
+ "xmlns:dsig"=>"http://www.w3.org/2000/09/xmldsig#",
+ "Type"=>"http://www.w3.org/2001/04/xmlenc#Element",
+ "EncryptionMethod"=> {
+ "Algorithm"=>"http://www.w3.org/2001/04/xmlenc#aes128-cbc"
+ },
+ "KeyInfo"=> {
+ "xmlns:dsig"=>"http://www.w3.org/2000/09/xmldsig#",
+ "EncryptedKey"=> {
+ "EncryptionMethod"=>{
+ "Algorithm"=>"http://www.w3.org/2001/04/xmlenc#rsa-1_5"
+ },
+ "CipherData"=>{
+ "CipherValue"=> Base64.encode64(public_key.public_encrypt(key))
+ }
+ }
+ },
+ "CipherData"=>{
+ "CipherValue"=> Base64.encode64(iv + encrypted)
+ }
+ }
+ }
+
+ new_private_key_pem = Saml::Kit::SelfSignedCertificate.new(password).create[1]
+ new_private_key = OpenSSL::PKey::RSA.new(new_private_key_pem, password)
+ subject = described_class.new(configuration: double(private_keys: [new_private_key]))
+ expect do
+ subject.decrypt(data)
+ end.to raise_error(OpenSSL::PKey::RSAError)
+ end
end
end