Commit 0cc5e7a
Changed files (4)
lib
xml
kit
crypto
spec
xml
kit
lib/xml/kit/crypto/symmetric_cipher.rb
@@ -31,8 +31,9 @@ module Xml
end
def decrypt(cipher_text)
- iv = cipher_text[0...cipher.iv_len]
- data = cipher_text[cipher.iv_len..-1]
+ iv_len = cipher.iv_len
+ iv = cipher_text[0...iv_len]
+ data = cipher_text[iv_len..-1]
default_decrypt(iv, data)
end
spec/xml/kit/crypto/symmetric_cipher_spec.rb
@@ -1,6 +1,14 @@
# frozen_string_literal: true
RSpec.describe ::Xml::Kit::Crypto::SymmetricCipher do
+ let(:key_size) do
+ hash = Hash.new(32 / 2)
+ hash['aes128-cbc'] = 16 / 2
+ hash['aes192-cbc'] = 24 / 2
+ hash['tripledes-cbc'] = 24 / 2
+ hash
+ end
+
[
'tripledes-cbc',
'aes128-cbc',
@@ -11,16 +19,51 @@ RSpec.describe ::Xml::Kit::Crypto::SymmetricCipher do
subject { described_class.new("#{::Xml::Kit::Namespaces::XMLENC}#{algorithm}", key) }
let(:key) { SecureRandom.hex(key_size[algorithm]) }
- let(:key_size) do
- hash = Hash.new(32 / 2)
- hash['aes128-cbc'] = 16 / 2
- hash['aes192-cbc'] = 24 / 2
- hash['tripledes-cbc'] = 24 / 2
- hash
- end
let(:uuid) { SecureRandom.uuid }
specify { expect(subject.decrypt(subject.encrypt(uuid))).to eql(uuid) }
end
end
+
+# Some of the ciphers do not have large keys and others have security implications if not used cor-
+# rectly. All the block ciphers normally use PKCS#5 padding, also known as standard block padding. If
+# padding is disabled, the input data must be a multiple of the cipher block length.
+ describe "decrypting something encrypted with the OpenSSL CLI" do
+ subject { described_class.new("#{::Xml::Kit::Namespaces::XMLENC}#{algorithm}", key) }
+
+ let(:encrypted_file) { Tempfile.new('aes-128-cbc').path }
+ let(:original_file) { __FILE__ }
+ let(:decrypted_file) { Tempfile.new('aes-128-cbc-decrypted').path }
+ let(:algorithm) { 'aes128-cbc' }
+ let(:key) { SecureRandom.hex(8) }
+ let(:iv) { SecureRandom.hex(8) }
+
+ before do
+ raise 'heck' unless system("openssl enc -aes-128-cbc -p -A -nosalt -in #{original_file} -out #{encrypted_file} -K #{key} -iv #{iv}")
+ raise 'heck' unless system("openssl enc -aes-128-cbc -p -d -nosalt -in #{encrypted_file} -out #{decrypted_file} -K #{key} -iv #{iv}")
+ end
+
+ specify do
+ expect(subject.decrypt(IO.read(encrypted_file))).to eql(IO.read(decrypted_file))
+ end
+ end
+
+ describe "when decrypting with the OpenSSL CLI" do
+ subject { described_class.new("#{::Xml::Kit::Namespaces::XMLENC}#{algorithm}", key) }
+
+ let(:encrypted_file) { Tempfile.new('aes-128-cbc').path }
+ let(:original_file) { __FILE__ }
+ let(:decrypted_file) { Tempfile.new('aes-128-cbc-decrypted').path }
+ let(:algorithm) { 'aes128-cbc' }
+ let(:key) { SecureRandom.hex(8) }
+ let(:iv) { SecureRandom.hex(8) }
+ let(:original_content) { IO.read(original_file) }
+
+ before do
+ IO.write(encrypted_file, subject.encrypt(IO.read(original_file)))
+ system("openssl enc -aes-128-cbc -p -d -nosalt -in #{encrypted_file} -out #{decrypted_file} -K #{key.unpack("H*")[0]} -iv #{iv.unpack("H*")[0]}")
+ end
+
+ specify { expect(IO.read(decrypted_file)).to end_with(original_content) }
+ end
end
spec/xml/kit/decryption_spec.rb
@@ -163,5 +163,42 @@ RSpec.describe Xml::Kit::Decryption do
specify { expect { subject.decrypt_node(encrypted_node) }.to raise_error(Xml::Kit::DecryptionError) }
end
+
+ context "when using the ruby-saml example" do
+ subject { described_class.new(private_keys: [OpenSSL::PKey::RSA.new(private_key_pem)]) }
+ let(:private_key_pem) do
+ <<-PEM
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDo6m+QZvYQ/xL0ElLgupK1QDcYL4f5PckwsNgS9pUvV7fzTqCH
+k8ThLxTk42MQ2McJsOeUJVP728KhymjFCqxgP4VuwRk9rpAl0+mhy6MPdyjyA6G1
+4jrDWS65ysLchK4t/vwpEDz0SQlEoG1kMzllSm7zZS3XregA7DjNaUYQqwIDAQAB
+AoGBALGR6bRBit+yV5TUU3MZSrf8WQSLWDLgs/33FQSAEYSib4+DJke2lKbI6jkG
+UoSJgFUXFbaQLtMY2+3VDsMKPBdAge9gIdvbkC4yoKjLGm/FBDOxxZcfLpR+9OPq
+U3qM9D0CNuliBWI7Je+p/zs09HIYucpDXy9E18KA1KNF6rfhAkEA9KoNam6wAKnm
+vMzz31ws3RuIOUeo2rx6aaVY95+P9tTxd6U+pNkwxy1aCGP+InVSwlYNA1aQ4Axi
+/GdMIWMkxwJBAPO1CP7cQNZQmu7yusY+GUObDII5YK9WLaY4RAicn5378crPBFxv
+Ukqf9G6FHo7u88iTCIp+vwa3Hn9Tumg3iP0CQQDgUXWBasCVqzCxU5wY4tMDWjXY
+hpoLCpmVeRML3dDJt004rFm2HKe7Rhpw7PTZNQZOxUSjFeA4e0LaNf838UWLAkB8
+QfbHM3ffjhOg96PhhjINdVWoZCb230LBOHj/xxPfUmFTHcBEfQIBSJMxcrBFAnLL
+9qPpMXymqOFk3ETz9DTlAj8E0qGbp78aVbTOtuwEwNJII+RPw+Zkc+lKR+yaWkAz
+fIXw527NPHH3+rnBG72wyZr9ud4LAum9jh+5No1LQpk=
+-----END RSA PRIVATE KEY-----
+PEM
+ end
+ let(:document) { Nokogiri::XML(raw_xml) }
+ let(:encoded) { "PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgSUQ9InBmeDUxOWI1Y2JiLWNiNmYtOTQzNS0xNjNmLWJkMzVjZTM1YzNmMCIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTQtMDYtMDRUMDI6MjI6MDJaIiBEZXN0aW5hdGlvbj0iaHR0cDovL2FwcC5tdWRhLm5vL3Nzby9jb25zdW1lIiBJblJlc3BvbnNlVG89Il9mYzRhMzRiMC03ZWZiLTAxMmUtY2FhZS03ODJiY2IxM2JiMzgiPjxzYW1sOklzc3Vlcj5odHRwczovL2FwcC5vbmVsb2dpbi5jb20vc2FtbDI8L3NhbWw6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPg0KICA8ZHM6U2lnbmVkSW5mbz48ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPg0KICAgIDxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjcnNhLXNoYTEiLz4NCiAgPGRzOlJlZmVyZW5jZSBVUkk9IiNwZng1MTliNWNiYi1jYjZmLTk0MzUtMTYzZi1iZDM1Y2UzNWMzZjAiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNzaGExIi8+PGRzOkRpZ2VzdFZhbHVlPjBTRFRrNXNYWjdoMW9YUWVRMm5YY3BLZnZoTT08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+WENPVmk4U2c0MllRS25oMWpNTWYvV0dVcDh5Q1dFQWV4UE5taVNWT0M2dUFBUGc5WWwySUt4Um1SeGczcHpVK0o5SzlTRUVEOEJWenJERTZ4VDlxV1JUbXZ1WExqemE0TndvRmFGWllIc3ZzN0FPR3l5UEJjT3Z2R3JoM2RGWmVTUzF5U2tVc3FBWW5Wck54emRkRVFZa2trRmNxQkNqZ3dnd0Z5Vlpvbkc4PTwvZHM6U2lnbmF0dXJlVmFsdWU+DQo8ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE+PGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlDR3pDQ0FZUUNDUUNOTmNRWG9tMzJWREFOQmdrcWhraUc5dzBCQVFVRkFEQlNNUXN3Q1FZRFZRUUdFd0pWVXpFTE1Ba0dBMVVFQ0JNQ1NVNHhGVEFUQmdOVkJBY1RERWx1WkdsaGJtRndiMnhwY3pFUk1BOEdBMVVFQ2hNSVQyNWxURzluYVc0eEREQUtCZ05WQkFzVEEwVnVaekFlRncweE5EQTBNak14T0RReE1ERmFGdzB4TlRBME1qTXhPRFF4TURGYU1GSXhDekFKQmdOVkJBWVRBbFZUTVFzd0NRWURWUVFJRXdKSlRqRVZNQk1HQTFVRUJ4TU1TVzVrYVdGdVlYQnZiR2x6TVJFd0R3WURWUVFLRXdoUGJtVk1iMmRwYmpFTU1Bb0dBMVVFQ3hNRFJXNW5NSUdmTUEwR0NTcUdTSWIzRFFFQkFRVUFBNEdOQURDQmlRS0JnUURvNm0rUVp2WVEveEwwRWxMZ3VwSzFRRGNZTDRmNVBja3dzTmdTOXBVdlY3ZnpUcUNIazhUaEx4VGs0Mk1RMk1jSnNPZVVKVlA3MjhLaHltakZDcXhnUDRWdXdSazlycEFsMCttaHk2TVBkeWp5QTZHMTRqckRXUzY1eXNMY2hLNHQvdndwRUR6MFNRbEVvRzFrTXpsbFNtN3paUzNYcmVnQTdEak5hVVlRcXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0R0JBTE0ydkdDaVEvdm0rYTZ2NDArVlgyemRxSEEyUS8xdkYxaWJReko1NE1KQ09WV3ZzK3ZRWGZaRmhkbTBPUE0ySXJEVTdvcXZLUHFQNnhPQWVKSzZIMHlQN000WUwzZmF0U3ZJWW1tZnlYQzlrdDNTdnovTnlySHpQaFVuSjB5ZS9zVVNYeG56UXh3Y20vOVB3QXFyUWFBM1FwUWtINTd5YkYvT29yeVBlKzJoPC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PC9kczpTaWduYXR1cmU+PHNhbWxwOlN0YXR1cz48c2FtbHA6U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIi8+PC9zYW1scDpTdGF0dXM+PHNhbWw6QXNzZXJ0aW9uIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgVmVyc2lvbj0iMi4wIiBJRD0icGZ4OTUxNmIwZjMtNDUzNi0xMGY2LWM2ZmEtOWRkNTIzZTE0OThjIiBJc3N1ZUluc3RhbnQ9IjIwMTQtMDYtMDRUMDI6MjI6MDJaIj48c2FtbDpJc3N1ZXI+aHR0cHM6Ly9hcHAub25lbG9naW4uY29tL3NhbWwyPC9zYW1sOklzc3Vlcj48c2FtbDpTdWJqZWN0PjxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBOb3RPbk9yQWZ0ZXI9IjIwMzAtMDYtMDRUMDI6Mjc6MDJaIiBSZWNpcGllbnQ9InJlY2lwaWVudCIvPjwvc2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uPjxzYW1sOkVuY3J5cHRlZElEPjx4ZW5jOkVuY3J5cHRlZERhdGEgeG1sbnM6eGVuYz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjIiB4bWxuczpkc2lnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIiBUeXBlPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNFbGVtZW50Ij48eGVuYzpFbmNyeXB0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjYWVzMTI4LWNiYyIvPjxkc2lnOktleUluZm8geG1sbnM6ZHNpZz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PHhlbmM6RW5jcnlwdGVkS2V5Pjx4ZW5jOkVuY3J5cHRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNyc2EtMV81Ii8+PHhlbmM6Q2lwaGVyRGF0YT48eGVuYzpDaXBoZXJWYWx1ZT5ZUkdFZGF2dWpSNlYwNUZsWERHbmxCK1VUWTFjak9DallkYlhKN2JBZHFURWxDTyt1eHl0aytnMWVTTGVuczhJcjlZaVBNNUorUWU5cXo0TkdORXdyNjV6aDM5L0ZJVXNMQ3BhaXQ3QjZXM2lFcmR4aVUrSUN1cUw3TCtNSmlGVHZiVG90NVdleWZvVkFnSE94Z1BodDRONlZSL3BhYzRDdFZEQ0ZBbDlEMjA9PC94ZW5jOkNpcGhlclZhbHVlPjwveGVuYzpDaXBoZXJEYXRhPjwveGVuYzpFbmNyeXB0ZWRLZXk+PC9kc2lnOktleUluZm8+DQogICA8eGVuYzpDaXBoZXJEYXRhPg0KICAgICAgPHhlbmM6Q2lwaGVyVmFsdWU+dFdQZEV1dXZmSjh3WVBhOFVUQTRvR2htRENQTjFhQzVkUUFEN0g5SkhWQm5VS3Y0UkljNEQ3SnVJem12bXlyalZGWmRGNW15K3cvUGd3dWlOVGdpOUxid01iSW5adW1HbDhlSndFblBaVXBPQ0w1dDNXbEdKbU85OVVNejZQUVNLeGlGSU1DYzcrQXlRQmpjdTEzaUxWeU5TbFQyWDMxRXBOaW5jQ3FzSldvPTwveGVuYzpDaXBoZXJWYWx1ZT4NCiAgIDwveGVuYzpDaXBoZXJEYXRhPg0KPC94ZW5jOkVuY3J5cHRlZERhdGE+PC9zYW1sOkVuY3J5cHRlZElEPjwvc2FtbDpTdWJqZWN0PjxzYW1sOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDExLTA2LTA0VDAyOjE3OjAyWiIgTm90T25PckFmdGVyPSIyMDMwLTA2LTA0VDAyOjI3OjAyWiI+PHNhbWw6QXVkaWVuY2VSZXN0cmljdGlvbj48c2FtbDpBdWRpZW5jZT5odHRwczovL3NvbWVvbmUuZXhhbXBsZS5jb20vYXVkaWVuY2U8L3NhbWw6QXVkaWVuY2U+PC9zYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24+PC9zYW1sOkNvbmRpdGlvbnM+PHNhbWw6QXV0aG5TdGF0ZW1lbnQgQXV0aG5JbnN0YW50PSIyMDE0LTA2LTA0VDAyOjIyOjAyWiIgU2Vzc2lvbk5vdE9uT3JBZnRlcj0iMjAzMC0wNi0wNVQwMjoyMjowMloiIFNlc3Npb25JbmRleD0iXzE2ZjU3MGZiYzAzMTUwMDdhMDM1NWRmZWE2YjNjNDZjIj48c2FtbDpBdXRobkNvbnRleHQ+PHNhbWw6QXV0aG5Db250ZXh0Q2xhc3NSZWY+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFjOmNsYXNzZXM6UGFzc3dvcmRQcm90ZWN0ZWRUcmFuc3BvcnQ8L3NhbWw6QXV0aG5Db250ZXh0Q2xhc3NSZWY+PC9zYW1sOkF1dGhuQ29udGV4dD48L3NhbWw6QXV0aG5TdGF0ZW1lbnQ+PC9zYW1sOkFzc2VydGlvbj48L3NhbWxwOlJlc3BvbnNlPg==" }
+ let(:raw_xml) { Base64.decode64(encoded) }
+ let(:encrypted_node) do
+ document.at_xpath('/samlp:Response/saml:Assertion/saml:Subject/saml:EncryptedID/xmlenc:EncryptedData', {
+ 'xmlenc' => 'http://www.w3.org/2001/04/xmlenc#',
+ 'saml' => 'urn:oasis:names:tc:SAML:2.0:assertion',
+ 'samlp' => 'urn:oasis:names:tc:SAML:2.0:protocol',
+ })
+ end
+
+ specify do
+ expect(subject.decrypt_node(encrypted_node).to_s).to eql('<saml:nameid format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">test@onelogin.com</saml:nameid>')
+ end
+ end
end
end
spec/spec_helper.rb
@@ -8,6 +8,7 @@ require 'bundler/setup'
require 'xml/kit'
require 'ffaker'
require 'active_support/core_ext/hash/conversions'
+require 'tempfile'
Xml::Kit.logger.level = Logger::FATAL