Commit dd06fac

mo <mo.khan@gmail.com>
2017-11-23 04:12:28
add spec for xml decryption.
1 parent 24032d2
Changed files (2)
lib/saml/kit/cryptography.rb
@@ -7,33 +7,16 @@ module Saml
         @private_key = private_key
       end
 
-      #{
-        #"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"=>"" }
-            #}
-          #},
-          #"CipherData"=>{ "CipherValue"=>"" }
-        #}
-      #}
       def decrypt(data)
         encrypt_data = data['EncryptedData']
-        symmetric_key = retrieve_symmetric_key(encrypt_data, private_key)
-        node = Base64.decode64(encrypt_data["CipherData"]["CipherValue"])
-        retrieve_plaintext(node, symmetric_key, encrypt_data["EncryptionMethod"]['Algorithm'])
+        symmetric_key = retrieve_symmetric_key(encrypt_data)
+        cipher_text = Base64.decode64(encrypt_data["CipherData"]["CipherValue"])
+        retrieve_plaintext(cipher_text, symmetric_key, encrypt_data["EncryptionMethod"]['Algorithm'])
       end
 
       private
 
-      def retrieve_symmetric_key(encrypted_data, private_key)
+      def retrieve_symmetric_key(encrypted_data)
         encrypted_key = encrypted_data['KeyInfo']['EncryptedKey']
         cipher_text = Base64.decode64(encrypted_key['CipherData']['CipherValue'])
         retrieve_plaintext(cipher_text, private_key, encrypted_key["EncryptionMethod"]['Algorithm'])
@@ -41,20 +24,26 @@ module Saml
 
       def retrieve_plaintext(cipher_text, symmetric_key, algorithm)
         case algorithm
-          when 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc' then cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').decrypt
-          when 'http://www.w3.org/2001/04/xmlenc#aes128-cbc' then cipher = OpenSSL::Cipher.new('AES-128-CBC').decrypt
-          when 'http://www.w3.org/2001/04/xmlenc#aes192-cbc' then cipher = OpenSSL::Cipher.new('AES-192-CBC').decrypt
-          when 'http://www.w3.org/2001/04/xmlenc#aes256-cbc' then cipher = OpenSSL::Cipher.new('AES-256-CBC').decrypt
-          when 'http://www.w3.org/2001/04/xmlenc#rsa-1_5' then rsa = symmetric_key
-          when 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' then oaep = symmetric_key
+        when 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'
+          cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').decrypt
+        when 'http://www.w3.org/2001/04/xmlenc#aes128-cbc'
+          cipher = OpenSSL::Cipher.new('AES-128-CBC').decrypt
+        when 'http://www.w3.org/2001/04/xmlenc#aes192-cbc'
+          cipher = OpenSSL::Cipher.new('AES-192-CBC').decrypt
+        when 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
+          cipher = OpenSSL::Cipher.new('AES-256-CBC').decrypt
+        when 'http://www.w3.org/2001/04/xmlenc#rsa-1_5'
+          rsa = symmetric_key
+        when 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p'
+          oaep = symmetric_key
         end
 
         if cipher
-          iv_len = cipher.iv_len
-          data = cipher_text[iv_len..-1]
-          cipher.padding, cipher.key, cipher.iv = 0, symmetric_key, cipher_text[0..iv_len-1]
-          assertion_plaintext = cipher.update(data)
-          assertion_plaintext << cipher.final
+          data = cipher_text[cipher.iv_len..-1]
+          cipher.padding = 0
+          cipher.key = symmetric_key
+          cipher.iv = cipher_text[0..cipher.iv_len-1]
+          cipher.update(data) + cipher.final
         elsif rsa
           rsa.private_decrypt(cipher_text)
         elsif oaep
spec/saml/cryptography_spec.rb
@@ -0,0 +1,48 @@
+require 'spec_helper'
+
+RSpec.describe Saml::Kit::Cryptography do
+  describe "#decrypt" do
+    let(:secret) { FFaker::Movie.title }
+    let(:password) { FFaker::Movie.title }
+
+    it 'decrypts 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)
+          }
+        }
+      }
+      subject = described_class.new(private_key)
+      decrypted = subject.decrypt(data)
+      expect(decrypted.strip).to eql(secret)
+    end
+  end
+end