Commit a080bfe
Changed files (2)
lib
saml
spec
lib/saml/kit/xml_decryption.rb
@@ -1,10 +1,10 @@
module Saml
module Kit
class XmlDecryption
- attr_reader :private_key
+ attr_reader :private_keys
def initialize(configuration: Saml::Kit.configuration)
- @private_key = configuration.private_keys(use: :encryption).last
+ @private_keys = configuration.private_keys(use: :encryption)
end
def decrypt(data)
@@ -19,7 +19,16 @@ module Saml
def symmetric_key_from(encrypted_data)
encrypted_key = encrypted_data['KeyInfo']['EncryptedKey']
cipher_text = Base64.decode64(encrypted_key['CipherData']['CipherValue'])
- to_plaintext(cipher_text, private_key, encrypted_key["EncryptionMethod"]['Algorithm'])
+ attempts = private_keys.count
+ private_keys.each do |private_key|
+ begin
+ attempts -= 1
+ return to_plaintext(cipher_text, private_key, encrypted_key["EncryptionMethod"]['Algorithm'])
+ rescue OpenSSL::PKey::RSAError => error
+ Saml::Kit.logger.error(error)
+ raise if attempts.zero?
+ end
+ end
end
def to_plaintext(cipher_text, symmetric_key, algorithm)
spec/saml/xml_decryption_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe Saml::Kit::XmlDecryption do
expect(decrypted.strip).to eql(secret)
end
- it 'raise an error when it cannot decrypt the data' do
+ it 'attemps to decrypt with each encryption keypair' 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)
@@ -81,6 +81,49 @@ RSpec.describe Saml::Kit::XmlDecryption do
}
}
+ _, other_private_key_pem = Saml::Kit::SelfSignedCertificate.new(password).create
+ other_private_key = OpenSSL::PKey::RSA.new(other_private_key_pem, password)
+
+ subject = described_class.new(configuration: double(private_keys: [other_private_key, private_key]))
+ decrypted = subject.decrypt(data)
+ expect(decrypted.strip).to eql(secret)
+ end
+
+ it 'raise an error when it cannot decrypt the data' do
+ certificate_pem, _ = Saml::Kit::SelfSignedCertificate.new(password).create
+ public_key = OpenSSL::X509::Certificate.new(certificate_pem).public_key
+
+ 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]))