Commit fd928f7

mo <mo.khan@gmail.com>
2017-12-30 20:23:28
add specs for simple cipher.
1 parent 01a78bd
Changed files (4)
lib/xml/kit/crypto/simple_cipher.rb
@@ -9,25 +9,36 @@ module Xml
           "#{Namespaces::XMLENC}aes256-cbc" => "AES-256-CBC",
         }
 
-        def initialize(algorithm, private_key)
+        def initialize(algorithm, key)
           @algorithm = algorithm
-          @private_key = private_key
+          @key = key || cipher.random_key
         end
 
         def self.matches?(algorithm)
           ALGORITHMS[algorithm]
         end
 
+        def encrypt(plain_text)
+          cipher.encrypt
+          cipher.key = @key
+          cipher.random_iv + cipher.update(plain_text) + cipher.final
+        end
+
         def decrypt(cipher_text)
-          cipher = OpenSSL::Cipher.new(ALGORITHMS[@algorithm])
           cipher.decrypt
           iv = cipher_text[0..cipher.iv_len-1]
           data = cipher_text[cipher.iv_len..-1]
           #cipher.padding = 0
-          cipher.key = @private_key
+          cipher.key = @key
           cipher.iv = iv
           cipher.update(data) + cipher.final
         end
+
+        private
+
+        def cipher
+          @cipher ||= OpenSSL::Cipher.new(ALGORITHMS[@algorithm])
+        end
       end
     end
   end
lib/xml/kit/templates/encryption.builder
@@ -2,13 +2,13 @@ xml.EncryptedData xmlns: ::Xml::Kit::Namespaces::XMLENC do
   xml.EncryptionMethod Algorithm: symmetric_algorithm
   xml.KeyInfo xmlns: ::Xml::Kit::Namespaces::XMLDSIG do
     xml.EncryptedKey xmlns: ::Xml::Kit::Namespaces::XMLENC do
-      xml.EncryptionMethod Algorithm: "#{::Xml::Kit::Namespaces::XMLENC}rsa-1_5"
+      xml.EncryptionMethod Algorithm: asymmetric_algorithm
       xml.CipherData do
-        xml.CipherValue Base64.encode64(public_key.public_encrypt(key))
+        xml.CipherValue asymmetric_cipher_value
       end
     end
   end
   xml.CipherData do
-    xml.CipherValue Base64.encode64(iv + encrypted)
+    xml.CipherValue symmetric_cipher_value
   end
 end
lib/xml/kit/encryption.rb
@@ -2,19 +2,20 @@ module Xml
   module Kit
     class Encryption
       DEFAULT_ALGORITHM="AES-256-CBC"
-      attr_reader :public_key
+      attr_reader :asymmetric_algorithm
+      attr_reader :asymmetric_cipher_value
       attr_reader :symmetric_algorithm
-      attr_reader :key, :iv, :encrypted
+      attr_reader :symmetric_cipher_value
 
-      def initialize(raw_xml, public_key, algorithm = DEFAULT_ALGORITHM)
-        @public_key = public_key
-
-        cipher = OpenSSL::Cipher.new(algorithm)
+      def initialize(raw_xml, public_key, symmetric_algorithm = DEFAULT_ALGORITHM)
+        @symmetric_algorithm = ::Xml::Kit::Crypto::SimpleCipher::ALGORITHMS.key(symmetric_algorithm)
+        cipher = OpenSSL::Cipher.new(symmetric_algorithm)
         cipher.encrypt
-        @symmetric_algorithm = ::Xml::Kit::Crypto::SimpleCipher::ALGORITHMS.key(algorithm)
-        @key = cipher.random_key
-        @iv = cipher.random_iv
-        @encrypted = cipher.update(raw_xml) + cipher.final
+        key = cipher.random_key
+        @symmetric_cipher_value = Base64.encode64(cipher.random_iv + cipher.update(raw_xml) + cipher.final)
+
+        @asymmetric_algorithm = "#{::Xml::Kit::Namespaces::XMLENC}rsa-1_5"
+        @asymmetric_cipher_value = Base64.encode64(public_key.public_encrypt(key))
       end
 
       def to_xml(xml: ::Builder::XmlMarkup.new)
spec/xml/crypto/simple_cipher_spec.rb
@@ -0,0 +1,25 @@
+RSpec.describe ::Xml::Kit::Crypto::SimpleCipher do
+  [
+    "tripledes-cbc",
+    "aes128-cbc",
+    "aes192-cbc",
+    "aes256-cbc",
+  ].each do |algorithm|
+    describe algorithm 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(16)
+        hash['aes128-cbc'] = 8
+        hash['aes192-cbc'] = 12
+        hash["tripledes-cbc"] = 12
+        hash
+      end
+      let(:uuid) { SecureRandom.uuid }
+
+      it 'encrypts/decrypts' do
+        expect(subject.decrypt(subject.encrypt(uuid))).to eql(uuid)
+      end
+    end
+  end
+end