Commit 5ffb1f7

mokha <mo@mokhan.ca>
2019-01-25 01:32:23
update soap spec to use same symmetric key in EncryptedKey and EncryptedData section
1 parent f970a50
Changed files (6)
lib/xml/kit/crypto/symmetric_cipher.rb
@@ -14,7 +14,7 @@ module Xml
 
         attr_reader :algorithm, :key, :padding
 
-        def initialize(algorithm, key = nil, padding = nil)
+        def initialize(algorithm = DEFAULT_ALGORITHM, key = nil, padding = nil)
           @algorithm = algorithm
           @key = key || cipher.random_key
           @padding = padding
@@ -41,6 +41,10 @@ module Xml
           result[0...-padding_size]
         end
 
+        def to_s
+          algorithm
+        end
+
         protected
 
         def default_decrypt(initialization_vector, data)
lib/xml/kit/templates/encryption.builder
@@ -1,7 +1,7 @@
 # frozen_string_literal: true
 
 xml.EncryptedData xmlns: ::Xml::Kit::Namespaces::XMLENC do
-  xml.EncryptionMethod Algorithm: symmetric_algorithm
+  xml.EncryptionMethod Algorithm: symmetric_algorithm.to_s
   render key_info, xml: xml
   xml.CipherData do
     xml.CipherValue symmetric_cipher_value
lib/xml/kit/templatable.rb
@@ -27,12 +27,12 @@ module Xml
         ::Xml::Kit::EncryptedKey.new(id: id, public_key: public_key, key: key).to_xml(xml: xml)
       end
 
-      def encryption_for(xml:, key_info: nil, &block)
+      def encryption_for(*args, &block)
         ::Xml::Kit.deprecate('encryption_for is deprecated. Use encrypt_data_for instead.')
-        encrypt_data_for(xml: xml, key_info: key_info, &block)
+        encrypt_data_for(*args, &block)
       end
 
-      def encrypt_data_for(xml:, key_info: nil)
+      def encrypt_data_for(xml:, key_info: nil, symmetric_cipher: Crypto::SymmetricCipher.new)
         return yield xml unless encrypt?
 
         temp = ::Builder::XmlMarkup.new
@@ -40,6 +40,7 @@ module Xml
         ::Xml::Kit::Encryption.new(
           signatures.complete(temp.target!),
           encryption_certificate.public_key,
+          symmetric_algorithm: symmetric_cipher,
           key_info: key_info
         ).to_xml(xml: xml)
       end
spec/fixtures/soap.builder
@@ -3,12 +3,12 @@ xml.instruct!
 xml.Envelope xmlns: "http://schemas.xmlsoap.org/soap/envelope/" do
   xml.Header do
     xml.Security mustUnderstand: '1' do
-      encrypt_key_for(xml: xml, id: key_id, public_key: encryption_key_pair.public_key, key: SecureRandom.hex(32))
+      encrypt_key_for(xml: xml, id: key_id, public_key: encryption_key_pair.public_key, key: symmetric_key)
       xml.BinarySecurityToken ''
     end
   end
   xml.Body xmlns: 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd', Id: id  do
-    encrypt_data_for xml: xml, key_info: body_key_info do |xml|
+    encrypt_data_for xml: xml, key_info: body_key_info, symmetric_cipher: symmetric_cipher do |xml|
       xml.EncryptMe do
         xml.Secret "secret"
       end
spec/support/soap.rb
@@ -15,6 +15,14 @@ class Soap
     @template_path = File.join(__dir__, '../fixtures/soap.builder')
   end
 
+  def symmetric_key
+    symmetric_cipher.key
+  end
+
+  def symmetric_cipher
+    @symmetric_cipher ||= ::Xml::Kit::Crypto::SymmetricCipher.new
+  end
+
   def key_id
     'EK-E2C32E59F27A1320A215468956686717'
   end
spec/xml/kit/soap_spec.rb
@@ -8,6 +8,18 @@ RSpec.describe Soap do
 
     specify { expect(result['Envelope']).to be_present }
     specify { expect(result['Envelope']['Header']).to be_present }
+    specify do
+      cipher_value = result['Envelope']['Header']['Security']['EncryptedKey']['CipherData']['CipherValue']
+      symmetric_key = subject.encryption_key_pair.private_key.private_decrypt(Base64.decode64(cipher_value))
+      expect(symmetric_key).to eql(subject.symmetric_key)
+
+      algorithm = result['Envelope']['Body']['EncryptedData']['EncryptionMethod']['Algorithm']
+      cipher_value = result['Envelope']['Body']['EncryptedData']['CipherData']['CipherValue']
+      result = ::Xml::Kit::Crypto::SymmetricCipher.new(algorithm, symmetric_key).decrypt(Base64.decode64(cipher_value))
+      hash = Hash.from_xml(result)
+      expect(hash['EncryptMe']['Secret']).to eql('secret')
+    end
+
     specify { expect(result['Envelope']['Body']).to be_present }
   end
 end